|
|
This was not the easiest of templates to fit things in, in particular,
there were all sorts of holes in horrid places to work with (or work
around, if you prefer). The runs, such as they were were often not long
enough to do useful things with them, however, entries were produced,
and they did do interesting things.
The entries as submitted were from:
Matthew Byng-Maddick (non-entry)
Phil Kendall [2]
Andrew Savige [2] [3] [4] [5] [6]
Pete Clay
The winner, though it's a close one between Andrew's
snowscape and Pete's single entry, is the PPM snowflake.
The entries can all be downloaded from here
as a .tar.gz, including the test programme that was used to verify the entries.
Matthew Byng-Maddick
Back to top
Matthew B-M opened the competition with this single snowscape, in the hope of
getting people to enter and produce interesting solutions. This was an idea
that was brought up at a london.pm
social meeting just before the competition was posted. This does, of course,
not count as a real entry, due to him having judged the competition.
Requirements: ANSI Terminal
sub l{$
r[-1]=~ s/./-/g
;a( 2,$d );a(4,"/$e\\") ;a(3 ,$f
);a(5,$u.$e. "".$ u."",1);for(
@t){$p="(.{" .$_. "}";$r[-5]=~
s, $p.) .,$ 1. "." ,ex; $r
[0- $_] =~s; $p )... ;$1 .""
."/$u" .qq/\\/;xe ,1 for(2..4)} $_=$z.
"" .join"\n",@r;print;sleep$|}sub r{
int(rand$_[0])}$|=1;$u=$";$e="_"x5;$a=$u."o";$b="o";
;sub a{;substr $r[-$_[0 ]],$h,7, $_[1]}sub t{t(
01) if!@_;$ k=$a;$ a=$b;$ b=$k;$r [$_
-01] =~s/$a/r( 012)?$a: $b.""/eg for(1..$r )}$b
.=$u;$z="\e[H\e[J";($r,$c)=split/\s/,`stty${u}size`;
$v =$"x$c;$h=r($c-7);@t=map{r($c- 3)
}(0..r (9));$k=$b ;$ k=~s/\s//; for(01
..$ r){ ($r[ $_ -1]= $v) =~#
s, \s,r (30 )? $": $k#" o"
,xeg}($f=$d= "|". "$u#$u+$u|")
=~y/#/+/;for (0.. $r){l;t;@r=(
$v, @r); pop@r}$r[-6]=" Let" .$"
."it$u" ."snow"
;l; $p;
| |
This prints a snowscape with a house and some trees. The snow falls gently,
occasionally being pertured from side to side as it goes. It's a fairly
simple program once you see it having been reformatted and spaced out
sensibly. It calls `stty size` to find out how big it's supposed to be, and
then fills the screen with snow, finally overlaying the other bits.
|
# This function is better called "render"
sub l {
# set out the base.
$r[-1] =~ s/./-/g;
;
# set out the house
# at this point, $d is "| # + |"
# $f is "| + + |"
# $e is "_____"
a(2, $d);
a(4, "/$e\\");
a(3, $f);
a(5, $u . $e . "" . $u . "", 1);
# set out the trees
for(@t) {
$p="(.{".$_."}";
$r[-5] =~ s,$p.).,$1.".",ex;
$r[0-$_] =~ s;$p)...;$1.""."/$u".qq/\\/;xe,1 for(2..4)
}
# $_ contains the screen, including the "clear screen" code
$_=$z . "" . join "\n", @r;
print;
# $| is set to 1 so this is a "sleep 1"
sleep $|
}
# r() returns a random integer between 0 and <arg>-1
sub r {
int(rand $_[0])
}
# set autoflush
$|=1;
# $u and $" both contain ' ' by default.
$u=$";
# $e now contains "_____"
$e="_" x 5;
# $a will contain " o"
$a=$u . "o";
# $b contains "o"
$b="o";
;
# this is a replace specifically for drawing the house.
# it does a substitution for the line <arg1> from the bottom
# position $h for 7 characters with <arg2>
sub a {
;
substr $r[-$_[0]], $h, 7, $_[1]
}
# this function is better called perturb. It occasionally swaps " o" for "o "
# and vice versa. It does this recursively, by calling itself with an
# argument.
sub t {
# recurse if we haven't already
t(01) if ! @_;
# swap $a and $b
$k=$a;
$a=$b;
$b=$k;
# do the swap across all the rows for whatever is in $a with $a or $b
# on a 1 in 10 chance.
$r[$_-01] =~ s/$a/r(012) ? $a : $b . ""/eg for(1..$r)
}
# $b="o ";
$b.=$u;
# this is the clear screen code
$z="\e[H\e[J";
# get the number of rows and columns rows => $r and cols => $c
($r,$c) = split/\s/, `stty${u}size`;
# $v contains a blank line as wide as the screen.
$v=$" x $c;
# $h is the left-hand position of the house
$h=r($c-7);
# @t contains the left hand positions of the trees there are between 1 and 9
# of them and they're each random
@t=map {r($c-3)} (0..r(9));
# set up $k="o "
$k=$b;
# $k="o"
$k=~s/\s//;
# for each row on the screen, set it to a blank line, and then randomly
# (1 in 30 chance) put snow in each position instead.
for(01..$r) {
($r[$_-1]=$v) =~ s,\s,r(30) ? $" : $k,xeg
}
# $f is "| + + |"
# $d is "| # + |"
($f=$d="|" . "$u#$u+$u|") =~ y/#/+/;
# run the frames
for(0..$r) {
# draw the frame
l;
# perturb the snow
t;
# get the next frame, by putting a blank line at the top, and
# removing the bottom line
@r=($v, @r);
pop @r
}
# set $r[-6] to " Let it snow"
$r[-6]=" Let" . $" . "it$u" . "snow";
# render the frame
l;
# space filler.
$p;
|
Phil Kendall
Back to top
Phil Kendall was the first to submit a real entry, and also, in fact the
last, for his second, revised version. His program was based on checking
the snowflakes for compliance to the rules of the competition (there was
a test programme applied to all entries, but this one was more helpful
for development). It stores its own copy of the template, encoded, of
course, and produces an output that is basically a character (rather than
line) diff of the program in its argument against the template.
Version 1
Requirements: filename as argument
for (()
,split+ '',('C'
.'' .'3' .'Q3!A7M7!93'. '3'. '4'
.'2E2433!A'. 'C4' .'44C!AC444'
.'C!922433'. '42' .'433422!8'.
'' .''. ''. '' .'' .''. ''
.'' .'' .''. '' .''. '3' .''
.'433' .'422243'. '' .'343!763' .'A1'.
'' .'21A36!625U52!2k!1429284829'. ''
.'24!134746664743')){$t.=$/,next,if"!"eq$_;$t.=($|--
?'#' :chr(32)) x(ord$_> 57?(-55+ ord$_):$_ );};
@l= ((split "\n",( $t))); $nn=@l; ();
push @l,$l[$nn -$_]for( 2..@l);; undef($/) ;@p=
map{s/[^\s]/#/g;$_}split"\n",<>;foreach(0..(@l>@p?@l
-1 :$#p)){@a=split'',$l[$_]||'';; @b
=split '',$p[$_." "] ||"";for(0 ..(@a>
@b? $#a :$#b )) {$c= $a[ $_]
|| chr( 32) ;; ;$d =$b[ $_
]||chr(32);; ;;;; print+($c)eq
$d?$c:chr(32 )eq( $c)?"-":"+"}
s;# ;;g; print"\n"}#cam -pm. '02
#.Xmas. Tourney
#by PAK
| |
Phil's entry has been discussed above, in essence it's pretty simple, though
there are obviously some slight nasties, anyone who has done any golfing will
be familiar with the $|-- trick, which is that the return value from
that expression will always be 1 or 0, and it will flip. Phil is also fond of
the ?: ternary operator, which he seems to use an awful lot.
You should run the program as:
perl pak.pl /path/to/filename/to/test.pl
If all is well, then you will see the snowflake as printed in the original
template, if not then there will be +s and -s where non-whitespace needs to
be added or removed.
|
# for each character in:
# C3Q3!A7M7!93342E2433!AC444C!AC444C!92243342433422!83433422243343!763
# A121A36!625U52!2k!142928482924!134746664743
# do:
for ((), split +'', ('C' . '' . '3' . 'Q3!A7M7!93' . '3' . '4' . '2E2433!A' .
'C4' . '44C!AC444' . 'C!922433' . '42' . '433422!8' .
'' . '' . '' . '' . '' . '' . '' . '' . '' . '' . ''
. '' . '3' . '' . '433' . '422243' . '' . '343!763' .
'A1' . '' . '21A36!625U52!2k!1429284829' . '' .
'24!134746664743'
)) {
# if the character is a "!" then print a newline
$t.=$/ , next , if "!" eq $_;
# otherwise, it's a space or hash (switching) for
# (if it's a number, that number, otherwise the ascii value - 55)
# characters
$t.=( $|-- ? '#' : chr(32) ) x ( ord $_ > 57 ? ( -55 + ord $_ ) : $_ );
}
# we now have a representation of the top half of the snowflake in #'s
;
# @l contains the lines of our now expanded template.
@l=((split "\n", ($t)));
# $nn contains the number of lines
$nn=@l;
();
# mirror all but the last line on the end of the array, going outwards.
push @l, $l[$nn-$_] for(2..@l);
# at this point, join("\n",@l) would have a full snowflake layout.
;
# set our record separator to undef, so when we do <> it will read the
# entire file.
undef($/);
# get each line of the file into @p, converting all the non-whitespace to
# "#"
@p=map {s/[^\s]/#/g ; $_} split "\n", <>;
# generate numbers to the bigger of @l and @p
foreach (0..(@l>@p?@l-1:$#p)) {
# split the iteration line of the template into characters, making sure
# to cope in the case where it's undefined.
@a=split '', $l[$_] || '';
;
# do the same for the line of the input. the $_." " is a pointless
# stringification and then back again, but it uses up characters and
# whitespace.
@b=split '', $p[$_." "] || "";
# for the bigger of a and b (note that we have these loaded and the
# $_ is localised. iterate for that number of characters.
for(0 .. (@a>@b ? $#a : $#b )) {
# $c will contain the value at this point of the template, or if
# it's not there then a space - this copes with trailing whitespace.
$c=$a[$_] || chr(32);
;;
# similarly for $d and the input
$d=$b[$_] || chr(32);
;;;;;
# print the appropriate character, the value from the template if
# they are the same, a "-" if $c thinks there should be whitespace
# and a "+" if $c thinks there should be text.
print +($c) eq $d ? $c : chr(32) eq ($c) ? "-" : "+"
}
# this is a useless substitution, since $_ is a number at this point.
s;# ;;g;
# we've reached the end of the line, so print the newline.
print "\n"
}
|
Back to top
Version 2
Requirements: filename as argument
$t= '3'
.'*A*'. '!1.='.
'.' .'!' .'0**+)5)+**'. '!'. '1'
.'3+++3!13'. '++' .'+3!0))+**'
.'+)+**+))'. '!/' .'*+**+)))+'
.+ '*'. '*' .+ '+' .'*' .+
'!' .~~ '.-' .+ '*1' .~~ '('
.')(1' .'*-!-),E' .+ ',)!)[!(+' .')0)'
.+ '/+/)0)+!(*+.+---+.+*!';$w=chr 32
;$t=~s;.;$&=~/!/?$/:($|--?'#':$w)x(-39+ord$&);eg;$n=
+$/; $/=$1;@p= grep{~y~ ~#~c+23} split+$n, <>;;
@l= split~~ $n,$t; push@l ,$l[10- $_]
for( -0..012); for(0... (23>@p?+ 23:$#p)){ +@a=
split'',$l[$_]||'';@b=split'',$p[$_]||'';for(0...(@a
>+ @b?$#a:$#b)){$c=$a[$_]||$w;$d= $b
[$_]|| $w;$s.=+$c eq $d?$c:($w) eq$c?+
'-' :~~ '+'} $s .=$n }$m =$s
.+ 'E'. 'r' .+ 'r' .'o' .+
"rs:".$s=~+y .+-. ..$n;print$m
#Have.Golfed Code TooMuch.Must
### Fill WithComment.Oh Well ###
#Happy# NewYear
### PAK
| |
This is pretty similar, though the encoding string is different, and shorter, the
chr(32)s have been replaced by a variable, and it's a slightly neater programme.
It is run in the same way as the one above, and reports the number of errors found.
|
# + and ~~ are noops in this (~~ because you get "bitwise complement
# of bitwise complement")
$t = '3' . '*A*' . '!1.=' . '.' . '!' . '0**+)5)+**' . '!' . '1' .
'3+++3!13' . '++' . '+3!0))+**' . '+)+**+))' . '!/' .
'*+**+)))+' . +'*' . '*' . +'+' . '*' . +'!' . ~~'.-' . +'*1' .
~~'(' . ')(1' . '*-!-),E' . +',)!)[!(+' . ')0)' .
+'/+/)0)+!(*+.+---+.+*!';
# $w is " "
$w=chr 32;
# in the above string substitute every character for either
# \n if it is a "!"
# run of alternate "#" and " " to the ascii value of the character
# minus 39
# $t therefore contains the top half of template after this.
$t =~ s;.; $& =~ /!/ ? $/ : ($|--?'#':$w) x (-39 + ord $&) ;eg;
# $n is "\n"
$n= +$/;
# set $/=undef
$/=$1;
# <> will be the whole file ($/==undef)
# split it per line
# translate all of the nonwhitespace characters into "#", returning
# all of the lines (I can't see a situation where ~y~ ~#~c+23 is
# false)
@p=grep{~y~ ~#~c+23} split+$n, <>;
;
# @l is the template version of the above, being also split on \n
# (~~$n eq "\n")
@l = split ~~$n , $t;
# reflect the template about its midpoint
push @l, $l[10-$_] for (-0..012);
# $s is going to be our output
# So for each line or the whole of the input (whichever is greater)
for(0...( 23 > @p ? +23 : $#p ) ) {
# @a contains the characters on this line from the template
+@a = split '', $l[$_] || '';
# @b contains the characters on this line from the input
@b = split '', $p[$_] || '';
# for each character on the longest line.
for(0...(@a > +@b ? $#a : $#b)) {
# $c is the character from the template on this line, or
# a whitespace if it doesn't exist
$c = $a[$_] || $w;
# $d is the character from the input on this line, or
# a whitespace if it doesn't exist
$d = $b[$_] || $w;
# The above code makes sure that trailing whitespaces work.
# This code puts the template character if both are the same
# (ie " " or "#", and a "-" if they're different and the template
# says whitespace, or a "+" if they're different and the template
# has a "#"
$s .= +$c eq $d ?
$c
:
($w) eq $c ?
+'-'
:
~~'+'
}
# add a newline to our output before processing the next line.
$s .= $n
}
# $m is the output then "Errors:" and a count of the number of "+" and "-"
# characters in $s and then a newline.
$m = $s . +'E' . 'r' . +'r' . 'o' . +"rs:" . $s =~ +y.+-. . . $n;
# print it.
print $m
|
Andrew Savige
Back to top
So, the man who made his name with
Acme::EyeDrops, and as Santa in one of the first big FWP golf tournaments
submitted no fewer than 6 entries to this. Andrew Savige is either insane or a
genius. It seemed reasonable to allow the EyeDrops-based entry, given that he was also
the author of the automated code generation tool.
Requirements: large terminal, programme in a file
'?' =~(
'(?{'.( '`'|'%'
).( '['^ '-').('`'|'!') .''. (((
'`'))|"\,"). '"'. ('`'|"\/").(
'['^('+')).( '`'| '%').(('`')|
(( '.') )). (( ((( '\\' ))
))) .(( '$') ). '%;' .(( (((
'\\')) ))).'@~='. +( '`'|'-').( ('`')|
(( '!'))).('['^'+').'\\{'.(('[')^ ((
'"'))).';!-~;.;;\\$_\\}<'.('^'^('`'|'.')).'>;'.('`'|
'-') .('`'|'!' ).("\["^ '+').''. '\\{`'.+( '`'|
'#' ).('`'| ',').( ('`')| "\%").( '`'
|'!' ).(('[')^ ')').'>' .('&').( '^'^('`'| ',')
).'`;'.('{'^'[').('['^',').('`'|'!').('['^')').('`'|
(( '.'))).'\\$/'.('['^'#').'(\\$' .+
'_+\\' .'$_),\\@' .+ '~;'.('{'^ '[').(
'[' ^(( '(') )) .''. ((( '`'
)) |',' ).( (( '`' ))|+ ((
'%'))).('`'| '%') .('['^"\+").
'!\\$%\\}\\' .'$' .'%'.(('{')^
'[' ).(( '.')).'.'.('{' ^'[' ).(
';'&'=' ).'"}'.
')' );;
| |
Andrew's first programme produces a falling snowflake by opening $0 and substituting a
"." for every non-whitespace character. It adds newlines at the top, and then clears the
screen and prints a frame each time. I cheated with this, and read the source using
B::Deparse.
|
# STAGE 1 : run through Deparse
#
# '?' =~ m[(?{eval"open\$%;\@~=map\{y;!-~;.;;\$_\}<0>;map\{`clear>&2`; warn\$/x(\$_+\$_),\@~; sleep!\$%\}\$% .. 9"})];
#
# STAGE 2 : reduce by getting rid of the eval (it's the only thing that
# is run by the regexp eval, and doesn't return anything)
# this is a function of the way that EyeDropper works. In effect, it's
# a null regexp and an eval within the regexp. The string you see above
# and below is formed by doing bitwise operations on constant strings.
'?' =~ m[(?{
# the following line is equivalent to:
# open 0, $0;
open $%;
# map yourself ($0) translating all the characters to "." as we go into
# the array @~
@~ = map { y;!-~;.; ; $_ } <0>;
# equivalent to a "for (0..9) {"
map {
# clear the screen
`clear >&2` ;
# print out 2n "\n"s (the value of $/) and then our translated
# snowflake
warn $/ x ($_+$_), @~;
# sleep 1 (1 is the !0 and $%==0)
sleep !$%
} $%..9
# end our eval
})];
|
Back to top
Then came the second entry
Requirements: large terminal
$_= '33
01Z2101 0701Z27
010 901Z 16010401090112 01Z3 901
Z13010601070 1040 110010401Z29
02Z160106010 6030 301040105010
30 1Z11 011 80 5Z1 8011 00
811 01Z 2301 04 0903 010 401
Z16011 109Z290602 01 0304Z22010 401040
10 508Z32010211Z2916Z2422Z2026Z20 26
Z2025Z2025Z2026Z1927Z1828Z1826Z1826Z2123Z2123Z2123Z2
123Z 2123Z2123 Z2123Z21 23Z2123Z 03011723Z 0009
122 3080105 01Z021 306230 2010410 Z03
1701 230317Z03 02033602 20Z09020 2120335Z1 5040
41601030102030105010501Z160109060105Z2214Z1818Z1618Z
18 0302030303Z';s/\s//g;$f='*';;; ;;
print+ map((($f^= $/ )x(($_))), /../g)
,$/ for (((( (( (((( ((( (((
(( (((( ((( (( ((( (((( ((
split+Z))))) )))) ))))))))))))
)))))))))))) )))# ############
### #### ############## #### ###
####### #######
### ###
| |
The second entry produces a static picture of a candle, the data for which is run-length
encoded in pairs in the data at the top. I, personally, thought it was a pretty picture,
though this is just the first version of the it, and it definitely gets better. The trick
of using "*"^"\n" eq " " is very clever, and all the following programmes use it.
|
# Set up $_ to be our data string. This means that all of the // operations
# will work sensibly.
# The data has been reformatted as the next operation removes all \s
# characters. I feel this is ok to aid the readability of this program.
$_='3301Z
21010701Z
27010901Z
1601040109011201Z
3901Z
130106010701040110010401Z
2902Z
1601060106030301040105010301Z
11011805Z
180110081101Z
2301040903010401Z
16011109Z
290602010304Z
2201040104010508Z
32010211Z
2916Z
2422Z
2026Z
2026Z
2025Z
2025Z
2026Z
1927Z
1828Z
1826Z
1826Z
2123Z
2123Z
2123Z
2123Z
2123Z
2123Z
2123Z
2123Z
2123Z
03011723Z
0009122308010501Z
0213062302010410Z
031701230317Z
030203360220Z
090202120335Z
1504041601030102030105010501Z
160109060105Z
2214Z
1818Z
1618Z
180302030303Z';
# get rid of the spaces in the data.
s/\s//g;
# set $f to be "*". Worth noting at this point that "*" ^ "\n" = " ".
$f='*';
;;;;
# take off two characters from the stream (so we get double figures)
# and use them to alternately print spaces and "*"s (because of the
# XOR property above. Do this for each of the parts in between split/Z/
# Note that there are 3 different uses of $_ here. In the outside, the
# full data string, then the part in the for() loop that's split by the
# "Z" characters, then the current 2 numbers in the map. This is fine
# because they're implicitly localised at each level.
print +map ( ( ( $f ^= $/ ) x (($_)) ), /../g), $/
for ((((((((((((((((((((((((((((((((((((
# worth noting at this point that "+" stringifies the bareword
# so this is morally equivalent to ``split/Z/''
split+Z
))))))))))))))))))))))))))))))))))))
|
Back to top
And a third
Requirements: large terminal
$:= q^A
"#,Z>1Z 97Z5;Z5
;Z5 :Z5: Z5;Z4<Z3=Z3;Z3 ;Z68 Z68
Z68Z68Z68Z68 Z68Z 68Z68Z$"28Z!
*-8)"&"Z#.'8 #"%+ Z$2"8$2Z$#$E
#5 Z*## -$D Z0 %%1 "$"# $"
&"& "Z1 "*'" &Z 7/Z3 3Z1 3Z3
$#$$$Z ^;$;=q^B"Z 6" ("Z<"*"Z1" %"*"-"
ZH "Z."'"("%"+"%"Z>#Z1"'"'$$"%"&" $"
Z,"3&Z3"+),"Z8"%*$"%"Z1",*Z>'#"$%Z7"%"%"&)Z^;$^=q^@"
Z8"* "Z="*"Z2" &"*"*"ZF "Z/"%")" &")"%"Z># Z2"'
"&$ %"%"$"$ "Z-"2& Z4"*)+ "Z7"&*% "#"
Z0"- *Z>'$"#%Z 6"%"&"&) Z^;;;sub _{s}\s}}g ;$.=
'*';system$^O=~Win?CLS:'clear';print+map((($.^=$/)x(
(( ord))-33)),/./g),$/for+split+Z ;;
sleep! $%}_($_=$; .$ :),_$_=$^. $:,for
!$% ..4 ;$_= 'M erry 60C hri
st mas6 0to 60 a60 snow bo
und60cam.pm6 0fro m60a60Sydney
60sunbather! ';$\ =$/;s;\s;;g;
;;; s;$= ;$";gsex;print ;s;k ara
te;chop ;eggs;;
#by /-\
| |
This was an evolution on the first entry. The data encoding was single characters, giving
a lot more space, and there were two heads to the candle used in alternation, to make it
flicker. The end prints "Merry Christmas to a snowbound cam.pm from a Sydney sunbather!",
which was only stifled by the fact that for once, it didn't snow in Cambridge. Even
better, this version of Andrew's programme will work under Windows too.
|
# 111111111122222222223333333333
# 0123456789012345678901234567890123456789
# !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH
#
# $: contains the data for the bottom half of the candle, the bit that doesn't
# move.
$: = q^
A"#,Z
>1Z
97Z
5;Z
5;Z
5:Z
5:Z
5;Z
4<Z
3=Z
3;Z
3;Z
68Z
68Z
68Z
68Z
68Z
68Z
68Z
68Z
68Z
$"28Z
!*-8)"&"Z
#.'8#"%+Z
$2"8$2Z
$#$E#5Z
*##-$DZ
0%%1"$"#$"&"&"Z
1"*'"&Z
7/Z
33Z
13Z
3$#$$$Z
^;
# $; and $^ contain the two alternate top halves.
$; = q^
B"Z
6"("Z
<"*"Z
1"%"*"-"Z
H"Z
."'"("%"+"%"Z
>#Z
1"'"'$$"%"&"$"Z
,"3&Z
3"+),"Z
8"%*$"%"Z
1",*Z
>'#"$%Z
7"%"%"&)Z
^;
$^ = q^
@"Z
8"*"Z
="*"Z
2"&"*"*"Z
F"Z
/"%")"&")"%"Z
>#Z
2"'"&$%"%"$"$"Z
-"2&Z
4"*)+"Z
7"&*%"#"Z
0"-*Z
>'$"#%Z
6"%"&"&)Z
^;
;;
# define a sub "_"
sub _ {
# which gets rid of spaces in $_
s}\s}}g;
# $. is a "*", this is useful because:
# $. ^ $/ eq " "
# and of course, $. ^ $/ ^ $/ eq "*"
$. = '*';
# run "CLS" or "clear" depending on what system we're on.
system
$^O =~ Win ?
CLS :
'clear';
# note 3 different uses of $_ here:
# 1. the global data
# 2. that data split by "Z" from the for() below
# 3. each character mapped to be the multiplier, when passed
# through ord() and then having 33 subtracted.
#
# so this prints alternate " " and "*" for each character in the data,
# with "Z" marking line splits
print + map ((( $. ^= $/ ) x ( ((ord)) -33) ) , /./g ), $/
for + split +Z;
;
# sleep "not 0" == 1
sleep !$%
}
# this is a fake, the argument isn't used, but it's evaluated before the
# function is called. So, we call &_ with ($_ eq $; . $:), and then with
# ($_ eq $^ . $:), which we do 4 times each.
_ ( $_ = $; . $: ) , _ $_ = $^ . $: , for !$% .. 4;
# define a new string to print.
$_ = 'Merry60Christmas60to60a60snowbound60cam.pm60from60a60Sydney60sunbather!';
# make sure that print will automatically put a newline on the end.
$\ = $/;
# get rid of spaces in the above string
s;\s;;g;
;;;
# $= is our current format page length (defaults to 60). $" defaults to a
# space. The evaluation doesn't really matter, because it would get
# substituted anyway...
s;$=;$";gsex;
# print out the string
print;
# random filler noop substitution
s;k ara
te;chop ;eggs;;
|
Back to top
He didn't stop there, though. I swear the man didn't do anything else
over christmas.
Requirements: large terminal
$;= q]A
"#,Z>1Z 97Z5;Z5
;Z5 :Z5: Z5;Z4<Z3=Z3;Z3 ;Z68 Z68
Z68Z68Z68Z68 Z68Z 68Z$"28Z!*-8
)"&"Z#.'8(+Z $1#8 $2Z&^Z*##SZ0
%$ 6-"Z ;-Z 7/ Z33 Z13Z 3$
$$] ;$~ ='Qi vv }$Gl vmw xqe
w';sub _{s}\s}}g; $. ='*';print join""
,( !!system$^O=~Win3?CLS:'clear') ,(
map{map((($.^=$/)x(-33+ord)),m).)g),$/}split+Z),@,;;
push (+@,,$~=~ /.*?\$/g ?map{chr (-4+ord)} $&=~
((( m).)g)) ):$/); sleep! $%}$:=q ^B"
Z6"( "Z<"*"Z1" %"*"-"ZH "Z."'"(" %"+"%"Z># Z1"'
"'$$"%"&"$"Z,"3&Z3"+),"Z8"%*$"%"Z1",*Z>'#"$%Z7"%"%"&
)Z ^;$^=q^@"Z8"*"Z="*"Z2"&"*"*"ZF "Z
/"%")" &")"%"Z>#Z 2" '"&$%"%"$" $"Z-"2
&Z4 "*) +"Z7 "& *%"# "Z0 "-*
Z> '$"# %Z6 "% "&" &)Z^ ;;
;$~.='$xs$e$ wrs{ fsyrh$geq2tq
$jvsq$e$W}hr i}$w yrfexliv%$';
$|= 1;$~ =~s~\s~~g;_($_ =$:. $;)
,_$_=$^ .$;,for
!$% ..6
| |
Yet another evolution, this one managed to encode the "Merry Christmas" message, and
display it, one word at a time as the frame advanced. The maps that were
used made my brain hurt, and some clever techniques to make it hard to read were
evident.
|
# The data for the bottom of the candle
$; = q]
A"#,Z
>1Z
97Z
5;Z
5;Z
5:Z
5:Z
5;Z
4<Z
3=Z
3;Z
3;Z
68Z
68Z
68Z
68Z
68Z
68Z
68Z
68Z
$"28Z
!*-8)"&"Z
#.'8(+Z
$1#8$2Z
&^Z
*##SZ
0%$6-"Z
;-Z
7/Z
33Z
13Z
3$$$
];
$~ = 'Qivv}$Glvmwxqew';
sub _ {
# get rid of the spaces in $_
s}\s}}g;
$. = '*';
print join"", (!!system $^O =~ Win3 ? CLS : 'clear'),
(
# this map splits per line
map {
# this one splits per character, and signals
# the run length
map ( ( ($.^=$/) x (-33+ord) ), m).)g ), $/
}
split+Z
),
# @, contains the text for the Happy Christmas message
@,;
;
# the /g makes sure that the next time, we retain our current position
# so each time this is called, we push a new word, at the end, we push
# a newline. The words are taken from $~
push( +@, , $~ =~ /.*?\$/g ?
# the word themselves need to have 4
# subtracted from the ascii value of each
# character.
map { chr(-4 + ord) } $&=~ ((( m).)g )))
:
$/
);
# sleep 1
sleep !$%
}
# the data for one of the tops
$: = q^
B"Z
6"("Z
<"*"Z
1"%"*"-"Z
H"Z."'"("%"+"%"Z
>#Z
1"'"'$$"%"&"$"Z
,"3&Z
3"+),"Z
8"%*$"%"Z
1",*Z
>'#"$%Z
7"%"%"&)Z
^;
# and the other
$^ = q^
@"Z
8"*"Z
="*"Z
2"&"*"*"Z
F"Z
/"%")"&")"%"Z
>#Z
2"'"&$%"%"$"$"Z
-"2&Z
4"*)+"Z
7"&*%"#"Z
0"-*Z
>'$"#%Z
6"%"&"&)Z
^;
;;
$~ .= '$xs$e$wrs{fsyrh$geq2tq$jvsq$e$W}hri}$wyrfexliv%$';
# set autoflush
$|=1;
# get rid of the spaces in $~
$~ =~ s~\s~~g;
# run each individual top 6 times.
_( $_ = $: . $; ), _ $_ = $^ . $; , for !$% .. 6
|
Back to top
This programme was the fifth submitted, and took some ideas from the
example at the top
Requirements: large terminal
$_= q~v
ZvZ&%(' $&"'"&(
&"& $&"' "&$Z$#$$$#$%$& "'"& (&#
%$&"'"&#Z#$$ $#%# %$%$%$%(%%%#
%$%$%#Z"%*#$ %$%$ %$%(%%%#%$%$
%# Z"%, ($% $% $%( %%%# %$
%$% #Z" %*%" %$ %$%$ %(% %%#
%$%$%# Z#%%"#%#%$ %$ %$%$##&#%$ %$%$%#
Z$ &""$%"&$%$%$%#%"%"&%%$%$%#Z%&% &#
%"'"'"'###%*'"'"'"ZT%?ZT%?ZS'>Zv~;s;\s;;g;$;='@,=map
{$.= $";join"" ,map((($ .^=O)x(- 33+ord)), /./g
),$ /}split +Z;s/. /(rand )<.2?"o ":$
"/eg for@;=((5 x84).$/) x30;map{ system$^O =~W?
CLS:"clear";print@;;splice@;,-$_,2,pop@,;@;=($/,@;);
sl eep!$%}2..17';$;=~s;\s;;g;eval $;
###### ########## ## ########## ######
### ### #### ## #### ### ###
## #### ### ## ### #### ##
############ #### ############
############ #### ############
### #### ############## #### ###
####### #######
#by /-\
| |
This was a different programme, and used something similar to my snowscape to fall on
the ground to spell out cam.pm in a block. I liked this entry, and typical to Andrew's
golfing history, he had nearly half the space just in comments. Most of the code was
evalled, and it's pretty amazing that there didn't need to be whitespace in
any of that bit.
|
$_ = q~
vZ
vZ
&%('$&"'"&(&"&$&"'"&$Z
$#$$$#$%$&"'"&(&#%$&"'"&#Z
#$$$#%#%$%$%$%(%%%#%$%$%#Z
"%*#$%$%$%$%(%%%#%$%$%#Z
"%,($%$%$%(%%%#%$%$%#Z
"%*%"%$%$%$%(%%%#%$%$%#Z
#%%"#%#%$%$%$%$##&#%$%$%$%#Z
$&""$%"&$%$%$%#%"%"&%%$%$%#Z
%&%&#%"'"'"'###%*'"'"'"Z
T%?Z
T%?Z
S'>Z
v
~;
s;\s;;g;
# the following bit of code is basically:
# @, ends up containing the cam.pm text, which is extracted from the RLE
# data in $_
# @; is filled with snow on 30 rows
# each frame is printed in the map, which prints the current "@;" (screen)
# the splice then takes off a row of snow and turns it into the cam.pm
# body.
# finally a newline is pushed on at the top.
$; = '
@, = map { $.=$" ; join "" , map((($.^=O)x(-33+ord)),/./g) , $/ }
split +Z;
s/./(rand)<.2 ? "o" : $"/eg for @; = ((5x84).$/)x30;
map { system $^O =~ W ? CLS :"clear" ;
print @;
;
splice @; , -$_ , 2 , pop @, ;
@; = ( $/ , @; );
sleep !$%
} 2..17
';
# eval the above code with no spaces in it.
$; =~ s;\s;;g;
eval $;
|
Back to top
This last programme came hot on the tail of the one above, and is an
evolution of it. It adds a snowman that appears on the last frame.
Requirements: large terminal
$_= q~v
ZvZ&%(' $&"'"&(
&"& $&"' "&$Z$#$$$#$%$& "'"& (&#
%$&"'"&#Z#$$ $#%# %$%$%$%(%%%#
%$%$%#Z"%*#$ %$%$ %$%(%%%#%$%$
%# Z"%, ($% $% $%( %%%# %$
%$% #Z" %*%" %$ %$%$ %(% %%#
%$%$%# Z#%%"#%#%$ %$ %$%$##&#%$ %$%$%#
Z$ &""$%"&$%$%$%#%"%"&%%$%$%#Z%&% &#
%"'"'"'###%*'"'"'"ZT%?ZT%?ZS'>Zv~;s;\s;;g;$~=q~ZZZJ_
#_ZH /'\\ZG|#o #o#|ZG|$ <%|ZH\\" \\!_!_!/" /ZG/
)\\ ZF/+\\Z E|-|ZE |-|ZE| -|ZF\\+ /ZG
\\)/ ~;;@x=@,= +map{$.= $";;join "",map((( $.^=
O)x(-33+ord)),/./g)}split+Z;$~=~s~\s~~g;;s/./(rand)<
.2 ?"o":$"/egxfor@;=(5x84)x30;map {#
system $^O=~W?CLS :+ "clear";;; ;print
$_. $/, ,for $_ -18? @;: ###
(( map{ $|= 1; ;;; join ""
,map($|--?$" x(-3 *11+ord):$_,
/./g)}split+ Z,$~ ),@x);splice
@;, -$_, 2,pop@,;@;=("" ,@;) ;;;
;sleep! $%}+2..
18# /-\
| |
This got rid of the horrid eval above, and had some more brain-wrenching mapping.
$_ contains the cam.pm block, and $~ the snowman
|
$_ = q~
vZ
vZ
&%('$&"'"&(&"&$&"'"&$Z
$#$$$#$%$&"'"&(&#%$&"'"&#Z
#$$$#%#%$%$%$%(%%%#%$%$%#Z
"%*#$%$%$%$%(%%%#%$%$%#Z
"%,($%$%$%(%%%#%$%$%#Z
"%*%"%$%$%$%(%%%#%$%$%#Z
#%%"#%#%$%$%$%$##&#%$%$%$%#Z
$&""$%"&$%$%$%#%"%"&%%$%$%#Z
%&%&#%"'"'"'###%*'"'"'"Z
T%?Z
T%?Z
S'>Z
v
~;
# get rid of the spaces in $_
s;\s;;g;
$~=q~
Z
Z
Z
J_#_Z
H/'\\Z
G|#o#o#|Z
G|$<%|Z
H\\"\\!_!_!/"/Z
G/)\\Z
F/+\\Z
E|-|Z
E|-|Z
E|-|Z
F\\+/Z
G\\)/
~;
;
# Fill @x and @, with the RLE encoded "cam.pm" block from $_
@x = @, = +map {
$. = $";
;
join "", map( ( ( $. ^= O ) x (-33+ord) ), /./g )
} split +Z;
# get rid of the spaces in $~ (the snowman)
$~ =~ s~\s~~g;
;
# fill @; with snow
s/./(rand)<.2?"o":$"/egx for @; =(5x84)x30;
# run our frames
map {
# clear the screen
system $^O =~ W ? CLS : +"clear";
;;;
# print "$_\n"
print $_ . $/,, for $_-18 ?
# the snowscape
@;
:
((
# this map draws the snowman
map {
$| = 1;
;;;
join "",
# alternate characters are RLE number
# of spaces, or the character itself
map( $|-- ? $" x (-3*11+ord) : $_, /./g)
} split +Z, $~),
# @x contains the block
@x);
# advance the snowscape pushing the snow and block
splice @; , -$_ , 2 , pop @, ;
@; = ( "" , @; );
;;;
# sleep
sleep !$%
} +2..18
|
Pete Clay
Back to top
So, this competition's Colin Watson came in at the 11th hour and used nice
vector maths and quasi-Affine Transformations to produce a snowflake but
as a PPM file.
$w= 100
;$w*=5; ;$W=$w*
$w; q--; $p=atan2(1,0)* 2;3; @P=
("\000"x3)x( $W); BEGIN{$";sub
S{$_.='fhoq' }sub K{$_.='s'.((
$n ++)) .(( '' .'' .'{' ))
;}; sub Y{$_ .= $_[0 ]}; S;K
;Y(''. '$k/=2;$'. '' .'l/=2}'); S;K;0;
Y( '$k/=3;$l/=3;$k+=$j/4}fhoqh{'. ''
.'cevq"P6\a$jq$j\a255\a",q@P}');S;K;Y('$g=$c/3;e}');
S;K; Y(q.$g=$. .'c/-3;' .'e}');S ;K;Y('$'. 'g'.
'=' .'$c*2' .'/3}' );;s/v /vag/x; sub
p{$P [$x+$w/2+ int($y)* $w+$W/2] ="\377"x3 }sub
r{$z=$x*cos($t)+$y*sin($t);$y=$x*sin($t)-$y*cos($t);
$x =$z};tr/a-z/n-za-m/;s/d/$"/gx; $x
++;$y= 4;eval$_}; s/ /japh/;sub T{;$a=
$_[ 0]; ;$b= (( $a&( ($a |(+
$a <<1) )<< 1) )>> 2)|( $a
>>3);if($b){ $_[0 ]=""}else{$_
[0]="f$a;p;" }};; for(1..20000
*10 ){$_ =int(rand(20)) ;T$_ ;0;
eval$_} u#byPJC
#JA PH#
| |
Pete's entry was the only one which used no data at all. The data that is there
is code that gets rot-13ed and evalled. The code itself confuses Deparse in a
couple of places, and contains some real nasties. The circuit reduction for
the effective: $b=$a>4 within T is, erm, interesting. The
fact that it produces the output it does is also impressive, but is a function
of the way such transformations work, and doing the iteration that many times
makes it likely to work.
Pete's recommendation was to run this programme as:
perl pjc.pl | xloadimage stdin
though any PPM (Portable PixMap) viewer should work
The output should look something like that below:
|
# $w=500 - The width and height of our canvas
$w = 100;
$w *= 5;
;
# $W=250000 = number of pixels
$W = $w*$w;
# ''
q--;
# $p = \pi
$p = atan2(1,0)*2;
3;
# fill each pixel with 0x000000
@P=("\000"x3) x ($W);
BEGIN {
$";
# $_ is going to be (lc only) rot-13'ed, and "d" is used as a space
# separator so:
# S adds "sub " to the code we're building
sub S {
$_ .= 'fhoq'
}
# K keeps track of a number, and adds "f<n>{" to the stream, where
# <n> is replaced by an incrementing counter
sub K {
$_ .= 's' . (( $n++ )) . (('' . '' . '{' ));
}
;
# Y adds its argument onto the stream.
sub Y {
$_ .= $_ [0]
}
;
# sub f0{$x/=2;$y/=2}
S;K;
Y ( '' . '$k/=2;$' . '' . 'l/=2}');
# sub f1{$x/=3;$y/=3;$x+=$w/4}sub u{pri "P6\n$w $w\n255\a", @P}
# note that below the "i" gets expanded to "int"
S;K;
0;
Y( '$k/=3;$l/=3;$k+=$j/4}fhoqh{' . '' . 'cevq"P6\a$jq$j\a255\a",q@P}');
# sub f2{$t=$p/3;r}
S;K;
Y('$g=$c/3;e}');
# sub f3{$t=$p/-3;r}
S;K;
Y(q.$g=$. .'c/-3;' .'e}');
# sub f4{$t=$p*2/3}
S;K;
Y( '$' . 'g'. '=' . '$c*2' . '/3}');
;
# turn "i" into "int"
s/v/vag/x;
# p turns a pixel ($x-$w/2 , $y-$w/2) to white
# ie, the origin for x and y is in the middle
sub p {
$P[ $x + $w/2 + int($y)*$w + $W/2 ] = "\377" x 3
}
# r rotates the cursor vector by $t
sub r {
$z = $x * cos($t) + $y * sin($t);
$y = $x * sin($t) - $y * cos($t);
$x = $z
}
;
# rot13
tr/a-z/n-za-m/;
# substitute d (q before the rot) with " "
s/d/$"/gx;
$x++;
$y=4;
# the finished code that will be run is:
# # move the cursor closer in by a factor of 2
# sub f0 {
# $x /= 2;
# $y /= 2
# }
#
# # f1 moves the cursor inwards by a factor of 3 (to the centre)
# # and then move it out by a quarter of the canvas along the x-axis
# # this gives a lot of the filament structure
# sub f1 {
# $x /= 3;
# $y /= 3;
# $x += $w/4
# }
#
# # print out our canvas as a PPM
# sub u {
# print "P6\n$w $w\n255\n", @P
# }
#
# # Theta = pi/3 ; rotate
# sub f2 {
# $t=$p/3;
# r
# }
#
# # Theta = -pi/3 ; rotate
# sub f3 {
# $t = $p/-3;
# r
# }
#
# # This does nothing
# sub f4 {
# $t = $p*2/3
# }
eval $_
}
;
s/ /japh/;
sub T {
;
# $a is our argument
$a = $_[0];
;
# $b > 0 if $a not element of [0,4]
# I did this by doing:
# perl -e 'map { $b=(($_ & (($_|($_<<1))<<1))>>2)|($_>>3); print "\$a=$_ \$b=$b\n" } (0..20)'
$b=(( $a & (( $a | (+$a<<1) ) <<1 )) >> 2 ) | ( $a>>3 );
if($b) {
# note this is a reassign back to our argument
# does nothing
$_[0] = ""
}
else {
# note this is a reassign back to our argument
# calls f0,f1,f2,f3,f4 as appropriate, and then puts the pixel
$_[0] = "f$a;p;"
}
}
;;
# apply lots of potential transformations using T.
for(1 .. 20000*10) {
$_ = int(rand(20));
T $_;
0;
# since T reassigns back in its argument, we eval that
eval $_
}
# u prints out the ppm
u
|
|