1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- (* open IntInf; *)
- fun compose a b =
- (fn input => b (a input));
- (* fun chain procs = *)
- (* foldl (fn (proc, composed_procs) => *)
- (* (fn input => *)
- (* proc (composed_procs input))) *)
- (* (fn any => any) *)
- (* procs; *)
- val block_tokenizer = StringExtra.split "\n\n";
- val newline_tokenizer = String.tokens (fn c => c = #"\n");
- val str = FileExtra.read "input";
- val parts = block_tokenizer str;
- val number_sequence =
- map (fn num_as_str =>
- case Int.fromString num_as_str of
- SOME number => number
- | NONE =>
- raise Fail "encountered a non-int string")
- (String.tokens (fn c => c = #",") (hd parts));
- val board_strings = tl parts;
- val boards = map Board.fromString board_strings;
- val first_board = hd boards;
- val rows_and_cols = ListExtra.flatten (map Board.getAllRowsAndColumns boards);
- val seq_len = List.length number_sequence;
- fun find_board (nil, number_sequence) = NONE
- | find_board (boards as (board::rest), number_sequence) =
- if Board.has_completed_line (board, number_sequence)
- then
- SOME board
- else
- find_board (rest, number_sequence);
- fun calculate_score (board, num_seq) =
- let
- val finishing_num = List.last num_seq;
- val board_score = Board.sum_unselected (board, num_seq);
- val _ = print ("finishing num: " ^ (Int.toString finishing_num) ^ "\n");
- val _ = print ("board score: " ^ (Int.toString board_score) ^ "\n");
- in
- board_score * finishing_num
- end;
- fun try_sequences (boards, num_sequence) =
- let
- val max_prefix_len = List.length num_sequence;
- in
- let
- fun iter (nil, prefix_len) = raise Fail "no more boards"
- | iter ([board], prefix_len) =
- let
- val prefix = List.take (num_sequence, prefix_len);
- in
- (* repeat until the last board was solved *)
- case find_board ([board], prefix) of
- SOME board => calculate_score (board, prefix)
- | NONE => iter ([board], (prefix_len + 1))
- end
- | iter (remaining_boards, prefix_len) =
- if prefix_len < max_prefix_len
- then
- let
- val prefix = List.take (num_sequence, prefix_len);
- val _ = print ("prefix length: " ^ (Int.toString prefix_len) ^ "\n");
- val _ = print ("boards remaining: " ^ (Int.toString (length remaining_boards)) ^ "\n");
- val result_for_prefix = find_board (remaining_boards, prefix);
- in
- case result_for_prefix of
- (* try with the board removed *)
- SOME winning_board => iter ((ListExtra.remove remaining_boards winning_board),
- prefix_len)
- | NONE => iter (remaining_boards, prefix_len + 1)
- end
- else
- raise Fail "no winning board for any prefix of number sequence";
- in
- iter (boards, 0)
- end
- end;
- val solution = try_sequences (boards, number_sequence);
- solution;
- (* val result = Board.sum_unselected (hd boards) [50,98,65,14,47,40,84,0,37]; *)
|