/****************************************************************************** * This program solves the Tower of Hanoi * * Copyright © 2021 Richard Lesh. All rights reserved. *****************************************************************************/ #undef NDEBUG #include "Utils.hpp" #include #include #include #include #include using namespace Utils; using namespace std; static int NUM_DISKS = 0; static vector> PEGS(3); static int MOVE_NUMBER = 0; static int PRINT_MOD = 1; static void print_pegs() noexcept { cout << string("Move: ") + to_string(MOVE_NUMBER) << endl; for (auto i = 0; i < NUM_DISKS; ++i) { for (auto j = 0; j < 3; ++j) { int const DISK = PEGS[j][i]; cout << (DISK == 0 ? "|" : to_string(DISK)); cout << " "; } cout << endl; } cout << "=========" << endl; cout << endl; } static void move(int source, int dest) noexcept { ++MOVE_NUMBER; int disk = 0; for (auto i = 0; i < NUM_DISKS; ++i) { if (PEGS[source][i] != 0) { disk = PEGS[source][i]; PEGS[source][i] = 0; break; } } int pos = NUM_DISKS - 1; for (auto i = 0; i < NUM_DISKS; ++i) { if (PEGS[dest][i] != 0) { pos = i - 1; break; } } PEGS[dest][pos] = disk; if (MOVE_NUMBER % PRINT_MOD == 0) { print_pegs(); } } static void solve(int num_disks, int source, int dest, int aux) noexcept { if (num_disks == 1) { move(source, dest); } else { solve(num_disks - 1, source, aux, dest); move(source, dest); solve(num_disks - 1, aux, dest, source); } } int main(int argc, char **argv) { if (argc != 2) { cout << "Syntax: " << argv[0] << " [disks]" << endl; exit(1); } NUM_DISKS = Utils::stoiWithDefault(string(argv[1]), 3); for (auto i = 0; i < 3; ++i) { vector positions = {}; for (auto j = 0; j < NUM_DISKS; ++j) { Utils::push(positions, 0); } PEGS[i] = positions; } for (auto i = 0; i < NUM_DISKS; ++i) { PEGS[0][i] = i + 1; } int const SOLUTION_STEPS = int(pow(2., NUM_DISKS) - 1.); PRINT_MOD = SOLUTION_STEPS / 5 + 2; PRINT_MOD -= PRINT_MOD % 5; PRINT_MOD = max(PRINT_MOD, 1); print_pegs(); solve(NUM_DISKS, 0, 2, 1); if (MOVE_NUMBER % PRINT_MOD != 0) { print_pegs(); } return 0; }