Add Towers of Hanoi exercise
This commit is contained in:
parent
5f57627225
commit
45c27ba067
81
18_towers_of_hanoi.lua
Normal file
81
18_towers_of_hanoi.lua
Normal file
@ -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 = <rod>, to = <rod>} 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())
|
Loading…
x
Reference in New Issue
Block a user