Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Triangle Golf

by nashdj (Friar)
on Apr 24, 2001 at 14:23 UTC ( [id://75004]=CUFP: print w/replies, xml ) Need Help??

A friend of mine recently had an assignment where he had to split up a text file and print it out as a triangle. Of course this was in "c" and so, just because I could I had to see just how simple it would be in perl. The idea is to take a ctriangle.txt file like
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
and end up centered over 80 chars
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
The same principle applies to any text file, basically splitting words only on spaces or new lines
My best shot was 132 chars (\n inc). I especially like the new trick I learnt.
/[ ]+/
Which matches space/new line combinations.

Well this is the best I could do, after staring at it for half an hour it wasnt getting any shorter.

open F,"ctriangle.txt";sub n{print " "x(40-$r/2)."$x\n"};for(split/[ ]+/,join'',<F>){$c=$r,n,$x=''if( $r=length($x.=" $_"))>$c}n
- nashdj

Update:
With jeroenes idea, if I undef $/ by assigning it undef from an unused variable (not pretty but we're talking size) its down to 128 chars.

open F,"ctriangle.txt";sub n{print " "x(40-$r/2)."$x\n"};$/=$w;$_=<F>; for(split){$c=$r,n,$x=''if( $r=length($x.=" $_"))>$c}n

Replies are listed 'Best First'.
Re: Triangle Golf
by jeroenes (Priest) on Apr 24, 2001 at 15:53 UTC
    Instead of
    split /[ ]+/, join '', <F>
    You can also say: split /\s+/, join '', <F> or
    undef $/; $_=<F>; split

    Saves Just Another Character
    "We are not alone"(FZ)

Re: Triangle Golf
by jmcnamara (Monsignor) on Apr 24, 2001 at 17:14 UTC

    This was attempt to see if using format() would be shorter. It wasn't. It does use some of Perl's dustier artifacts however:
    #!/usr/bin/perl -wall -00n use strict; END{ @_=shift@F; while(@F){ $_=shift @F; $_.=' '.shift@F while(length$_<=length$_[-1]&&@F); push@_,$_ } formline(('@'.('|'x80)."\n")x@_,@_); print $^A }


    Update: Using MeowChow's regex this can be reduced to 89 chars + 6 command line switches. I'm not proud of this:
    #!/usr/bin/perl -w -00nal use strict; END{ $_="@F "; @F=1; formline'@'.('|'x80)."\n",$&and@F=length$&while/.{1,@F}.*? /g; print$^A }


    John.
    --

Re: Triangle Golf
by xtrem (Novice) on Apr 24, 2001 at 19:32 UTC
    116 with newlines (by wc)
    @ARGV="ctriangle.txt"; sub n{print$"x(40-$r/2)."$x\n"} for(map{split}<>){$c=$r,n,$x=''if($r=length($x.=" $_"))>$c}n
Re: Triangle Golf
by MeowChow (Vicar) on Apr 24, 2001 at 22:29 UTC
    $c=(@ARGV,$/)='ctriangle.txt';$_=<>.$";y/ / /s;print$"x(40-($c=length$&)/2),"$&\n"while/.{1,$c}.*? /g
    102, including the newline ;)

    update: changed two ' ' to $", saving an additional two characters - liberally aped from jeroenes node :-)

    update2: shuffled the $/ assignment into the list assignment, saving another extra char.

       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
      Here's some variations on MeowChow's idea above:
      a perfectly respactable program, about 140 chars (after the #!.../):
      #!/usr/local/bin/perl -ln0777 $\ =' '; $c = 0; s/^\s+//; s/\s+/ /gs; while ( s/(.{$c,}?. |.+$)// ) { print " " x (40 - ($c = 1 + length $1) / 2), $1 }
      > triangle.pl a.txt w.txt
      a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a The same principle applies to any text file, basically splitting words only on spaces or new lines
      a one-liner, 74 chars (+6 extra flag chars):
      > perl -ln0777we '$c=0;s/\s+/ /sg;print" "x(40-($c=length$1)/2),$1 whi +le s/(.{$c,}?. |.+$)//' a.txt w.txt a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a The same principle applies to any text file, basically splitting words only on spaces or new lines
      and pretty well golfed, 66 chars (+6 extra flag chars):
      > perl -ln0777e's/\s+/ /sg;print$"x(40-($c=length$&)/2),$&while s/.{0$ +c,}?. |.+$//' a.txt w.txt a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a The same principle applies to any text file, basically splitting words only on spaces or new lines > perl -ln0777e's/\s+/ /sg;print$"x(40-($c=length$&)/2),$&while s/.{0$ +c,}?. |.+$//' w.txt a.txt The same principle applies to any text file, basically splitting words only on spaces or new lines a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
      p
        Very nice paring down, I especially like the conversion from a greedy expression to the minimal one you use, in order to avoid defining $c. Further reduction gives:
        perl -ln0e's/\s+/ /g;print$"x(40-($c=length$&)/2),$&while/.{0$c,}? |.* +/g' ...
        61 chars of code plus 3 modifier chars.
           MeowChow                                   
                       s aamecha.s a..a\u$&owag.print
Re: Triangle Golf
by japhy (Canon) on Apr 24, 2001 at 19:13 UTC
    I offer, at 118 (not counting newlines):
    @ARGV='ctriangle.txt';sub n{print " "x(40-$r/2).$x.$\};$/=$w;$_=<>; ($r=length($x.=" $_"))>$=and $==$r,n,$x=''for split;n


    japhy -- Perl and Regex Hacker

      The above didn't work for me. $\ is undefined by default so the newline doesn't print and $= is 60 by default so the tests fail. This is the best fix I could come up with, unfortunately with one extra character:

      @ARGV='ctriangle.txt';sub n{print " "x(40-$r/2)."$x\n"};$/=$w;$_=<>; ($r=length($x.=" $_"))>$/and $/=$r,n,$x=''for split;n;
        I'm sorry. I posted the code without testing it. I had meant $/ instead of $\, but I see that wouldn't have worked. Sorry about that.

        japhy -- Perl and Regex Hacker
Re: Triangle Golf
by jeroenes (Priest) on Apr 25, 2001 at 02:13 UTC
    Works not on words, but 114 char:
    @ARGV="ctriangle.txt"; sub n{print$"x(40-$r),@b,$/} @a=map{split}<>;$,=$";while($r++<@a){@b=splice@a,0,$r;n}$r--,n
    "We are not alone"(FZ)
    Update: Most of this is just an adaption of the other code in this nice thread, including the $". I like xterm's idea of map{split}<> very much I must say. But the '$,' was my own creativity....

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://75004]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (7)
As of 2024-04-19 10:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found