From c5b360acfa297c1618cdd9624748f0ee1a1cc36b Mon Sep 17 00:00:00 2001 From: Patrick Stevens Date: Sat, 10 Dec 2022 09:07:52 +0000 Subject: [PATCH] Day 10 (#13) --- .../AdventOfCode2022.App.fsproj | 1 + AdventOfCode2022.App/Program.fs | 8 +- .../AdventOfCode2022.Test.fsproj | 2 + AdventOfCode2022.Test/Day10.fs | 203 ++++++++++++++++++ AdventOfCode2022.Test/Inputs/Day10.txt | 137 ++++++++++++ AdventOfCode2022/AdventOfCode2022.fsproj | 1 + AdventOfCode2022/Day10.fs | 90 ++++++++ 7 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 AdventOfCode2022.Test/Day10.fs create mode 100644 AdventOfCode2022.Test/Inputs/Day10.txt create mode 100644 AdventOfCode2022/Day10.fs diff --git a/AdventOfCode2022.App/AdventOfCode2022.App.fsproj b/AdventOfCode2022.App/AdventOfCode2022.App.fsproj index f48094e..d528b33 100644 --- a/AdventOfCode2022.App/AdventOfCode2022.App.fsproj +++ b/AdventOfCode2022.App/AdventOfCode2022.App.fsproj @@ -16,6 +16,7 @@ + diff --git a/AdventOfCode2022.App/Program.fs b/AdventOfCode2022.App/Program.fs index f0bf87b..eb41f1a 100644 --- a/AdventOfCode2022.App/Program.fs +++ b/AdventOfCode2022.App/Program.fs @@ -20,7 +20,7 @@ module Program = [] let main _ = - let days = Array.init 9 (fun day -> readResource $"Day%i{day + 1}.txt") + let days = Array.init 10 (fun day -> readResource $"Day%i{day + 1}.txt") let inline day (i : int) = days.[i - 1] @@ -73,6 +73,12 @@ module Program = printfn "%i" (Day9.part1 day9) printfn "%i" (Day9.part2 day9) + + do + let day10 = StringSplitEnumerator.make '\n' (day 10) + printfn "%i" (Day10.part1 day10) + Day10.render (printfn "%s") (Day10.part2 day10) + time.Stop () printfn $"Took %i{time.ElapsedMilliseconds}ms" 0 diff --git a/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj b/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj index 17981d6..0adbe1f 100644 --- a/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj +++ b/AdventOfCode2022.Test/AdventOfCode2022.Test.fsproj @@ -17,6 +17,7 @@ + @@ -26,6 +27,7 @@ + diff --git a/AdventOfCode2022.Test/Day10.fs b/AdventOfCode2022.Test/Day10.fs new file mode 100644 index 0000000..3788470 --- /dev/null +++ b/AdventOfCode2022.Test/Day10.fs @@ -0,0 +1,203 @@ +namespace AdventOfCode2022.Test + +open System +open NUnit.Framework +open FsUnitTyped +open AdventOfCode2022 + +[] +module TestDay10 = + + let input = + """addx 15 +addx -11 +addx 6 +addx -3 +addx 5 +addx -1 +addx -8 +addx 13 +addx 4 +noop +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx -35 +addx 1 +addx 24 +addx -19 +addx 1 +addx 16 +addx -11 +noop +noop +addx 21 +addx -15 +noop +noop +addx -3 +addx 9 +addx 1 +addx -3 +addx 8 +addx 1 +addx 5 +noop +noop +noop +noop +noop +addx -36 +noop +addx 1 +addx 7 +noop +noop +noop +addx 2 +addx 6 +noop +noop +noop +noop +noop +addx 1 +noop +noop +addx 7 +addx 1 +noop +addx -13 +addx 13 +addx 7 +noop +addx 1 +addx -33 +noop +noop +noop +addx 2 +noop +noop +noop +addx 8 +noop +addx -1 +addx 2 +addx 1 +noop +addx 17 +addx -9 +addx 1 +addx 1 +addx -3 +addx 11 +noop +noop +addx 1 +noop +addx 1 +noop +noop +addx -13 +addx -19 +addx 1 +addx 3 +addx 26 +addx -30 +addx 12 +addx -1 +addx 3 +addx 1 +noop +noop +noop +addx -9 +addx 18 +addx 1 +addx 2 +noop +noop +addx 9 +noop +noop +noop +addx -1 +addx 2 +addx -37 +addx 1 +addx 3 +noop +addx 15 +addx -21 +addx 22 +addx -6 +addx 1 +noop +addx 2 +addx 1 +noop +addx -10 +noop +noop +addx 20 +addx 1 +addx 2 +addx 2 +addx -6 +addx -11 +noop +noop +noop +""" + + [] + let ``Part 1, given`` () = + Day10.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 13140 + + [] + let ``Part 1`` () = + let input = Assembly.readResource "Day10.txt" + + Day10.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 15140 + + [] + let ``Part 2, given`` () = + let output = ResizeArray () + Day10.part2 (StringSplitEnumerator.make '\n' input) |> Day10.render output.Add + + output + |> List.ofSeq + |> shouldEqual + [ + "##..##..##..##..##..##..##..##..##..##.." + "###...###...###...###...###...###...###." + "####....####....####....####....####...." + "#####.....#####.....#####.....#####....." + "######......######......######......####" + "#######.......#######.......#######....." + ] + + [] + let ``Part 2`` () = + let input = Assembly.readResource "Day10.txt" + let output = ResizeArray () + Day10.part2 (StringSplitEnumerator.make '\n' input) |> Day10.render output.Add + + output + |> List.ofSeq + |> shouldEqual + [ + "###..###....##..##..####..##...##..###.." + "#..#.#..#....#.#..#....#.#..#.#..#.#..#." + "###..#..#....#.#..#...#..#....#..#.#..#." + "#..#.###.....#.####..#...#.##.####.###.." + "#..#.#....#..#.#..#.#....#..#.#..#.#...." + "###..#.....##..#..#.####..###.#..#.#...." + ] diff --git a/AdventOfCode2022.Test/Inputs/Day10.txt b/AdventOfCode2022.Test/Inputs/Day10.txt new file mode 100644 index 0000000..06ecccf --- /dev/null +++ b/AdventOfCode2022.Test/Inputs/Day10.txt @@ -0,0 +1,137 @@ +noop +noop +addx 5 +addx 1 +addx 10 +addx -4 +noop +addx -1 +noop +addx 5 +addx -5 +addx 9 +addx 2 +addx -15 +addx 18 +addx 8 +addx -2 +noop +addx -18 +addx 21 +addx 1 +addx -37 +addx 27 +addx -24 +addx 2 +addx 5 +addx -7 +addx 26 +addx -16 +addx 2 +addx 5 +addx -15 +noop +addx 20 +addx 2 +addx 4 +addx -3 +addx 2 +noop +addx 3 +addx 2 +addx 5 +addx -40 +addx 2 +addx 33 +addx -30 +addx 5 +addx 5 +addx 17 +addx -19 +addx 2 +addx 5 +addx 20 +addx -16 +addx 3 +addx -2 +addx 7 +noop +addx -2 +addx 5 +addx 2 +addx 3 +addx -2 +addx -38 +addx 5 +addx 2 +addx 1 +addx 15 +addx -8 +noop +addx -2 +addx 4 +addx 2 +addx 4 +addx -2 +noop +addx 6 +addx 2 +addx -1 +addx 4 +noop +addx 1 +addx 4 +noop +noop +noop +addx -37 +addx 5 +addx 2 +addx 22 +addx -17 +addx -2 +noop +addx 3 +addx 2 +noop +addx 3 +addx 2 +noop +noop +noop +addx 5 +addx 5 +addx 2 +addx 3 +noop +addx 2 +addx -23 +addx 2 +addx -14 +noop +addx 29 +addx -26 +noop +addx 8 +noop +noop +noop +addx -9 +addx 11 +addx 5 +addx 2 +noop +addx 1 +noop +noop +addx 5 +noop +noop +addx 2 +noop +addx 3 +addx 2 +addx -2 +noop +noop +noop diff --git a/AdventOfCode2022/AdventOfCode2022.fsproj b/AdventOfCode2022/AdventOfCode2022.fsproj index 0bfe6d5..d2f5ced 100644 --- a/AdventOfCode2022/AdventOfCode2022.fsproj +++ b/AdventOfCode2022/AdventOfCode2022.fsproj @@ -18,6 +18,7 @@ + diff --git a/AdventOfCode2022/Day10.fs b/AdventOfCode2022/Day10.fs new file mode 100644 index 0000000..f65c955 --- /dev/null +++ b/AdventOfCode2022/Day10.fs @@ -0,0 +1,90 @@ +namespace AdventOfCode2022 + +open System.Collections.Generic +open System + +type Day10Instruction = + | Noop + | Addx of int + +[] +module Day10 = + + let parse (lines : StringSplitEnumerator) : Day10Instruction IReadOnlyList = + use mutable enum = lines + let output = ResizeArray () + + for line in enum do + let line = line.TrimEnd () + + if not (line.IsWhiteSpace ()) then + let toAdd = + if EfficientString.equals "noop" line then + Day10Instruction.Noop + else + let mutable split = StringSplitEnumerator.make' ' ' line + StringSplitEnumerator.chomp "addx" &split + let value = StringSplitEnumerator.consumeInt &split + + if split.MoveNext () then + failwith "line had too many spaces" + + Day10Instruction.Addx value + + output.Add toAdd + + output :> _ + + let perform (startState : 'a) (onCycle : 'a -> int -> int -> 'a) (instructions : Day10Instruction IReadOnlyList) = + let mutable cycle = 0 + let mutable state = startState + let mutable spritePos = 1 + + let inline incrCycle () = + state <- onCycle state cycle spritePos + cycle <- cycle + 1 + + for instruction in instructions do + incrCycle () + + match instruction with + | Day10Instruction.Noop -> () + | Day10Instruction.Addx newX -> + incrCycle () + spritePos <- spritePos + newX + + state + + let part1 (lines : StringSplitEnumerator) : int = + let instructions = parse lines + + let updateState cost cycle spritePos = + if cycle % 40 = 19 then + cost + ((cycle + 1) * spritePos) + else + cost + + perform 0 updateState instructions + + let part2 (lines : StringSplitEnumerator) : char[] = + let instructions = parse lines + let arr = Array.create 240 '.' + + let updateState (arr : char[]) cycle spritePos = + if spritePos - 1 = cycle % 40 && spritePos % 40 <> 0 then + arr.[cycle] <- '#' + elif spritePos + 1 = cycle % 40 && spritePos % 40 <> 39 then + arr.[cycle] <- '#' + elif spritePos = cycle % 40 then + arr.[cycle] <- '#' + + arr + + perform arr updateState instructions + + let inline render ([] print : string -> unit) (arr : char[]) : unit = + let arr = arr.AsSpan () + + for i in 0..5 do + let toPrint = arr.Slice (i * 40, 40) + print (toPrint.ToString ())