72 lines
1.9 KiB
OCaml
72 lines
1.9 KiB
OCaml
let load_file fname =
|
|
match In_channel.with_open_text fname In_channel.input_line with
|
|
| Some x -> x
|
|
| None -> failwith "load_file"
|
|
|
|
(*
|
|
let disk_print disk =
|
|
let prnt c = if c = -1 then print_char '.' else print_int c in
|
|
Array.iter prnt disk;
|
|
print_newline();
|
|
*)
|
|
let disk_size disk_str =
|
|
let rec impl acc disk_str =
|
|
let len = String.length disk_str in
|
|
match len with
|
|
| 0 -> acc
|
|
| len ->
|
|
let h = int_of_string (String.sub disk_str 0 1) in
|
|
flush_all ();
|
|
let t = String.sub disk_str 1 (len - 1) in
|
|
flush_all ();
|
|
impl (acc + h) t
|
|
in
|
|
impl 0 disk_str
|
|
|
|
let disk_init disk_str =
|
|
let size = disk_size disk_str in
|
|
let disk = Array.make size (-1) in
|
|
let rec add_id offset id = function
|
|
| 0 -> offset
|
|
| x ->
|
|
disk.(offset) <- id;
|
|
add_id (offset + 1) id (x - 1)
|
|
in
|
|
let rec impl offset id disk_str =
|
|
match String.length disk_str with
|
|
| 0 -> ()
|
|
| 1 ->
|
|
let _ = add_id offset id (int_of_string (String.sub disk_str 0 1)) in
|
|
()
|
|
| str_len ->
|
|
let len = int_of_string (String.sub disk_str 0 1) in
|
|
impl
|
|
(add_id offset id len + int_of_string (String.sub disk_str 1 1))
|
|
(id + 1)
|
|
(String.sub disk_str 2 (str_len - 2))
|
|
in
|
|
impl 0 0 disk_str;
|
|
disk
|
|
|
|
let disk_defrag disk =
|
|
let rec impl front back =
|
|
if front >= back then ()
|
|
else if disk.(front) <> -1 then impl (front + 1) back
|
|
else if disk.(back) = -1 then impl front (back - 1)
|
|
else (
|
|
disk.(front) <- disk.(back);
|
|
disk.(back) <- -1;
|
|
impl (front + 1) (back - 1))
|
|
in
|
|
impl 0 (Array.length disk - 1);
|
|
disk
|
|
|
|
let calc_checksum disk =
|
|
let rec impl acc idx =
|
|
if disk.(idx) = -1 then acc else impl (acc + (disk.(idx) * idx)) (idx + 1)
|
|
in
|
|
impl 0 0
|
|
|
|
let part1 str = disk_init str |> disk_defrag |> calc_checksum
|
|
let _ = Aoc.main load_file [ (string_of_int, part1) ]
|