solved day 7 !!

This commit is contained in:
ryan 2023-09-30 19:15:28 -07:00
parent 666c81118f
commit 1fdb1ebc36
3 changed files with 1141 additions and 1 deletions

View File

@ -6,5 +6,6 @@ let () =
Day3.print ();
Day4.print ();
Day5.print ();
Day6.print ()
Day6.print ();
Day7.print ()
;;

1032
inputs/day7.tt Normal file

File diff suppressed because it is too large Load Diff

107
src/day7.ml Normal file
View File

@ -0,0 +1,107 @@
open Containers
type node =
| File of
{ name : string
; size : int
}
| Dir of
{ name : string
; parent : node option
; mutable children : node list
}
let get_dir_tree () =
let lines = List.drop 1 @@ Utils.lines_of_input 7 in
let line_num = ref 0 in
let tree = Dir { name = "/"; children = []; parent = None } in
let _ =
lines
|> List.fold_left
(fun node line ->
incr line_num;
match node with
| File _ -> failwith "current directory cannot be a file"
| Dir dir ->
(match%pcre line with
| {|\$ ls|} -> node
| {|dir (?<name>.*)|} ->
let new_dir = Dir { name; parent = Some (Dir dir); children = [] } in
dir.children <- new_dir :: dir.children;
node
| {|(?<size>\d+) (?<name>.*)|} ->
let new_file = File { name; size = int_of_string size } in
dir.children <- new_file :: dir.children;
node
| {|cd \.\.|} ->
(match dir.parent with
| Some parent -> parent
| _ ->
failwith
@@ Printf.sprintf
"ERROR:%d: cant cd .. because node '%s' has no parent"
!line_num
dir.name)
| {|cd (?<name>.*)|} ->
dir.children
|> List.find (fun child ->
match child with
| Dir child_dir -> String.Infix.(name = child_dir.name)
| _ -> false)
| line -> failwith @@ Printf.sprintf "failed to parse line '%s'" line))
tree
in
tree
;;
let rec get_node_size fn node =
let get_node_size' = get_node_size fn in
match node with
| File file -> file.size
| Dir dir ->
let size =
match List.reduce ( + ) @@ List.map get_node_size' dir.children with
| Some size -> size
| None -> 0
in
fn size;
size
;;
let part1 () =
let tree = get_dir_tree () in
let answer = ref 0 in
let build_answer dir_size =
if dir_size <= 100000 then answer := !answer + dir_size;
()
in
let _ = get_node_size build_answer tree in
!answer
;;
let part2 () =
let tree = get_dir_tree () in
let dir_sizes = ref [] in
let collect_dir_sizes dir_size =
dir_sizes := dir_size :: !dir_sizes;
()
in
let used_space = get_node_size collect_dir_sizes tree in
let total_space = 70000000 in
let required_space = 30000000 in
let free_space = total_space - used_space in
match
!dir_sizes
|> List.sort ( - )
|> List.drop_while (fun size -> size < required_space - free_space)
|> List.head_opt
with
| Some size -> size
| None -> failwith "not possible!!"
;;
let print () =
Printf.(
printf "Day 7.1: %d\n" @@ part1 ();
printf "Day 7.2: %d\n" @@ part2 ())
;;