Example #1
0
/**
 * Recursively print the steps required to move all rings to the destination maintaining the invariant that no larger
 * ring can ever be on top of a smaller ring.  The thing to remember here is that the first step is to get all rings
 * except the largest one to the last peg first, using the middle peg.  The second step is to transfer the largest ring
 * from the first peg to the middle peg.  The final step is to transfer all of the rings, except the largest, to the
 * middle peg, using the first peg.  The recursion may seem daunting but focusing on those three steps makes this
 * problem pretty straightforward.  You don't have to understand how everything is being handled recursively.  If you
 * understand and handle the outer conditions properly, the rest will take care of itself.
 * This works by first recursively moving all rings from peg 0 to peg 2 using peg 1 as an intermediary.  Then it
 * recursively moves all rings from peg 2 to peg 1 using peg 0 as an intermediary.  It will be easier to see what is
 * happening in the example.
 *
 * i.e.
 * If the starting number of rings is 3, from peg is 0, to peg is 1 and use peg is 2.
 *
 * $numberOfRings = 3
 * $pegs = [
 *  [
 *      0 => 3,
 *      1 => 2,
 *      2 => 1
 *  ],
 *  [],
 *  [],
 * ]
 * $fromPeg = 0
 * $toPeg = 1
 * $usePeg = 2
 *
 * Is the $numberOfRings > 0? Yes
 *      <<< FIRST RECURSIVE CALL BEGIN >>>
 *      $numberOfRings = 2
 *      $fromPeg = 0
 *      $toPeg = 2
 *      $usePeg = 1
 *
 *      Is the $numberOfRings > 0? Yes
 *          <<< FIRST RECURSIVE CALL BEGIN >>>
 *          $numberOfRings = 1
 *          $fromPeg = 0
 *          $toPeg = 1
 *          $usePeg = 2
 *
 *          Is the $numberOfRings > 0? Yes
 *              <<< FIRST RECURSIVE CALL BEGIN >>>
 *              $numberOfRings = 0
 *              $fromPeg = 0
 *              $toPeg = 2
 *              $usePeg = 1
 *
 *              Is the $numberOfRings > 0? No
 *              <<< FIRST RECURSIVE CALL RETURN >>>
 *
 *          Move ring from peg 0 to peg 1
 *          $pegs = [
 *              [
 *                  0 => 3,
 *                  1 => 2
 *              ],
 *              [
 *                  0 => 1
 *              ],
 *              []
 *          ]
 *
 *              <<< SECOND RECURSIVE CALL BEGIN >>>
 *              $numberOfRings = 0
 *              $fromPeg = 2
 *              $toPeg = 1
 *              $usePeg = 0
 *
 *              Is $numberOfRings > 0? No
 *              <<< SECOND RECURSIVE CALL RETURN >>>
 *          <<< FIRST RECURSIVE CALL RETURN >>>
 *
 *      Move ring from peg 0 to peg 2
 *      $pegs = [
 *          [
 *              0 => 3
 *          ],
 *          [
 *              0 => 1
 *          ],
 *          [
 *              0 => 2
 *          ]
 *      ]
 *
 *          <<< SECOND RECURSIVE CALL BEGIN >>>
 *          $numberOfRings = 1
 *          $fromPeg = 1
 *          $toPeg = 2
 *          $usePeg = 0
 *
 *          Is $numberOfRings > 0? Yes
 *              <<< FIRST RECURSIVE CALL BEGIN >>>
 *              $numberOfRings = 0
 *              $fromPeg = 1
 *              $toPeg = 0
 *              $usePeg = 2
 *
 *              Is $numberOfRings > 0? No
 *              <<< FIRST RECURSIVE CALL RETURN >>>
 *
 *          Move ring from peg 1 to peg 2
 *          $pegs = [
 *              [
 *                  0 => 3
 *              ],
 *              [],
 *              [
 *                  0 => 2,
 *                  1 => 1
 *              ]
 *          ]
 *
 *              <<< SECOND RECURSIVE CALL BEGIN >>>
 *              $numberOfRings = 0
 *              $fromPeg = 0
 *              $toPeg = 2
 *              $usePeg = 1
 *
 *              Is $numberOfRings > 0? No
 *              <<< SECOND RECURSIVE CALL RETURN >>>
 *          <<< SECOND RECURSIVE CALL RETURN >>>
 *      <<< FIRST RECURSIVE CALL RETURN >>>
 *
 * Move ring from peg 0 to peg 1
 * $pegs = [
 *      [],
 *      [
 *          0 => 3
 *      ],
 *      [
 *          0 => 2,
 *          1 => 1
 *      ]
 * ]
 *
 *      <<< SECOND RECURSIVE CALL BEGIN >>>
 *      $numberOfRings = 2
 *      $fromPeg = 2
 *      $toPeg = 1
 *      $usePeg = 0
 *
 *      Is $numberOfRings > 0? Yes
 *          <<< FIRST RECURSIVE CALL BEGIN >>>
 *          $numberOfRings = 1
 *          $fromPeg = 2
 *          $toPeg = 0
 *          $usePeg = 1
 *
 *          Is $numberOfRings > 0? Yes
 *              <<< FIRST RECURSIVE CALL BEGIN >>>
 *              $numberOfRings = 0
 *              $fromPeg = 2
 *              $toPeg = 1
 *              $usePeg = 0
 *
 *              Is $numberOfRings > 0? No
 *              <<< FIRST RECURSIVE CALL RETURN
 *
 *          Move ring from peg 2 to peg 0
 *          $pegs = [
 *              [
 *                  0 => 1
 *              ],
 *              [
 *                  0 => 3
 *              ],
 *              [
 *                  0 => 2
 *              ]
 *          ]
 *
 *              <<< SECOND RECURSIVE CALL END >>>
 *              $numberOfRings = 0
 *              $fromPeg = 1
 *              $toPeg = 0
 *              $usePeg = 2
 *
 *              Is $numberOfRings > 0? No
 *              <<< SECOND RECURSIVE CALL RETURN >>>
 *          <<< FIRST RECURSIVE CALL RETURN >>>
 *
 *      Move ring from peg 2 to peg 1
 *      $pegs = [
 *          [
 *              0 => 1
 *          ],
 *          [
 *              0 => 3,
 *              1 => 2
 *          ],
 *          []
 *      ]
 *
 *          <<< SECOND RECURSIVE CALL BEGIN >>>
 *          $numberOfRings = 1
 *          $fromPeg = 0
 *          $toPeg = 1
 *          $usePeg = 2
 *
 *          Is $numberOfRings > 0? Yes
 *              <<< FIRST RECURSIVE CALL BEGIN >>>
 *              $numberOfRings = 0
 *              $fromPeg = 0
 *              $toPeg = 2
 *              $usePeg = 1
 *
 *              Is $numberOfRings > 0? No
 *              <<< FIRST RECURSIVE CALL RETURN >>>
 *
 *          Move ring from peg 0 to peg 1
 *          $pegs = [
 *              [],
 *              [
 *                  0 => 3,
 *                  1 => 2,
 *                  2 => 1
 *              ],
 *              []
 *          ]
 *
 *              <<< SECOND RECURSIVE CALL BEGIN >>>
 *              $numberOfRings = 0
 *              $fromPeg = 2
 *              $toPeg = 1
 *              $usePeg = 0
 *
 *              Is $numberOfRings > 0? No
 *              <<< SECOND RECURSIVE CALL RETURN >>>
 *          <<< SECOND RECURSIVE CALL RETURN >>>
 *      <<< SECOND RECURSIVE CALL RETURN >>>
 *
 * @param int $numberOfRings
 * @param array[\SplStack] $pegs
 * @param int $fromPeg
 * @param int $toPeg
 * @param int $usePeg
 */
