02.sml 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. (* open IntInf; *)
  2. fun compose a b =
  3. (fn input => b (a input));
  4. (* fun chain procs = *)
  5. (* foldl (fn (proc, composed_procs) => *)
  6. (* (fn input => *)
  7. (* proc (composed_procs input))) *)
  8. (* (fn any => any) *)
  9. (* procs; *)
  10. val block_tokenizer = StringExtra.split "\n\n";
  11. val newline_tokenizer = String.tokens (fn c => c = #"\n");
  12. val str = FileExtra.read "input";
  13. val parts = block_tokenizer str;
  14. val number_sequence =
  15. map (fn num_as_str =>
  16. case Int.fromString num_as_str of
  17. SOME number => number
  18. | NONE =>
  19. raise Fail "encountered a non-int string")
  20. (String.tokens (fn c => c = #",") (hd parts));
  21. val board_strings = tl parts;
  22. val boards = map Board.fromString board_strings;
  23. val first_board = hd boards;
  24. val rows_and_cols = ListExtra.flatten (map Board.getAllRowsAndColumns boards);
  25. val seq_len = List.length number_sequence;
  26. fun find_board (nil, number_sequence) = NONE
  27. | find_board (boards as (board::rest), number_sequence) =
  28. if Board.has_completed_line (board, number_sequence)
  29. then
  30. SOME board
  31. else
  32. find_board (rest, number_sequence);
  33. fun calculate_score (board, num_seq) =
  34. let
  35. val finishing_num = List.last num_seq;
  36. val board_score = Board.sum_unselected (board, num_seq);
  37. val _ = print ("finishing num: " ^ (Int.toString finishing_num) ^ "\n");
  38. val _ = print ("board score: " ^ (Int.toString board_score) ^ "\n");
  39. in
  40. board_score * finishing_num
  41. end;
  42. fun try_sequences (boards, num_sequence) =
  43. let
  44. val max_prefix_len = List.length num_sequence;
  45. in
  46. let
  47. fun iter (nil, prefix_len) = raise Fail "no more boards"
  48. | iter ([board], prefix_len) =
  49. let
  50. val prefix = List.take (num_sequence, prefix_len);
  51. in
  52. (* repeat until the last board was solved *)
  53. case find_board ([board], prefix) of
  54. SOME board => calculate_score (board, prefix)
  55. | NONE => iter ([board], (prefix_len + 1))
  56. end
  57. | iter (remaining_boards, prefix_len) =
  58. if prefix_len < max_prefix_len
  59. then
  60. let
  61. val prefix = List.take (num_sequence, prefix_len);
  62. val _ = print ("prefix length: " ^ (Int.toString prefix_len) ^ "\n");
  63. val _ = print ("boards remaining: " ^ (Int.toString (length remaining_boards)) ^ "\n");
  64. val result_for_prefix = find_board (remaining_boards, prefix);
  65. in
  66. case result_for_prefix of
  67. (* try with the board removed *)
  68. SOME winning_board => iter ((ListExtra.remove remaining_boards winning_board),
  69. prefix_len)
  70. | NONE => iter (remaining_boards, prefix_len + 1)
  71. end
  72. else
  73. raise Fail "no winning board for any prefix of number sequence";
  74. in
  75. iter (boards, 0)
  76. end
  77. end;
  78. val solution = try_sequences (boards, number_sequence);
  79. solution;
  80. (* val result = Board.sum_unselected (hd boards) [50,98,65,14,47,40,84,0,37]; *)