Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Round tuits via Text::Autoformat or other ways

by sg (Pilgrim)
on Sep 26, 2007 at 01:06 UTC ( #641072=note: print w/replies, xml ) Need Help??


in reply to Round tuits via Text::Autoformat or other ways

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.

#!/usr/bin/perl BEGIN {(*STDERR = *STDOUT) || die;} use diagnostics; use warnings; use strict; $| = 1; use Text::Autoformat qw(autoformat break_TeX); #-------------------------------------------- # Configuration # Since vertical spacing is fixed (meaning we do not have # the option, at least in this release, of using double # spaced or 1.5 spaced lines) all computation is done in # units of vertical spacing. So we need the width to # height ratio. my $width_to_height = 5/9; # End configuration #-------------------------------------------- my $iterations_limit = 10; my $pi = 3.1412; my %taf_options = ( left => 1, #right => $width, justify => 'full', break => break_TeX, #case => 'sentence ', #widow => 1, ); my @messages = (); push @messages, <<EOF; 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 EOF push @messages, <<EOF; 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. EOF for (@messages) { tuit_top_down_approach($_, 0); #tuit_dual_approach($_); } sub tuit_top_down_approach { my ($message, $pedastal) = @_; $message = message_as_line($message); my ($radius, @slab_widths) = quantify_circle($message); my @lines = (); my $adjust = -1; my $adjust_increment = 1; my $original_message = $message; while(length $message > $slab_widths[0]) { $adjust += $adjust_increment; @lines = (); $message = $original_message; @lines = extract_top_down($original_message, $adjust, 1, \@sla +b_widths); $message = $lines[-1]; chomp $message; if($adjust >= $iterations_limit) { $adjust = 1; $adjust_increment = -1; } if($adjust <= -$iterations_limit) { last; } $pedastal and last; } align_tuit(\@lines); print "\nThe tuit as is after $adjust adjusts:\n"; print @lines, "\n\n"; } sub message_as_line { my $message = shift; $message =~ s/^\s+//gm; $message =~ s/\s+$//gm; $message =~ s/-\n//g; $message =~ s/\n/ /g; $message =~ s/\s\s+/ /g; return $message; } sub quantify_circle { my $message = shift; my $count = () = $message =~ m/./g; my $area = $count * $width_to_height; my $radius = sqrt ($area / $pi); my @slab_widths = (); for (- int $radius .. -1) { push @slab_widths, int (2 * (sqrt (($radius * $radius) - ($_ * $_ +)))/$width_to_height + 0.5); } push @slab_widths, (int ($radius * 2 / $width_to_height + 0.5)), re +verse @slab_widths; if(0) { my $check = int ($radius * 2 / $width_to_height + 0.5); for (@slab_widths) { $check += 2 * $_; } my $layers = int $radius; print "count:$count, area:$area, radius:$radius, layers=$layers, ch +eck=$check,\n"; print "slab widths:\n@slab_widths,\n"; } return $radius, @slab_widths; } sub extract_top_down { my ($message, $adjust, $widow, $slabs) = @_; # following overrides the global one my %taf_options = ( left => 1, #right => $width, justify => 'full', break => break_TeX, #case => 'sentence ', widow => 1, ); my @lines = (); for my $width (@{$slabs}) { my $foo = $width + $adjust; $foo > 0 or $foo = 2; $taf_options{right} = $foo; ($widow) and $taf_options{widow} = $foo - 1; my $formatted = autoformat $message, {%taf_options}; if(!($formatted =~ s/^([^\n]+\n)(.+\n)$/$2/s)) { $message = $formatted; last; } push @lines, $1; $message = message_as_line($formatted); } push @lines, "$message\n"; return @lines; } sub align_tuit { my $lines = shift; for (@{$lines}) { $_ = " "x(40 - 0.5 * length($_)) . $_; } } __END__

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.

Replies are listed 'Best First'.
Re^2: Round tuits via Text::Autoformat or other ways
by roboticus (Chancellor) on Sep 26, 2007 at 21:02 UTC
    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: note [id://641072]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (2)
As of 2022-11-26 12:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?