in reply to My first JAPH

++ColinHorne on a very respectable first Japh!

Here are a few tips for "golfing" it down, should you desire to make it even more terse, while still preserving the important elements:

  1. Convert 'shift' to 'pop' wherever @_ contains a single argument.
  2. Get rid of the extra "{ }" around the main program, and get rid of extra "( )" wherever you can.
  3. Change "long" variable names like "count" and "buf" to single chars like "c" and "b".  (You can even get really obtuse and use variables like "$," and "$;" if you want)
  4. Get rid of 'my'.  You're not using strict anyway, so change all your variables to globals (it's not production code after all!)   Use a different name if there's a variable name conflict.  Then, you may have to assign to 0, but you can even save space there, with "$b=$c=0;" instead of "$b=0;$c=0;".  Or, if you're willing to forego warnings, you can even avoid the assignment, as $b and $c default to zero.
  5. Changing for(...){...} to map{...}... saves a few characters.  It has the added benefit that it forms an array, so you can actually get rid of all occurrences of @r!
  6. You have a string concatenation which seems unnecessary, and saves 3 characters ('"."')
  7. You can change "$b=(($b<<1)|($_?1:0))&255" to "$b=255&$b<<1|($_?1:0)" to save 4 chars.
  8. Changing "print chr($b)unless(++$c%8)" to "++$c%8or print chr$b" saves 7 chars.
  9. If you change "(reverse(0..7))" to "(-7..0)", and change the sign of $_ where it's used "2**-$_", it'll have the same effect, but obviates the need for "reverse". (You need two extra '-', but you also save a pair of parens "(...)").
  10. You were already careful not to have the last statement in each subroutine end with ';', and you can apply that to the last line of the program as well.
  11. Finally, prefer $/ over "\n", and you save a couple of chars.

And here is the final result:

#!/usr/bin/perl @k=split//,'colin@colinhorne.co.uk'; @p=sub{$_=pop;map{sub{$_=pop;map{chr(eval"0b$_")}/.{8}/g}->(sprintf('% +032b',eval "0x$_"))}split/,/;}->("291a1f1d,4e210d00,18010b1a,4f220b17,4243274f,16 +080a1e"); sub d{$b=255&$b<<1|($_?1:0);++$c%8or print chr$b}sub{$f=pop;map{for$a( +map{2**-$ _}(-7..0)){local$_=(ord($k[$_%$#k])^ord($p[$_]))&$a;&$f}}0..$#p}->(\&d +);print$/

s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

Replies are listed 'Best First'.
Re^2: My first JAPH
by ColinHorne (Sexton) on May 13, 2006 at 19:21 UTC
    > ++ColinHorne on a very respectable first Japh!
    Many thanks! As you've probably guessed, I'm fairly new to the monastery (although, I've been lurking for a while), so that's my first ++ :-)
    > Here are a few tips for "golfing" it down, should you desire to make it even more terse, while still preserving the important elements:
    I made a re-write this morning, which implemented many of your tips. Still based on the same idea as the old code, though.
    #!/usr/bin/perl $a="cdfh";printf(join("",map{chr(ord)}map({$_^=(split //,$a)[$i++% length$a]}(map{chr(eval"0x$_")}(("4617460110442c1d101046090d0b120" ."00616463806160a482b05050306166c")=~/../g)))),$a)#GPL:Colin Horne
    I think there's only one pair of parenthesis which can be taken out, which are around chr(ord). I decided to keep them in, though, since the formatting is quite nice at the moment, and removing them would mess that up a bit :-)
    > 6. You have a string concatenation which seems unnecessary, and saves 3 characters ('"."')
    I left that in on the re-write, so that I could keep the col-width under 70 (there can't be a newline character in the string). Shoot me if there's a nicer way to do that, though :-)
    My exam's in a few days time, but after that I will have another go at re-writing it, and will hopefully get 'round to making an explanation page (for those who aren't wizards like yourself :-) ).
    Anyway, many thanks for your help! Hopefully you can expect me to be active more, and lurk less in the near future :-D Cheers!
    Edit: Actually, it seems there was quite a bit I could strip out from this mornings code ;-) This is the updated version:
    #!/usr/bin/perl map{print chr ord}map{$_^=qw{c d f h}[$a++%4]}map{eval"chr 0x$_ "}"2911151c43050807170c031a4334031a0f442e09000f031a4f6e"=~/../g
    Changed the output a bit, since I wasn't too sure if it was considered arrogant for one to label himself directly (also, it made the code slightly shorter to strip that out!).