http://www.perlmonks.org?node_id=401164


in reply to Re: Recursion: the Towers of Hanoi problem
in thread Recursion: The Towers of Hanoi problem

sub han { if (my $l = pop) { han(@_[0,2,1],$l-1); print "Move disc $l from $_[0] to $_[2]\n"; han(@_[1,0,2],$l-1); } }

little shorter

Replies are listed 'Best First'.
Re^3: Recursion: the Towers of Hanoi problem
by abitkin (Monk) on Oct 21, 2004 at 16:20 UTC
    Try this on:
    sub a{my$l=pop;a(@_[0,2,1],--$l)."Move disc $l from $_[0] to $_[2] ".a(@_[1,0,2],$l)if$l>0;}print a 'A'..'C',shift;
    Now trying for the least number of chars. 116 in this solution.
    New rules, no #! needed.

    ==
    Kwyjibo. A big, dumb, balding North American ape. With no chin.
      In real terms, this is slightly longer than the previous version, isn't it? you need a space between print and the argument, I don't. Apart from that, this is different to the requirements. This prints out $l - 1, which is incorrect, or at least different to the 1-3 based original solution.

      Trimming whitespace from the solution in my last post, and giving it a one character sub name makes it 112 characters, 107 if you take the quotes and braces around a A..C,pop.

      Strangely, using my $l=$_[3]-- and using a(@_[0,2,1,3]) etc. doesn't work at all. @_ is not localised ($_3 ends up very negative and the solution becomes deeply recursive), which makes me wonder if the above solution works. I haven't compared the output to the original solution's output.
        Strangely, using my $l=$_[3]-- and using a(@_[0,2,1,3]) etc. doesn't work at all. @_ is not localised ($_3 ends up very negative and the solution becomes deeply recursive), which makes me wonder if the above solution works. I haven't compared the output to the original solution's output.

        from perlsub:
        The array @_ is a local array, but its elements are aliases for the actual scalar parameters.

        Basically, if you think about it, @_ has to be localized. Otherwise if you called a function inside a function (something I hope most of us do) your @_ array would be wiped out, leaving you with the parameters you sent into the child function you just called. The particular behavior your seeing is probably becuase the @_ array contains aliases to scalars.

        Second, using 0 based discs is okay, it's easy enough for the user to add 1 in their head (or to start thinking like a cs person.)

        Third, and this is where it gets interesting, when removing all the whitespace I can I get (for your solution):

        sub a{if(my$l=pop){a(@_[0,2,1],$l-1);print"Move disc $l from $_[0] to +$_[2] ";a(@_[1,0,2],$l-1);}}a 'A'..'C',pop;
        Which just happens to be the same amount of space as (my solution):
        sub a{my$l=pop;a(@_[0,2,1],--$l)."Move disc $l from $_[0] to $_[2] ".a(@_[1,0,2],$l)if$l>0;}print a 'A'..'C',pop;
        so it seems that both solutions are (atleast as far as this little experiment goes) equal. My goal is to squeeze everything that I have now down to 115 or 110 by Tuesday.

        Oh and I have compared our outputs, and with the exception of the disc number (mine being one less than yours) they are exactly the same.

        EDIT:
        perlsub not perlvar

        EDIT2:
        pop instead of shift to remove chars

        EDIT3 (10/26/04):
        Best I've done, modifing jasper's code, is 111 chars.

        sub a{if(my$l=pop){a(@_[0,2,1],--$l);print"Move disc $l from $_[0] to +$_[2] ";a(@_[1,0,2],$l);}}a 'A'..'C',pop;

        ==
        Kwyjibo. A big, dumb, balding North American ape. With no chin.