note
BrowserUk
<blockquote><i>A step-by-step explanation is what I am looking for.</i></blockquote>
<p>Okay. (but you could have produced this yourself; see [mod://Devel::Trace]):<spoiler><code>
C:\test>perl -d:Trace junk72.pl
>> [0] junk72.pl : 16: hanoi( 3, 'A', 'C', 'B' );
>> [0] junk72.pl : 5: my ($n, $start, $end, $extra) = @_;
>> [0] junk72.pl : 6: if ($n == 1) {
>> [0] junk72.pl : 10: hanoi($n-1, $start, $extra, $end);
>> [0] junk72.pl : 5: my ($n, $start, $end, $extra) = @_;
>> [0] junk72.pl : 6: if ($n == 1) {
>> [0] junk72.pl : 10: hanoi($n-1, $start, $extra, $end);
>> [0] junk72.pl : 5: my ($n, $start, $end, $extra) = @_;
>> [0] junk72.pl : 6: if ($n == 1) {
>> [0] junk72.pl : 7: print "Move disk #1 from $start to $end.";
Move disk #1 from A to C.
>> [0] junk72.pl : 11: print "Move disk #$n from $start to $end.";
Move disk #2 from A to B.
>> [0] junk72.pl : 12: hanoi($n-1, $extra, $end, $start);
>> [0] junk72.pl : 5: my ($n, $start, $end, $extra) = @_;
>> [0] junk72.pl : 6: if ($n == 1) {
>> [0] junk72.pl : 7: print "Move disk #1 from $start to $end.";
Move disk #1 from C to B.
>> [0] junk72.pl : 11: print "Move disk #$n from $start to $end.";
Move disk #3 from A to C.
>> [0] junk72.pl : 12: hanoi($n-1, $extra, $end, $start);
>> [0] junk72.pl : 5: my ($n, $start, $end, $extra) = @_;
>> [0] junk72.pl : 6: if ($n == 1) {
>> [0] junk72.pl : 10: hanoi($n-1, $start, $extra, $end);
>> [0] junk72.pl : 5: my ($n, $start, $end, $extra) = @_;
>> [0] junk72.pl : 6: if ($n == 1) {
>> [0] junk72.pl : 7: print "Move disk #1 from $start to $end.";
Move disk #1 from B to A.
>> [0] junk72.pl : 11: print "Move disk #$n from $start to $end.";
Move disk #2 from B to C.
>> [0] junk72.pl : 12: hanoi($n-1, $extra, $end, $start);
>> [0] junk72.pl : 5: my ($n, $start, $end, $extra) = @_;
>> [0] junk72.pl : 6: if ($n == 1) {
>> [0] junk72.pl : 7: print "Move disk #1 from $start to $end.";
Move disk #1 from A to C.
</code></spoiler>
<p>But, whilst that may help you wrap your head around an existing recursive implementation, it probably won't help you with writing your own recursive routines.
<P>The trick to understanding and <i>using</i> recursion is to avoiding trying to 'run the loops' in your head, and instead think about the subroutine in snapshots. That is to say, imagine each of the situations (states) that could exist at the point of entry to the subroutine and then what needs to be done to move that state to the next state.
<P>So for the routine above the are two states:
<ol><li><c>$n == 1 </c>
<P>If there is only one disc, then all that is required is to move that disc directly from the <c>$start</c> to the <c>$end</c> and exit.
</li><li><c>$n != 1</c>
<p>Start with the simplest situation, of <c>$n == 2</c>.
<P>In this case, there are three steps required:
<ol><li>Move the top disc from the <c>$start</c> to the <c>$extra</c>.
<P>This can be achieved by pretending that there is only one disc to move and that the <c>$extra</c> is the <c>$end</c>. In this way, we can call ourselves and the first state handler (above) will do the work.
<P>So reduce the count to one, switch the <c>$end</c> for the <c>$extra</c> and call ourselves recursively.
</li><li>Move the second disc from the <c>$start</c> to the <c>$end</c>
<P>With the top disc out of the way (on <c>$extra</c>), we can now move the second disk from the <c>$start</c> to the <c>$end</c> unimpeded.
<P>(The print statement does the "work" for this step!)
</li><li>Move the top disc from the <c>$extra</c> to the <c>$end</c>
<P>So, again reduce the count to one; but this time, pass <C>$extra</c> as the <c>$start</c> and <c>$end</c> and the end.
</li></ol>
<P>And the job is done for 2 discs.
</li></ol>
<P>For three discs, we only need to do: the above two disc procedure but from <c>$start</c> to <c>$extra</c>; followed by the one disc procedure from <c>$start</c> to <c>$end</c>; followed by the two disc procedure from <c>$extra</c> to <c>$end</c>.
<P>And by now, you should be able to see that by passing in <c>$n == 3</c>, that is exactly what happens.
<div class="pmsig"><div class="pmsig-171588">
<hr />
<font size=1 >
<div>With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'</div>
<div>Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.</div>
<div>"Science is about questioning the status quo. Questioning authority". </div>
<div>In the absence of evidence, opinion is indistinguishable from prejudice.
</div>
</font>
</div></div>/c
1030922
1030922