12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- fun read file =
- let
- val inStream = TextIO.openIn file
- in
- (* TextIO.inputAll returns a TextIO.vector, which is a string. *)
- TextIO.inputAll inStream
- end;
- val newline_tokenizer = String.tokens (fn c => c = #"\n");
- val space_tokenizer = String.tokens (fn c => c = #" ");
- datatype HorizontalChange = HorizontalChange of int;
- datatype DepthChange = DepthChange of int;
- type change = HorizontalChange * DepthChange;
- fun direction_to_factor dir =
- case dir of
- "forward" => 1
- | "backward" => ~1
- | "up" => ~1
- | "down" => 1
- | _ => raise Fail "unrecognized direction";
- fun calc_change line =
- let
- val (dir::len_as_str::_) = space_tokenizer line;
- val len = case Int.fromString len_as_str of
- SOME number => number
- | NONE => raise Fail "encountered a non-int string";
- val dir_factor = direction_to_factor dir;
- in
- case dir of
- "forward" => (HorizontalChange (dir_factor * len), DepthChange 0)
- | "backward" => (HorizontalChange (dir_factor * len), DepthChange 0)
- | "up" => (HorizontalChange 0, DepthChange (dir_factor * len))
- | "down" => (HorizontalChange 0, DepthChange (dir_factor * len))
- | _ => raise Fail "unrecognized direction"
- end;
- fun plus_changes (change1, change2) =
- let
- val (HorizontalChange h1, DepthChange d1) = change1;
- val (HorizontalChange h2, DepthChange d2) = change2;
- in
- (HorizontalChange (h1 + h2), DepthChange (d1 + d2))
- end;
- val initial_change = (HorizontalChange 0, DepthChange 0): change;
- val str = read "input";
- val lines = newline_tokenizer str;
- let
- val (HorizontalChange h, DepthChange d) =
- foldl (fn (line, acc) => plus_changes (acc, (calc_change line)))
- initial_change
- lines;
- val solution = h * d;
- in
- solution
- end;
|