Michelignax
Michelignax

Reputation: 69

array display in recursive function in php

I want to use a recursive function on arrays to solve the problem of the Towers of Hanoi in php. The program doesn't do what I expected and after hours trying to get why it seems I won't be able to do so on my own.

My index.php has the following code :

    <!doctype HTML>
    <html>

     <head>
        <?php require"hanoi.php" ?>

        <title>Tours de Hanoi</title>
        <style>
            <?php
                if (isset($_POST['nbDiscs']))
                {
                    $nb = $_POST['nbDiscs'];
                }
            ?>
        </style>
    </head>

    <body>
        <h3>Tower of Hanoi</h3>

        <form action="index.php" method="post">
            <input type="text" name="nbDiscs" value=""/>
            <input type="submit" value="submit"/>
        </form>

        <?php
            if (isset($_POST['nbDiscs']))
            {
                $list1 = [];
                $list2 = [];
                $list3 = [];

                for($i=0;$i<$nb;$i++)
                {
                    array_push($list1, $i);
                }

                DisplayLists($list1,$list2,$list3);
                MovePlates($nb,$list1,$list2,$list3);

            }
        ?>
    </body>
    </html>

And my hanoi.php file the following one :

    <?php
        function MovePlates ($number, &$start, &$finish, &$other) {
            if ($number != 0) 
            {
                MovePlates($number-1, $start, $other, $finish);
                array_push($finish, array_pop($start));
                DisplayLists($start,$finish,$other);
                MovePlates($number-1, $other, $finish, $start);
            }       
        }

        function DisplayLists($list1,$list2,$list3)
        {
            echo"list1: ";
            for($i=0;$i<sizeof($list1);$i++) echo"$list1[$i]";
            echo"<br/>";
            echo"list2: ";
            for($i=0;$i<sizeof($list2);$i++) echo"$list2[$i]";
            echo"<br/>";
            echo"list3: ";
            for($i=0;$i<sizeof($list3);$i++) echo"$list3[$i]";
            echo"<br/>";
            echo"<hr/>";
        }
    ?>

When I run that for 2 elements, I get the following :

list1: 01
list2:
list3:


list1: 0
list2: 1
list3:

list1:
list2: 0
list3: 1

list1:
list2: 01
list3:

I use the function DisplayLists in the main program so I see the state of array before using the function. Let's call it state 0.

First problem

I don't understand what's going on with the first step (going from state 0 to state 1), looking at the "MovePlates" function:

we call MovePlates(2,list1,list2,list3),

number = 2, so we enter the "if" block then we call MovePlates(1,list1,list3,list2)

number = 1, so we enter the "if" block then we call MovePlates(0,list1,list2,list3)

number = 0 so the function does nothing and we continue to resolving the number=1 call.

So the call was MovePlates(1,list1,list3,list2) and we now go to the element exchange, meaning that we take the last element of list1 and put it in the last position of list3.

But as you can see, it's list2 that gets the element (state 1). I don't get it, it's like the program keeps the arguments in the orger of the initial call.

Second Problem

I don't understant step 2 (between state1 and state 2) : regardless of the recursive aspect of the function, each time there's an exchange of argument, the lists are displayed by the function DisplayLists but state 2 shows that two elements have been moved (one elment from list2 to list3 then one element from list1 to list 2). That's a big mistery to me.

I anyone has any insight of why it works that way I'd be grateful !

Upvotes: 1

Views: 341

Answers (2)

Michelignax
Michelignax

Reputation: 69

I just need to assign a name to the different lists by using a key to keep track of them :

    $list1['name'] = start;
    $list2['name'] = finish;
    $list3['name'] = other;

and write their name in my display function :

    function DisplayLists(&$list1,&$list2,&$list3)
        {
            echo $list1['name']." : ";
            for($i=0;$i<sizeof($list1)-1;$i++) echo"$list1[$i]";
            echo"<br/>";
            echo $list2['name']." : ";
            for($i=0;$i<sizeof($list2)-1;$i++) echo"$list2[$i]";
            echo"<br/>";
            echo $list3['name']." : ";
            for($i=0;$i<sizeof($list3)-1;$i++) echo"$list3[$i]";
            echo"<br/>";
            echo"<hr/>";
        }

then i get :

start : 01
finish :
other :


start : 0
other : 1
finish :

start :
finish : 0
other : 1

other :
finish : 01
start :

Not very good looking but problem solved.

Upvotes: 0

dWinder
dWinder

Reputation: 11642

Your logic is fine and both of your problem cause by the same reason.

What you missed is that your DisplayLists function prints the list by the order send to her and by global name. I will explain:

As you mention in the first problem, in the call MovePlates(1,list1,list3,list2) you call other MovePlates with 0 which we can ignore - but then you call DisplayLists($start,$finish,$other); -> notice that now list3 = finish and list2 = other. So when you call DisplayLists you actually call DisplayLists(list1, list3, list2) that way the print look weird -> you print list 3 but write before it list 2. The actual status of the lists are:

list1: 0
list2: 
list3: 1

Regarding you next problem; after the last explain we can see state 1 is as mention above. So now, state 2:

list1: 
list2: 0
list3: 1

is make sense - only 1 number moved...

Hope that helps!

Upvotes: 1

Related Questions