Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Round tuits via Text::Autoformat or other ways

by sg (Pilgrim)
on Sep 23, 2007 at 22:51 UTC ( [id://640622]=perlquestion: print w/replies, xml ) Need Help??

sg has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

Any suggestions for algorithms implementable in perl to create round tuits? Input would be a string; algorithm attempts to lay it out in a circle and displays the best possible arrangement.

It's been said ever so often by many an expert that in ol' plain text one neer can get a round tuit, but just look here
Would help if algorithm can give the author clues regarding where to add or remove words, where to use longer or shorter or hyphenatable words. (The longer the message, the more circular the appearance of the output is likely to be.) Would help to output a numerical measure of the circularness of the output.

Since Damian (Conway) asks for tuits in his interview, it would help if the solution used his Text::Autoformat!

Besides algorithms, any suggestions for texts for potential tuits?

Incidentally, the first time I saw the word tuit was a few days ago while reading Damian's interview cited above. I then looked for "tuit" at www.m-w.com (doesn't exist!) and googled for info on it. I found a fake history of tuits and a boring tuit.

Also, in the history of tuits I came across an interesting British expression that I had never heard before, viz., "pull your finger out": "This round ‘Tuit’ was a sign from her people and her son, Tuitkharmen, that she needed to pull her finger out and finish the project."

Replies are listed 'Best First'.
Re: Round tuits via Text::Autoformat or other ways
by liverpole (Monsignor) on Sep 24, 2007 at 01:49 UTC
    Hi sg,

    I was going to suggest the "mathematical approach", but when I finished coding it, saw that roboticus had "beat me to the punch".  So, at least one other person interpreted your question the same way that I did :-)

    Here's my solution:

    #!/usr/bin/perl -w # Strict use strict; use warnings; use Data::Dumper; # User defined my $text = " It's been said ever so often by many an expert that in ol' plain text one neer can get a round tuit, but just look here "; # Main program $text =~ s/(?<!\s) (?!\s)/@/gms; # Turn inner spaces into +'@' print "Debug1> text = [$text]\n"; # Show text $text =~ s/\s+//; # Strip all other spaces $text =~ s/\n/@/gs; # Convert newlines to '@' my @text = grep { /\S/ms } split //, $text; # Split text into charact +ers # Find the mass of the diamond my $mass = (my $temp = $text) =~ s/\S/./g; print "Debug2> mass = [$mass]\n"; # Circle mass 'm' = pi * r^2, so the radius 'r' = sqrt(m / pi) my $radius = sqrt($mass / 3.14159265358); print "Debug3> radius = $radius\n"; # Format the text into a circle, my $circle = ""; my $aspect = 1.0; for (my $row = -($radius + 10); $row <= ($radius + 10); $row++) { for (my $col = -($radius + 10); $col <= ($radius + 10); $col++) { my $char = " "; if (($aspect * $row) ** 2 + $col ** 2 <= $aspect * ($radius ** + 2)) { $char = shift @text || '*'; } $circle .= ($char eq '@'? ' ': $char); } $circle .= "\n"; } # Show the resulting circle print "$circle\n"; __END__ Output: Debug1> text = [ It's been@said ever@so@often by@many@an@expert that@in@ol'@plain@text one@neer@can@get@a round@tuit,@but just@look here ] Debug2> mass = [120] Debug3> radius = 6.18038723238067 It's be en said e ver so ofte n by many a n expert tha t in ol' pla in text one neer can get a round tu it, but ju st look here

    What the above solution boils down to is this:  count up the number of characters in the original text, excluding spaces which are outside of the "block" of text.  Calculate the "mass" (which in your case is 120), and then use it to find the characters which are within the circle.

    You can test the veracity of this solution by changing the text.

    For example, if you choose $text to be:

    my $text = " This document is intended to give you a quick overview of the Perl programming language, along with pointers to further documentation. It is intended as a \"bootstrap\" guide for those who are new to the language, and provides just enough information for you to be able to read other peoples' Perl and understand roughly what it's doing, or write your own simple scripts. This introductory document does not aim to be complete. It does not even aim to be entirely accurate. In some cases perfection has been sacrificed in the goal of getting the general idea across. You are *strongly* advised to follow this introduction with more information from the full Perl manual, the table of contents to which can be found in perltoc. ";

    then you'll get a nice, circular output of:

    This docume nt is intended to give you a quic k overview of the Per l programming language, along with pointers to further documentation. It is intended as a "bootstrap " guide for those who are ne w to the language, and provid es just enough information fo r you to be able to read other peoples' Perl and understand roughly what it's doing, or wr ite your own simple scripts. This introductory document doe s not aim to be complete. It d oes not even aim to be entirel y accurate. In some cases per fection has been sacrificed i n the goal of getting the ge neral idea across. You are *strongly* advised to foll ow this introduction with more information from the full Perl manual, the table of conte nts to which can be found in p erltoc.

    You can vary $aspect to change the aspect ratio of the circle as well.  For example, with $aspect = 1.7, the last example looks even more "circular":

    This docume nt is intended to g ive you a quick overview of the Perl programming lan guage, along with pointers to f urther documentation. It is intend ed as a "bootstrap" guide for those who are new to the language, and pro vides just enough information for you to be able to read other peoples' Perl and understand roughly what it's doing, or write your own simple scripts. This introductory document does not aim to b e complete. It does not even aim to be entirely accurate. In some cases perfec tion has been sacrificed in the goal of getting the general idea across. You are *strongly* advised to follo w this introduction with more in formation from the full Perl manual, the table of conte nts to which can be fo und in perltoc.

    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      liverpole:

      ++ This is one of those times I wish I could double ++ a post. I only beat you to the punch 'cause you actually *did* it. It was an interesting enough problem that I could've done it. But I wouldn't have an answer until tomorrow... ;^)

      (Especially as I would've wasted my time on a recursive backtrack to "optimize" the circle, but your results show that it's unneeded.)

      --Roboticus

