#!/usr/bin/perl # Usage: # ./ssstgen.pl n h # Where n is the number of balls, and h is the highest siteswap value. # High values will take a while due to a bit of a hack I used to # generate states. The output is a file called nballmaxh.eps. n and h # must both be numbers, rather than their ss equivalent, although the # output will use a,b,c etc for throws higher than 9. # This code is open source. If you want to distribute, modify or sell # it then do so. If you do sell it then please let me know at: # guy.griffiths@rdg.ac.uk so we can laugh about the fact that you # found someone stupid enough to pay for it. Oh, also I'd rather you # kept the next line intact, but I'm not going to stop you taking # credit for it either. # Written by Guy Griffiths $balls=$ARGV[0]; $highss=$ARGV[1]; if($highss<$balls){die"No of balls must be greater than highest ss value\n";} $nstates=factorial($highss)/(factorial($balls)*factorial($highss-$balls)); $picw=2*$nstates; $papw=3*$picw+10; $pich=$nstates+2+0.4*$highss; $paph=3*$pich+10; open(TEX,">temp.tex")||die "Cannot open file for writing"; print TEX "\\documentclass{article}\n\\pagestyle{empty}\n"; print TEX "\\special{papersize=$papw mm,$paph mm}\n"; print TEX "\\setlength{\\textwidth}{$papw mm}\n"; print TEX "\\setlength{\\textheight}{$paph mm}\n\\begin{document}\n\n"; print TEX "\\begin{center}\n\\setlength{\\unitlength}{3mm}\n"; print TEX "\\begin{picture}($picw,$pich)\n"; $temp=$pich/2; print TEX "\\multiput(0,",$pich/2,")(1,0){$nstates}{\\oval(0.8,$pich)}\n"; for($i=0,$j=0;$i<2**($highss);$i++){ $t=0; $curst=dec2bin($i); map$t+=$_,(split//,$curst); if($t==$balls){$state[$j]=bin2dec($curst);$j++;} } for($i=0;$i<$nstates;$i++){ #Find all transitions going to current state drawstate($state[$i],$i); $curst=$state[$i]; for($j=0;$j<=$highss;$j++){ $initialstate=2*$curst+1-2**$j; $valid=0; for($k=0;$k<$nstates;$k++){if($initialstate==$state[$k]){$valid=1;$inin=$k}} if($valid==1){drawtransition($inin,$i,$j);} } } print TEX "\\end{picture}\n\\end{center}\n\\end{document}"; system("latex temp.tex"); $psname=$balls."ballmax".$highss; system("dvips -E -o $psname.eps temp.dvi"); system("rm temp.aux temp.log temp.tex temp.dvi"); sub drawstate{ my @state=split(//,dec2bin($_[0])); while($#state<=$balls){unshift(@state,0);} my $x=$_[1]; my $y=$pich-($highss*0.4); my $i; for($i=0;$i<$highss;$i++){ $onoff=pop(@state); print TEX "\\put($x,$y){\\circle"; if($onoff==1){print TEX "*";} print TEX "{0.3}}\n"; $y+=0.4; } } sub drawtransition{ # Arguments: State to draw from, state to draw to, ss value. my $fromx=$_[0]; my $tox=$_[1]; my $fromy=$pich-1-($highss*0.4)-$tox; my $ss=$_[2]; if($ss>9){$ss=chr($ss+87)} print TEX "\\put(",$fromx,",",$fromy,"){\\circle{0.8}}\n"; print TEX "\\put(",$fromx-0.2,",",$fromy-0.2,"){\\bf{\\tiny ",$ss,"}}\n"; print TEX "\\put(",$fromx,",",$fromy-0.4,"){\\line(0,-1){0.1}}\n"; unless($fromx==$tox){print TEX "\\put(",$fromx,",",$fromy-0.5,"){\\vector(",($tox-$fromx)/abs($tox-$fromx),",0){",abs($tox-$fromx),"}}\n";} else{print TEX "\\put(",$fromx,",",$fromy-0.5,"){\\line(0,-1){0.05}}\n";} return 0; } sub dec2bin { my $str = unpack("B32", pack("N", shift)); $str =~ s/^0+(?=\d)//; # otherwise you'll get leading zeros return $str; } sub bin2dec { return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); } sub factorial { my $n = shift; return undef if $n < 0; return 1 if $n == 0; return $n * factorial($n - 1); }