solved day 7 !!
This commit is contained in:
parent
666c81118f
commit
1fdb1ebc36
|
|
@ -6,5 +6,6 @@ let () =
|
||||||
Day3.print ();
|
Day3.print ();
|
||||||
Day4.print ();
|
Day4.print ();
|
||||||
Day5.print ();
|
Day5.print ();
|
||||||
Day6.print ()
|
Day6.print ();
|
||||||
|
Day7.print ()
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
1032
inputs/day7.tt
Normal file
1032
inputs/day7.tt
Normal file
File diff suppressed because it is too large
Load Diff
107
src/day7.ml
Normal file
107
src/day7.ml
Normal 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 ())
|
||||||
|
;;
|
||||||
Loading…
Reference in New Issue
Block a user