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));