Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Triangle Golf

by nashdj (Friar)
on Apr 24, 2001 at 14:23 UTC ( #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

Comment on Triangle Golf
Select or Download Code
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 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 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 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
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? | Other CB clients
Other Users?
Others lurking in the Monastery: (12)
As of 2014-10-21 18:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (106 votes), past polls