aboutsummaryrefslogtreecommitdiff
path: root/aoc-2022-dotnet/Day10/Program.fs
blob: 9a2f002818e40898bec64de2e847f2cac74fac9b (plain)
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
module Day10

open System.IO
open FParsec
open Common

let initialCpuState = Map.empty |> Map.add 1 1
let screenWidth = 40
let screenHeight = 6

let testScreen =
    "██░░██░░██░░██░░██░░██░░██░░██░░██░░██░░\n\
     ███░░░███░░░███░░░███░░░███░░░███░░░███░\n\
     ████░░░░████░░░░████░░░░████░░░░████░░░░\n\
     █████░░░░░█████░░░░░█████░░░░░█████░░░░░\n\
     ██████░░░░░░██████░░░░░░██████░░░░░░████\n\
     ███████░░░░░░░███████░░░░░░░███████░░░░░"

type Instr =
    | NOOP
    | ADDX of int

    static member parse =
        let pnoop = pstring "noop" >>% NOOP
        let paddx = pstring "addx " >>. pint32 |>> ADDX
        let pinstr = pnoop <|> paddx
        Util.parse pinstr

let solution actOnCpuStates =
    Seq.map Instr.parse
    >> Seq.fold
        (fun states instr ->
            let (cycle, X) = Map.maxKeyValue states

            states
            |> Map.add (cycle + 1) X
            |> match instr with
               | NOOP -> id
               | ADDX v -> Map.add (cycle + 2) (X + v))
        initialCpuState
    >> actOnCpuStates

let signalStrengthSum =
    Map.filter (fun cycle _ -> cycle % 40 = 20)
    >> Seq.sumBy (fun kv -> kv.Key * kv.Value)

let drawScreen =
    Map.map (fun cycle X ->
        match abs ((cycle - 1) % 40 - X) <= 1 with
        | true -> '█'
        | false -> '░')
    >> Map.values
    >> Seq.truncate (screenWidth * screenHeight)
    >> Seq.chunkBySize screenWidth
    >> Util.matrixToString

let test = File.ReadLines("test.txt")
assert (solution signalStrengthSum test = 13140)
assert (solution drawScreen test = testScreen)

let input = File.ReadLines("input.txt")
printfn "%d" <| solution signalStrengthSum input
printfn "%s" <| solution drawScreen input