function printTowerOfHanoiSteps($numberOfRings, $pegs, $fromPeg, $toPeg, $usePeg)
{
    if ($numberOfRings > 0) {
        printTowerOfHanoiSteps($numberOfRings - 1, $pegs, $fromPeg, $usePeg, $toPeg);
        printf('Move %d from peg %d to peg %d', $pegs[$fromPeg]->top(), $fromPeg, $toPeg);
        print PHP_EOL;
        $pegs[$toPeg]->push($pegs[$fromPeg]->top());
        $pegs[$fromPeg]->pop();
        printTowerOfHanoiSteps($numberOfRings - 1, $pegs, $usePeg, $toPeg, $fromPeg);
    }
}
                $to = 0;
            }
        } elseif ($i % PEG_COUNT == 2) {
            // Either move from peg 0 to peg $destination or peg $destination to peg 0
            if ($pegs[$destination]->isEmpty() || !$pegs[0]->isEmpty() && $pegs[0]->top() < $pegs[$destination]->top()) {
                $from = 0;
                $to = $destination;
            } else {
                $from = $destination;
                $to = 0;
            }
        } else {
            // Either move from peg $destination to peg $auxiliary or peg $auxiliary to peg $destination
            if ($pegs[$auxiliary]->isEmpty() || !$pegs[$destination]->isEmpty() && $pegs[$destination]->top() < $pegs[$auxiliary]->top()) {
                $from = $destination;
                $to = $auxiliary;
            } else {
                $from = $auxiliary;
                $to = $destination;
            }
        }
        $pegs[$to]->push($pegs[$from]->pop());
        printf('Move #%d: from peg %d to peg %d', $i, $from, $to);
        print PHP_EOL;
        $i++;
    }
}
$inputHelper = new InputHelper();
$numberOfRings = (int) $inputHelper->readInputFromStdIn('Enter the number of rings to move: ');
printTowerOfHanoiSteps($numberOfRings);