-
Notifications
You must be signed in to change notification settings - Fork 0
/
day5-1.ml
71 lines (62 loc) · 2.28 KB
/
day5-1.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
open Core
let input_file = "day5.input"
module Config =
struct
type t = char list array
let construct (lines: string list): t =
match lines with
[] -> raise (Failure "Precondition error.")
| nums::boxes -> (
(* Get the number of columns from the first row *)
let cols = nums |> String.split ~on:' ' |> List.count ~f:(fun s -> not (String.is_empty s)) in
let config = Array.init cols ~f:(const []) in
let addRow line =
for col = 0 to cols - 1 do
let idx = 4 * col + 1 in
let c = if String.length line > idx then String.get line idx else ' ' in
if not (Char.equal c ' ') then config.(col) <- c::config.(col)
done
in
List.iter boxes ~f:addRow;
config
)
let moveOne (config: t) (src: int) (dst: int) : unit =
match config.(src) with
[] -> raise (Failure "Precondition error.")
| c::cs -> (
config.(src) <- cs;
config.(dst) <- c::config.(dst)
)
let move (config: t) ((num, src, dst): int * int * int) : unit =
let moveOne = fun () -> moveOne config src dst in
let rec move' num = if not (num = 0) then (moveOne (); move' (num - 1)) in
move' num
let getTop (config: t): string =
Array.filter_map config ~f:List.hd |> Array.to_list |> String.of_char_list
end
let split_input: string list -> string list * string list =
let rec split_input' block1 block2 =
match block2 with
[] -> (block1, block2)
| l::ls -> if String.equal l "" then (block1, ls) else split_input' (l::block1) ls
in
split_input' []
let construct_and_simulate (config, actions) =
let config = Config.construct config in
let actions = List.filter_map actions ~f:(fun action ->
if String.is_empty action then None else
let words = String.split ~on:' ' action in
let num = List.nth_exn words 1 |> Int.of_string in
let src = List.nth_exn words 3 |> Int.of_string in
let dst = List.nth_exn words 5 |> Int.of_string in
Some (num, src - 1, dst - 1)
) in
let move = Config.move config in
List.iter actions ~f:move;
Config.getTop config
let main =
input_file
|> Stdio.In_channel.read_lines
|> split_input
|> construct_and_simulate
|> Stdio.Out_channel.print_endline