This commit is contained in:
2024-12-09 22:29:06 +01:00
parent 233a6d211d
commit cc503f93ea

107
9/main.ml Normal file
View File

@@ -0,0 +1,107 @@
open Printf;;
open String;;
let rec list_of_lines in_file =
try
let line = input_line in_file in
line :: list_of_lines(in_file)
with End_of_file ->
close_in in_file;
[]
let parse_filesystem_block index length =
if index mod 2 == 0 then
Array.init length (fun x -> index / 2)
else
Array.init length (fun x -> (-1))
let digit_code_to_int c =
int_of_char c - int_of_char '0'
let rec fix_file_layout_inner front_index back_index file_layout =
if front_index >= back_index then
()
else if file_layout.(front_index) >= 0 then
fix_file_layout_inner (front_index + 1) back_index file_layout
else if file_layout.(back_index) < 0 then
fix_file_layout_inner front_index (back_index - 1) file_layout
else begin
file_layout.(front_index) <- file_layout.(back_index);
file_layout.(back_index) <- (-1);
fix_file_layout_inner (front_index + 1) (back_index - 1) file_layout
end
let fix_file_layout file_layout =
let array_copy = Array.copy file_layout in
fix_file_layout_inner 0 (Array.length array_copy - 1) array_copy;
array_copy
let rec get_repeated_count array value index step =
try
if array.(index) != value then
0
else
1 + get_repeated_count array value (index + step) step
with Invalid_argument _ -> 0
let rec try_move_file_no_fragment file_id file_index file_length file_layout front_index =
if front_index >= file_index then
()
else if file_layout.(front_index) >= 0 then
try_move_file_no_fragment file_id file_index file_length file_layout (front_index + 1)
else
let free_space_length = get_repeated_count file_layout (-1) front_index 1 in
if free_space_length < file_length then
try_move_file_no_fragment file_id file_index file_length file_layout (front_index + free_space_length)
else begin
Seq.ints 0
|> Seq.take file_length
|> Seq.iter (
fun i ->
file_layout.(front_index + i) <- file_id;
file_layout.(file_index + i) <- (-1));
end
let rec fix_file_layout_defragment_inner back_index file_layout =
if back_index < 0 then
()
else if file_layout.(back_index) < 0 then
let free_space_length = get_repeated_count file_layout (-1) back_index (-1) in
fix_file_layout_defragment_inner (back_index - free_space_length) file_layout
else
let file_id = file_layout.(back_index) in
let file_length = get_repeated_count file_layout file_id back_index (-1) in
let new_back_index = back_index - file_length in
try_move_file_no_fragment file_id (new_back_index + 1) file_length file_layout 0;
fix_file_layout_defragment_inner new_back_index file_layout
let fix_file_layout_defragment file_layout =
let array_copy = Array.copy file_layout in
fix_file_layout_defragment_inner (Array.length file_layout - 1) array_copy;
array_copy
let get_checksum file_layout =
file_layout
|> Array.to_seq
|> Seq.mapi (fun i x -> i * x)
|> Seq.filter (fun x -> x >= 0)
|> Seq.fold_left Int.add 0
let () =
let f = open_in "input.txt" in
let disk_map = f
|> list_of_lines
|> List.hd
|> String.to_seq
|> Seq.map digit_code_to_int
|> List.of_seq in
let file_layout = disk_map
|> List.mapi (fun i x -> parse_filesystem_block i x)
|> Array.concat in
let fixed_layout = fix_file_layout file_layout in
let result = get_checksum fixed_layout in
printf "%d\n%!" result;
let fixed_layout_defragment = fix_file_layout_defragment file_layout in
let result2 = get_checksum fixed_layout_defragment in
printf "%d\n"result2