summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBrian Chu <brianmchu42@gmail.com>2022-01-05 19:13:22 -0800
committerBrian Chu <brianmchu42@gmail.com>2022-01-05 19:13:22 -0800
commit3d999d711642cfeabb8f53a80bb962c60a44a802 (patch)
treeac2b2bbc63fb05f1068cac2014cb7daaeaf8dc06
parentc377501ad97ce336c52a04ae9bf85ca335b814ba (diff)
downloadAdventOfCode2016-3d999d711642cfeabb8f53a80bb962c60a44a802.tar.gz
solution for day 10
-rw-r--r--day10.fsx95
1 files changed, 95 insertions, 0 deletions
diff --git a/day10.fsx b/day10.fsx
new file mode 100644
index 0000000..0ccb8a6
--- /dev/null
+++ b/day10.fsx
@@ -0,0 +1,95 @@
+open System
+open System.Collections.Generic
+open System.IO
+open System.Text.RegularExpressions
+
+let input = File.ReadAllLines "day10.txt"
+
+type Target =
+  | Bot     of int
+  | Output  of int
+
+let (|Regex|_|) pattern input =
+  let m = Regex.Match(input, pattern)
+  if m.Success then Some(List.tail [ for g in m.Groups -> g.Value ])
+  else None
+
+let (|Int|) x  = Int32.Parse x
+let (|Target|) = function | "bot" -> Bot | _ -> Output
+
+type Bot = 
+  {
+    Number     : int
+    Microchips : int list
+    LowTarget  : Target
+    HiTarget   : Target
+  }
+  
+let events =
+  let bots = new Dictionary<int, Bot>()
+
+  input
+  |> Array.sort
+  |> Array.iter (fun line ->
+    match line with
+    | Regex "bot (\d*) gives low to (bot|output) (\d*) and high to (bot|output) (\d*)" 
+            [ Int botN; Target lowT; Int lowN; Target hiT; Int hiN ] ->
+      let bot = 
+        { 
+          Number     = botN
+          Microchips = []
+          LowTarget  = lowT lowN
+          HiTarget   = hiT hiN 
+        }
+      bots.Add(botN, bot)
+
+    | Regex "value (\d*) goes to bot (\d*)" [ Int value; Int botN ] ->
+      let bot = bots.[botN]
+      bots.[botN] <- { bot with Microchips = value::bot.Microchips }
+    | _ -> ())
+
+  let give value = function
+    | Bot botN -> 
+      let bot = bots.[botN] 
+      bots.[botN] <- { bot with Microchips = value::bot.Microchips }
+    | _ -> ()
+
+  let botsWithTwo = 
+    bots 
+    |> Seq.map (fun kvp -> kvp.Value)
+    |> Seq.filter (fun bot -> bot.Microchips.Length = 2)
+
+  seq {
+    while Seq.length botsWithTwo > 0 do
+      for bot in (Array.ofSeq botsWithTwo) do
+        let vals = bot.Microchips |> List.sort
+        let lowVal, hiVal = vals[0], vals[1]
+        bots.[bot.Number] <- { bot with Microchips = [] }
+        
+        give lowVal bot.LowTarget
+        give hiVal bot.HiTarget
+
+        yield bot.Number, (bot.LowTarget, lowVal), (bot.HiTarget, hiVal)
+  }
+  
+let part1 = 
+  events 
+  |> Seq.pick (fun (botN, (_, lowVal), (_, hiVal)) ->
+    if lowVal = 17 && hiVal = 61 then Some botN else None)
+
+let part2 =
+  let isOutput0To2 = function
+    | Output 0 | Output 1 | Output 2 -> true
+    | _ -> false  
+
+  events
+  |> Seq.collect (fun (botN, (lowTarget, lowVal), (hiTarget, hiVal)) ->
+     seq {
+       if isOutput0To2 lowTarget then yield lowVal
+       if isOutput0To2 hiTarget then yield hiVal
+     })
+  |> Seq.take 3
+  |> Seq.reduce (*)
+
+part1 |> printfn "%A"
+part2 |> printfn "%A"
\ No newline at end of file