Below is the code we used in class.
In the cslab, it can also be found in /cslab/class/cs243/hanoi.ml
.
fun makeSet(0) = ([], [] : int list, [] : int list) | makeSet(n) = (n::(#1( makeSet(n-1))), [], []) ; fun pegInOrder([]) = true | pegInOrder(x::[]) = true | pegInOrder(x::y::rest) = x > y andalso pegInOrder(y::rest); fun pegContainsDisk(disk, []) = false | pegContainsDisk(disk, x::rest) = if disk = x then true else pegContainsDisk(disk, rest); fun booleanToInteger(true) = 1 | booleanToInteger(false) = 0; fun setContainsDiskOnce(disk, (peg1, peg2, peg3)) = booleanToInteger(pegContainsDisk(disk, peg1)) + booleanToInteger(pegContainsDisk(disk, peg2)) + booleanToInteger(pegContainsDisk(disk, peg3)) = 1; fun setContainsDisks(0, pegs) = true | setContainsDisks(n, pegs) = setContainsDiskOnce(n, pegs) andalso setContainsDisks(n-1, pegs); fun numDisks([], [], []) = 0 | numDisks([], [], a::rest) = let val highest = numDisks([], [], rest); in if a < highest then highest else a end | numDisks([], a::rest, peg3) = let val highest = numDisks([], rest, peg3); in if a < highest then highest else a end | numDisks(a::rest, peg2, peg3) = let val highest = numDisks(rest, peg2, peg3); in if a < highest then highest else a end; fun setValidState(pegs as (peg1, peg2, peg3)) = setContainsDisks( numDisks(pegs), pegs) andalso pegInOrder(peg1) andalso pegInOrder(peg2) andalso pegInOrder(peg3); fun hanoi(pegs) = let fun move((x::rest, peg2, peg3), 1, 2) = (rest, x::peg2, peg3) | move((x::rest, peg2, peg3), 1, 3) = (rest, peg2, x::peg3) | move((peg1, x::rest, peg3), 2, 1) = (x::peg1, rest, peg3) | move((peg1, x::rest, peg3), 2, 3) = (peg1, rest, x::peg3) | move((peg1, peg2, x::rest), 3, 1) = (x::peg1, peg2, rest) | move((peg1, peg2, x::rest), 3, 2) = (peg1, x::peg2, rest); fun solveHanoi(1, pegs, from, to, use) = move(pegs, from, to) | solveHanoi(n, pegs, from, to, use) = let val step1 = solveHanoi(n-1, pegs, from, use, to); val step2 = move(step1, from, to); val step3 = solveHanoi(n-1, step2, use, to, from); in step3 end; in solveHanoi(numDisks(pegs), pegs, 1, 3, 2) end; fun cheatHanoi(peg1, peg2, peg3) = (peg3, peg2, peg1); fun factorial(0) = 1 | factorial(n) = n * factorial(n-1); val counter = ref 0; fun monitor(x) = (counter := !counter + 1; x); fun factorialM(0) = 1 | factorialM(n) = n * monitor(factorialM(n-1)); !counter; fun monitor2(x) = (print(Int.toString(x)^"\n"); x); fun factorialM2(0) = 1 | factorialM2(n) = n * monitor2(factorialM2(n-1)); fun factorialMG(n, m) = let fun factorial(0) = 1 | factorial(x) = x * m(factorial(x-1)); in factorial(n) end; fun fibMG(n, m) = let fun fib(1) = 1 | fib(2) = 1 | fib(x) = m(fib(x-1)) + m(fib(x-2)); in fib(n) end; fun listToString(list) = let fun listToStringHelper([]) = "" | listToStringHelper([a]) = Int.toString(a) | listToStringHelper(x::rest) = Int.toString(x) ^ "," ^ listToStringHelper(rest); in "[" ^ listToStringHelper(list) ^ "]" end; fun printSet(peg1, peg2, peg3) = print("(" ^ listToString(peg1) ^ "," ^ listToString(peg2) ^ "," ^ listToString(peg3) ^ ")\n"); fun hanoiM(pegs, m) = let fun move((x::rest, peg2, peg3), 1, 2) = (rest, x::peg2, peg3) | move((x::rest, peg2, peg3), 1, 3) = (rest, peg2, x::peg3) | move((peg1, x::rest, peg3), 2, 1) = (x::peg1, rest, peg3) | move((peg1, x::rest, peg3), 2, 3) = (peg1, rest, x::peg3) | move((peg1, peg2, x::rest), 3, 1) = (x::peg1, peg2, rest) | move((peg1, peg2, x::rest), 3, 2) = (peg1, x::peg2, rest); fun solveHanoi(1, pegs, from, to, use) = m(move(pegs, from, to)) | solveHanoi(n, pegs, from, to, use) = let val step1 = solveHanoi(n-1, pegs, from, use, to); val step2 = m(move(step1, from, to)); val step3 = solveHanoi(n-1, step2, use, to, from); in step3 end; in solveHanoi(numDisks(pegs), pegs, 1, 3, 2) end; fun regular(set) = hanoiM(set, fn (x) => x); fun check(set) = hanoiM(set, fn (x) => (if not (setValidState(x)) then printSet(x) else () ; x)); fun watch(set) = hanoiM(set, fn (x) => (printSet(x); x));