From 77413a29df238ab77450e45bd3dd1e22a9ed61a3 Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Mon, 25 Dec 2017 13:32:37 +0100 Subject: [PATCH] Day 25 --- AdventOfCode2017/AdventOfCode2017.fsproj | 8 +++-- AdventOfCode2017/Day25.fs | 38 +++++++++++++++++++++ AdventOfCode2017/Program.fs | 5 +++ Tests/Day25 tests.fs | 43 ++++++++++++++++++++++++ Tests/Tests.fsproj | 1 + 5 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 AdventOfCode2017/Day25.fs create mode 100644 Tests/Day25 tests.fs diff --git a/AdventOfCode2017/AdventOfCode2017.fsproj b/AdventOfCode2017/AdventOfCode2017.fsproj index e568040..852dc74 100644 --- a/AdventOfCode2017/AdventOfCode2017.fsproj +++ b/AdventOfCode2017/AdventOfCode2017.fsproj @@ -25,7 +25,7 @@ AnyCPU bin\$(Configuration)\$(AssemblyName).XML true - 24 + 25 pdbonly @@ -37,7 +37,7 @@ AnyCPU bin\$(Configuration)\$(AssemblyName).XML true - 24 + 25 11 @@ -83,6 +83,7 @@ + @@ -157,6 +158,9 @@ PreserveNewest + + PreserveNewest + diff --git a/AdventOfCode2017/Day25.fs b/AdventOfCode2017/Day25.fs new file mode 100644 index 0000000..373265c --- /dev/null +++ b/AdventOfCode2017/Day25.fs @@ -0,0 +1,38 @@ +module AdventOfCode2017.Day25 + +let readMove (str : string) = if str = "right" then 1 else -1 + +type State = + { + Values : int[] + Moves : int[] // -1: left, +1: right. + NextState : char[] + } + +let split (str : string) (chars : char[]) = str.Split (chars, System.StringSplitOptions.RemoveEmptyEntries) + +let parseInput (lines : string[]) : Map * char * int = + let firstState = (split lines.[0] [| ' '; '.' |]).[3] |> char + let nbSteps = lines.[1].Split(' ').[5] |> int + + [ + for i = 0 to (lines.Length - 2) / 9 - 1 do + let lineNum = i * 10 + 3 + let name = (split lines.[lineNum] [| ' '; ':' |]).[2] |> char + let state = + { + Values = [| (split lines.[lineNum + 2] [| ' '; '.' |]).[4] |> int; (split lines.[lineNum + 6] [| ' '; '.' |]).[4] |> int |] + Moves = [| (split lines.[lineNum + 3] [| ' '; '.' |]).[6] |> readMove; (split lines.[lineNum + 7] [| ' '; '.' |]).[6] |> readMove |] + NextState = [| (split lines.[lineNum + 4] [| ' '; '.' |]).[4] |> char; (split lines.[lineNum + 8] [| ' '; '.' |]).[4] |> char |] + } + yield name, state + ] |> Map.ofList, firstState, nbSteps + +let checksum (states : Map, firstState : char, nbSteps : int) : int = + let next (tape : Set) (cursor : int) (stateName : char) : Set * int * char = + let state = states |> Map.find stateName + let v = if tape |> Set.contains cursor then 1 else 0 + (tape |> if state.Values.[v] = 1 then Set.add cursor else Set.remove cursor), cursor + state.Moves.[v], state.NextState.[v] + + let tape, _, _ = [ 1 .. nbSteps ] |> List.fold (fun (tape, cursor, state) _ -> next tape cursor state) (Set.empty, 0, firstState) + tape |> Set.count \ No newline at end of file diff --git a/AdventOfCode2017/Program.fs b/AdventOfCode2017/Program.fs index 65f1fbf..f5c32c3 100644 --- a/AdventOfCode2017/Program.fs +++ b/AdventOfCode2017/Program.fs @@ -109,6 +109,10 @@ let day24 () = let bridges = Day24.bridges input sprintf "part1 = %A, part2 = %A" (Day24.maxBridge bridges) (Day24.longestBridge bridges) +let day25 () = + let input = File.ReadAllLines "Data/day25.input" |> Day25.parseInput + sprintf "part1 = %A, part2 = %A" (Day25.checksum input) () + let doDay (n : int) = let sw = Diagnostics.Stopwatch () sw.Start () @@ -138,6 +142,7 @@ let doDay (n : int) = | 22 -> day22 () | 23 -> day23 () | 24 -> day24 () + | 25 -> day25 () | _ -> raise <| NotImplementedException () printfn "Result of day %i: %s (time : %i ms)" n result sw.ElapsedMilliseconds diff --git a/Tests/Day25 tests.fs b/Tests/Day25 tests.fs new file mode 100644 index 0000000..2cca89a --- /dev/null +++ b/Tests/Day25 tests.fs @@ -0,0 +1,43 @@ +namespace AdventOfCode2017.Tests + +open System +open Xunit +open Xunit.Abstractions +open Swensen.Unquote + +open AdventOfCode2017 + +type ``Day25 tests`` (output : ITestOutputHelper) = + + [] + let ``(Part1) From web page`` () = + let input = + [| + "Begin in state A." + "Perform a diagnostic checksum after 6 steps." + "" + "In state A:" + " If the current value is 0:" + " - Write the value 1." + " - Move one slot to the right." + " - Continue with state B." + " If the current value is 1:" + " - Write the value 0." + " - Move one slot to the left." + " - Continue with state B." + "" + "In state B:" + " If the current value is 0:" + " - Write the value 1." + " - Move one slot to the left." + " - Continue with state A." + " If the current value is 1:" + " - Write the value 1." + " - Move one slot to the right." + " - Continue with state A." + |] |> Day25.parseInput + Day25.checksum input =! 3 + + [] + let ``(Part2) From web page`` () = + () \ No newline at end of file diff --git a/Tests/Tests.fsproj b/Tests/Tests.fsproj index 31314ef..16f4250 100644 --- a/Tests/Tests.fsproj +++ b/Tests/Tests.fsproj @@ -78,6 +78,7 @@ + -- 2.45.2