-
Notifications
You must be signed in to change notification settings - Fork 0
/
Program.fs
74 lines (62 loc) · 2.39 KB
/
Program.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
module Day07
open System.IO
open System.Text.RegularExpressions
type Identifier = string
type Gate =
| Signal of Identifier
| SignalValue of int16
| And of Identifier * Identifier
| AndValue of Identifier * int16
| Or of Identifier * Identifier
| LeftShift of Identifier * int
| RightShift of Identifier * int
| Not of Identifier
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 parse (line: string) =
let parseGate gate =
match gate with
| Regex @"^([a-z]+)$" [a] -> Signal a
| Regex @"^(\d+)$" [a] -> SignalValue (int16 a)
| Regex @"^([a-z]+) OR ([a-z]+)$" [a; b] -> Or (a, b)
| Regex @"^([a-z]+) AND ([a-z]+)$" [a; b] -> And (a, b)
| Regex @"^1 AND ([a-z]+)$" [a] -> AndValue (a, 1s)
| Regex @"^([a-z]+) LSHIFT (\d+)$" [a; b] -> LeftShift (a, int b)
| Regex @"^([a-z]+) RSHIFT (\d+)$" [a; b] -> RightShift (a, int b)
| Regex @"^NOT ([a-z]+)$" [a] -> Not a
let gateAndId = line.Split(" -> ")
(gateAndId.[1], parseGate gateAndId.[0])
let rec resolve identifier gates (cache: byref<Map<string, int16>>) =
if cache.ContainsKey(identifier) then
cache.[identifier]
else
let (_, gate) = List.find (fun (x, _) -> x = identifier) gates
let value =
match gate with
| SignalValue value -> value
| Signal a -> resolve a gates &cache
| Or (a, b) -> (resolve a gates &cache) ||| (resolve b gates &cache)
| And (a, b) -> (resolve a gates &cache) &&& (resolve b gates &cache)
| AndValue (a, b) -> (resolve a gates &cache) &&& b
| LeftShift (a, shift) -> (resolve a gates &cache) <<< shift
| RightShift (a, shift) -> (resolve a gates &cache) >>> shift
| Not a -> ~~~ (resolve a gates &cache)
cache <- cache.Add(identifier, value)
value
let solve input =
let mutable cache = Map.empty
resolve "a" input &cache
[<EntryPoint>]
let main argv =
let input =
File.ReadLines("Input.txt")
|> Seq.map parse
|> Seq.toList
let signalA = solve input
signalA |> printfn "Part one: %d"
let newInput = ("b", SignalValue signalA) :: List.filter (fun (x, _) -> x <> "b") input
solve newInput |> printfn "Part two: %d"
0