diff --git a/17_towers_of_hanoi.lua b/17_towers_of_hanoi.lua new file mode 100644 index 0000000..c38b8ab --- /dev/null +++ b/17_towers_of_hanoi.lua @@ -0,0 +1,81 @@ +-- The Towers of Hanoi is a mathematical puzzle consisting of three +-- rods and a number of disks of various diameters which can slide +-- onto any rod. Initially, all the disks are stacked in decreasing +-- size order so that they form a conical shape. The objective to +-- move the entire stack to one of the other two rods, with each move +-- consisting of taking the uppermost disk from one of the rods and +-- placing it on top of the stack on another one. A disk cannot be +-- placed on top of a disk of smaller diameter. +-- +-- Write a function which generates an optimal solution to the puzzle. +-- The rods are numbered 1-3, with the stack starting on rod 1. Your +-- function should return a list of {from = , to = } tables, +-- and will receive the number of disks in the original stack as its +-- argument. +-- +-- Solution -------------------------------------------------------------------- +function towers_of_hanoi_solution(disk_count) + -- Your implementation here +end + +-- Tests ----------------------------------------------------------------------- + +local luaunit = require("luaunit.luaunit") + +local function disk_stack(count) + local stack = {} + for i = count, 1, -1 do table.insert(stack, i) end + return stack +end + +local function assert_valid(state) + for _, rod in ipairs(state) do + local previous = rod[1] + for _, disk in ipairs(rod) do + luaunit.assertTrue(disk <= previous) + previous = disk + end + end + return true +end + +local function assert_solved(state, disk_count) + luaunit.assertEquals(state[1], {}) + if #state[2] ~= 0 then + luaunit.assertEquals(state[2], disk_stack(disk_count)) + luaunit.assertEquals(state[3], {}) + else + luaunit.assertEquals(state[2], {}) + luaunit.assertEquals(state[3], disk_stack(disk_count)) + end +end + +local function assert_is_solution(solution, disk_count) + local state = {disk_stack(disk_count), {}, {}} + for i, move in ipairs(solution) do + local disk = table.remove(state[move.from]) + table.insert(state[move.to], disk) + assert_valid(state) + end + assert_solved(state, disk_count) +end + +local function test_with_count(disk_count) + local solution = towers_of_hanoi_solution(disk_count) + assert_is_solution(solution, disk_count) + luaunit.assertEquals(#solution, 2 ^ disk_count - 1) +end + +function test_with_1_disk() + test_with_count(1) +end + +function test_with_7_disks() + test_with_count(7) +end + +function test_with_12_disks() + test_with_count(12) +end + +os.exit(luaunit.LuaUnit.run())