Re: Round tuits via Text::Autoformat or other ways
by roboticus (Chancellor) on Sep 24, 2007 at 00:56 UTC
    sq:

    I'd count the letters to find the expected area, then get the radius. (Keep in mind the aspect ratio of your character cells...ellipses (pun intended) might be better to work with.

    Then use your trig relationships to compute the "best" number of characters in each line. You might then use a recursive backtracking algorithm with a simple heuristic to fit the words to the lines as good as possible.

    That's how I'd start it, were I to do it.

    ...Roboticus

Re: Round tuits via Text::Autoformat or other ways
by kyle (Abbot) on Sep 24, 2007 at 02:36 UTC

    As a point of interest to monks trying to solve this, the dimensions of a character in the <code> font on my screen are: 7 pixels wide, 12 pixels from baseline to baseline (that's counting from the first pixel below the baseline to the first pixel above the baseline of the next line). So a square on screen is 12x7 in characters. I got these numbers by zooming in on a screen shot. YMMV.

    ############ ############ ############ ############ <-- 12x7 ############ ############ ############

    If I were trying to write this, I'd probably go a brute force route first. Count the characters, estimate the size of a circle that would encompass them, and then start with a circle somewhat larger than that. I'd loop over circles of progressively smaller sizes. At each size, I'd try to break the lines to (handwave ahead) fit the edges of the circle and measure how close I get. Whatever formatting gets closest wins. I'd be tempted to insert an extra space between some words to get the edges to come out right (as with fully justified text).

Re: Round tuits via Text::Autoformat or other ways
by sg (Pilgrim) on Sep 26, 2007 at 01:06 UTC

    How about this as a goal?:

    This document is intended to give you a quick overview of the Perl pro- gramming language, along with pointers to further documentation. It is intended as a "bootstrap" guide for those who are new to the language, and pro- vides just enough information for you to be able to read other peoples' Perl and under- stand roughly what it's doing, or write your own simple scripts. This introductory document does not aim to be complete. It does not even aim to be entirely accurate. In some cases perfection has been sacrificed in the goal of getting the general idea across. You are *strongly* advised to follow this introduction with more information from the full Perl manual, the table of contents to which can be found in perltoc.

    I made the above by hand-tweaking the output of a code. Roboticus' response gave me a starting point, Liverpole's response gave me encouragement that a solution is possible, and Kyle's response helped me quantify a parameter in the solution: Thanks. Below is some of the code I came up with and its (non-tweaked) output.

    The solution given here does not break up words arbitrarily -- it uses grammatically correct (as per TeX) hyphenation.

    Raw output from the code:

    The tuit as is after 1 adjusts: It's been said ever so often by many an expert that in ol' plain text one neer can get a round tuit, but just look here The tuit as is after 1 adjusts: This docu- ment is intended to give you a quick overview of the Perl programming lan- guage, along with pointers to further documentation. It is intend- ed as a "bootstrap" guide for those who are new to the language, and pro- vides just enough information for you to be able to read other peoples' Perl and understand roughly what it's doing, or write your own simple scripts. This intro- ductory document does not aim to be com- plete. It does not even aim to be entire- ly accurate. In some cases perfection has been sacrificed in the goal of get- ting the general idea across. You are *strongly* advised to follow this introduction with more informa- tion from the full Perl manu- al, the table of contents to which can be found in perltoc.

    Note: Code that generated the starting point for the first of the three figures of this post is not included. The second and third figures are raw outputs from the code given in this post.

      sq:

      ++ Very nice!

      While reviewing your code and examples, I had a couple of thoughts:

      First, I'd preferentially add extra spaces after punctuation characters if any are on the line. I think people are used to seeing a bit more space after punctuation.

      Secondly, you might have a table of common contractions that you can swap in and out as needed (e.g., "It's" ==> "It is", "Doesn't" ==> "Does not", etc.) That might give you enough flex to get your circles even better.

      Finally, I'm going to have to try the code out, as the aspect ratio is still a little tall & thin on my monitor. ;^)

      ...roboticus

        Regarding the third point, I had found that when $width_to_height = 1/1.9, the code is unstable (perhaps because it exposes a bug in Text::Autoformat; try with $iterations_limit = 4) and so I did not experiment too much on aspect ratio. However, since your post, I have found that values of $width_to_height smaller than 1/1.9, e.g., 1/2.05, work and yeild more circular looking outputs.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://640622]
Approved by Joost
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (8)
As of 2024-04-19 08:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found