summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBrian Chu <brianmchu42@gmail.com>2022-01-27 13:43:15 -0800
committerBrian Chu <brianmchu42@gmail.com>2022-01-27 13:43:15 -0800
commitfacc9b10d3df43354e684882505fd07a3bc0985f (patch)
treedc951c96a7c7466d4cb7cb1f670c043fddb6cb7a
downloadAdventOfCode2017-facc9b10d3df43354e684882505fd07a3bc0985f.tar.gz
solutions up to day 4
-rw-r--r--.gitignore1
-rw-r--r--day1.ml39
-rw-r--r--day2.ml39
-rw-r--r--day3.ml24
-rw-r--r--day4.ml38
5 files changed, 141 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2211df6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.txt
diff --git a/day1.ml b/day1.ml
new file mode 100644
index 0000000..6e95cfb
--- /dev/null
+++ b/day1.ml
@@ -0,0 +1,39 @@
+#use "topfind";;
+#thread;;
+#require "core";;
+#require "stdio";;
+
+open Core
+open Stdio
+
+let captcha = In_channel.read_all "day1.txt"
+              |> String.strip
+              |> String.to_list
+              |> List.map ~f:(fun x -> Char.to_int x - Char.to_int '0')
+
+let rec last = function
+  | [] -> assert false
+  | [x] -> x
+  | x::xs -> last xs
+
+let rec init = function
+  | [] -> []
+  | [x] -> []
+  | x::xs -> x::(init xs)
+
+let rotate_once l = (last l)::(init l)
+
+let rec rotate n l =
+  match n with
+  | 0 -> l
+  | _ -> rotate (n-1) (rotate_once l)
+
+let neighbor_sums n l =
+  let rotated = rotate n l in
+    Caml.List.combine l rotated
+    |> List.map ~f:(fun (x, y) -> if x = y then x else 0)
+    |> List.fold_left ~f:(+) ~init:0
+
+let () =
+  neighbor_sums 1 captcha |> Printf.printf "%d\n";
+  neighbor_sums ((List.length captcha) / 2) captcha |> Printf.printf "%d\n"
diff --git a/day2.ml b/day2.ml
new file mode 100644
index 0000000..2843dcd
--- /dev/null
+++ b/day2.ml
@@ -0,0 +1,39 @@
+#use "topfind";;
+#thread;;
+#require "core";;
+#require "stdio";;
+#require "csv";;
+
+open Core
+open Stdio
+
+let spreadsheet = Csv.load ~separator:'\t' "day2.txt"
+                  |> List.map ~f:(List.map ~f:int_of_string)
+
+let minmax = List.fold_left
+               ~init:(Int.max_value, Int.min_value)
+               ~f:(fun (lmin, lmax) x -> (min x lmin, max x lmax))
+
+let part1 l = List.map ~f:minmax l
+              |> List.map ~f:(fun (lmin, lmax) -> lmax - lmin)
+              |> List.fold_left ~f:(+) ~init:0
+
+let rec dividend row =
+  let divisible a b =
+    a mod b = 0 || b mod a = 0 in
+  let divide a b =
+    if a mod b = 0 then a/b else b/a in
+
+  match row with
+  | [] -> 0
+  | h::t ->
+     match List.find t ~f:(divisible h) with
+     | Some x -> divide h x
+     | None -> dividend t
+
+let part2 l = List.map ~f:dividend l
+              |> List.fold_left ~f:(+) ~init:0
+
+let () =
+  Printf.printf "%d\n" (part1 spreadsheet);
+  Printf.printf "%d\n" (part2 spreadsheet)
diff --git a/day3.ml b/day3.ml
new file mode 100644
index 0000000..bcca156
--- /dev/null
+++ b/day3.ml
@@ -0,0 +1,24 @@
+open Float
+
+let input = 265149
+
+let coordinates n =
+    let k = int_of_float (ceil (((sqrt (float_of_int n)) -. 1.) /. 2.)) in
+    let t = 1 + (2 * k) in
+    let m = int_of_float ((float_of_int t) ** 2.) in
+    let t = t - 1 in
+    if n >= m - t then
+        (k - (m - n), -k)
+    else if n >= m - (2 * t) then
+        (-k, -k + (m - n))
+    else if n >= m - (3 * t) then
+        (-k + (m - n), k)
+    else
+        (k, k - (m - n - t))
+
+let () =
+    let (x, y) = coordinates input in
+        Printf.printf "%d\n" (Int.abs x + Int.abs y)
+
+        
+(* Part 2 is listed on OEIS *)
diff --git a/day4.ml b/day4.ml
new file mode 100644
index 0000000..e058aec
--- /dev/null
+++ b/day4.ml
@@ -0,0 +1,38 @@
+#use "topfind";;
+#thread;;
+#require "core";;
+#require "stdio";;
+
+open Core
+open Stdio
+
+let passphrases = In_channel.read_lines "day4.txt"
+                  |> List.map ~f:(fun x -> String.strip x |> String.split ~on:' ')
+
+
+let passphrase_set_lengths p =
+  let toSet strings =
+    List.fold ~f:Set.add ~init:(Set.empty (module String)) strings in
+  List.map ~f:toSet p |> List.map ~f:Set.length
+
+let passphrase_lengths = List.map ~f:List.length
+
+let rec has_anagram passphrase =
+  let string_to_set =
+    String.fold ~f:Set.add ~init:(Set.empty (module Char)) in
+  let anagram a b =
+    Set.equal (string_to_set a) (string_to_set b) in
+  match passphrase with
+  | [] -> false
+  | h::t ->
+     match List.find t ~f:(anagram h) with
+     | Some x -> true
+     | None -> has_anagram t
+
+let () =
+  let pairs = List.zip_exn (passphrase_set_lengths passphrases) (passphrase_lengths passphrases) in
+  let valid_count = List.fold ~f:(fun acc (x, y) -> if x = y then acc+1 else acc) ~init:0 pairs in
+  Printf.printf "%d\n" valid_count;
+
+  let anagram_count = List.fold ~f:(fun acc x -> if has_anagram x then acc else acc + 1) ~init:0 passphrases in
+  Printf.printf "%d\n" anagram_count