solved day 7 !!
This commit is contained in:
parent
666c81118f
commit
1fdb1ebc36
|
|
@ -6,5 +6,6 @@ let () =
|
|||
Day3.print ();
|
||||
Day4.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