You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			79 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			OCaml
		
	
			
		
		
	
	
			79 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			OCaml
		
	
| (* Common util. Should probably put this in a module or something.. *)
 | |
| let get_one_line file =
 | |
|   try Some (input_line file) with
 | |
|     End_of_file -> None
 | |
| 
 | |
| let get_lines file =
 | |
|   let rec input lines =
 | |
|     match get_one_line file with
 | |
|       Some line -> input (line :: lines)
 | |
|     | None -> List.rev lines
 | |
|   in input []
 | |
| 
 | |
| let read_file file =
 | |
|   let channel = open_in(file) in
 | |
|   get_lines channel
 | |
| 
 | |
| let (<<) f g x = f(g(x))
 | |
| let (>>) f g x = g(f(x))
 | |
| 
 | |
| let rec take n (x :: xs) = (* take the first n elements *)
 | |
|   match n with
 | |
|   | 0 -> []
 | |
|   | n -> x :: (take (n-1) xs)
 | |
| 
 | |
| let rec drop n l = (* drop the first n elemnts *)
 | |
|   match n with
 | |
|   | 0 -> l
 | |
|   | n -> drop (n-1) @@ List.tl l
 | |
| 
 | |
| let sub_list start length = (* sub list from start *)
 | |
|   take length >> drop start
 | |
| 
 | |
| let list_sum = List.fold_left (+) 0
 | |
| 
 | |
| let list_max l = List.fold_left (fun acc x -> if x > acc then x else acc) (List.hd l) l
 | |
| let list_min l = List.fold_left (fun acc x -> if x < acc then x else acc) (List.hd l) l
 | |
| 
 | |
| let range start len = (* makes a new list from start with length len *)
 | |
|   List.init len (fun x -> x + 0) |> List.map (fun x -> x + start)
 | |
| 
 | |
| let flip f x y = f y x
 | |
| 
 | |
| (* --- *)
 | |
| 
 | |
| let has_adders l target = (* do any 2 elements of l add up to target *)
 | |
|   match List.find_opt (fun x ->
 | |
|       match List.find_opt (fun y -> x != y && x + y = target) l with
 | |
|       | Some _ -> true
 | |
|       | None -> false
 | |
|     ) l with
 | |
|   | Some _ -> true
 | |
|   | None -> false
 | |
| 
 | |
| let rec first_without_adders pre lines =
 | |
|   let x :: xs = lines in (* match out the head and tail *)
 | |
|   let cur = List.nth lines pre in (* grab the first row after the preamble *)
 | |
|   let sub = take pre lines in (* grab the preamble sublist *)
 | |
|   if has_adders sub cur (* chechk for adders *)
 | |
|   then first_without_adders pre xs (* if it has adders, recurse with the tail of the original list *)
 | |
|   else cur (* no adders! return this one *)
 | |
| 
 | |
| let rec all_sub_lists = function (* all combinations of sub-lists *)
 | |
|   | [] -> []
 | |
|   | xs ->
 | |
|       range 0 (List.length xs)
 | |
|       |> List.map (fun len' -> sub_list 0 len' xs)
 | |
|       |> flip List.append (all_sub_lists @@ List.tl xs)
 | |
| 
 | |
| let () =
 | |
|   let lines = read_file "day9.txt" |> List.map int_of_string in
 | |
| 
 | |
|   let first = lines |> first_without_adders 25 in
 | |
|   Printf.printf "first without 2 adders %i\n" first;
 | |
| 
 | |
|   let all_subs = all_sub_lists lines in
 | |
|   let our_range = List.find (fun l -> list_sum l = first) all_subs in
 | |
|   let our_sum = (list_max our_range) + (list_min our_range) in
 | |
|   Printf.printf "sum %i\n" our_sum;
 |