GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
++ GlobalSection(Performance) = preSolution
++ HasPerformanceSessions = true
++ EndGlobalSection
EndGlobal
<Compile Include="Day18Part2.fs" />
<Compile Include="Day19.fs" />
<Compile Include="Day20.fs" />
+ <Compile Include="Day21.fs" />
+ <Compile Include="Day22.fs" />
<Compile Include="Program.fs" />
<None Include="App.config" />
<Content Include="Data\day01.input">
<Content Include="Data\day20.input">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <None Include="Data\day21.input" />
- <None Include="Data\day22.input" />
++ <Content Include="Data\day21.input">
++ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
++ </Content>
++ <Content Include="Data\day22.input">
++ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
++ </Content>
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
--- /dev/null
- open System
-
+module AdventOfCode2017.Day21
+
- let parseInput (lines : string[]) : (M * M) list =
+type M = bool[,]
+
- (*
-
- let l = str.Length
- let m = Array2D.zeroCreate l l : M
- let rows = str.Split '/'
- for i = 0 to l - 1 do
- for j = 0 to l - 1 do
- m.[i, j] <- rows.[i].[j] = '#'
- m*)
-
-
++/// We use a Map which is slower than a Dictionary<T,U>.
++/// To use a Dictionary<T,U> a new type must be created instead of bool[,] because Array2D do not properly support the 'GetHashCode' methode.
++/// To get a correct hash code of a Array2D the function 'hash' must be used.
++let parseInput (lines : string[]) : Map<M, M> =
+ let readMat (str : string) =
+ str.Split '/' |> Array.map (Array.ofSeq >> Array.map ((=) '#')) |> array2D
+
- |> List.ofArray
- |> List.map (
+ lines
- let matPair = line.Split ([| "=>" |], StringSplitOptions.RemoveEmptyEntries)
++ |> Array.map (
+ fun line ->
- let fractalArt (patterns : (M * M) list) : int =
++ let matPair = line.Split ([| " => " |], System.StringSplitOptions.RemoveEmptyEntries)
+ readMat matPair.[0], readMat matPair.[1]
+ )
++ |> Map.ofArray
+
- let l = Array2D.length1 m
- let m' = Array2D.zeroCreate l l
++let fractalArt (patterns : Map<M, M>) (nbIterations : int) : int =
+ let turn (m : M) =
- let l = Array2D.length1 m
- let m' = Array2D.zeroCreate l l
++ let m' = m.[*, *]
+ if Array2D.length1 m = 2 then
+ m'.[0,0] <- m.[1,0]
+ m'.[0,1] <- m.[0,0]
+ m'.[1,1] <- m.[0,1]
+ m'.[1,0] <- m.[1,1]
+ else
+ m'.[0,0] <- m.[2,0]
+ m'.[0,1] <- m.[1,0]
+ m'.[0,2] <- m.[0,0]
+ m'.[1,2] <- m.[0,1]
+ m'.[2,2] <- m.[0,2]
+ m'.[2,1] <- m.[1,2]
+ m'.[2,0] <- m.[2,2]
+ m'.[1,0] <- m.[2,1]
+ m'
+
+ let flip (m : M) =
- let next (m : M) : M =
- let l = Array2D.length1 m
- if l % 2 = 0 then
- let l' = l + l / 2
++ let m' = m.[*, *]
+ if Array2D.length1 m = 2 then
+ m'.[0,0] <- m.[0,1]
+ m'.[0,1] <- m.[0,0]
+ m'.[1,1] <- m.[1,0]
+ m'.[1,0] <- m.[1,1]
+ else
+ m'.[0,0] <- m.[0,2]
+ m'.[1,0] <- m.[1,2]
+ m'.[2,0] <- m.[2,2]
+ m'.[0,2] <- m.[0,0]
+ m'.[1,2] <- m.[1,0]
+ m'.[2,2] <- m.[2,0]
+ m'
+
+ let variants (m : M) : M list =
+ let l = List.unfold (fun (i, m) -> if i < 4 then Some (m, (i + 1, turn m)) else None) (0, m)
+ if Array2D.length1 m > 2 then l @ (l |> List.map flip) else l
+
- next (array2 [ [ false; true; false ]; [ false; false; true ]; [ true; true; true] ]) |> Array2D.iter (fun e -> if e then n <- n + 1)
++ let findPattern (p : M) : M =
++ variants p |> List.pick (fun v -> patterns |> Map.tryFind v)
++
++ let rec next (m : M) (n : int) : M =
++ if n = 0 then
++ m
+ else
++ let l = Array2D.length1 m
++ let s = if l % 2 = 0 then 2 else 3
++ let l' = l + l / s
++ let m' = Array2D.zeroCreate l' l'
++ for i = 0 to l / s - 1 do
++ for j = 0 to l / s - 1 do
++ let pattern = findPattern m.[i * s .. i * s + s - 1, j * s .. j * s + s - 1]
++ Array2D.blit pattern 0 0 m' (i * (s + 1)) (j * (s + 1)) (s + 1) (s + 1)
++ next m' (n - 1)
+
+ let mutable n = 0
++ next (array2D [ [ false; true; false ]; [ false; false; true ]; [ true; true; true] ]) nbIterations |> Array2D.iter (fun e -> if e then n <- n + 1)
+ n
--- /dev/null
- for i = 0 to lines.Length do
- for
+ module AdventOfCode2017.Day22
+
+ type M = Set<int * int>
+
+ let parseInput (lines : string[]) : M =
++ (*for i = 0 to lines.Length do
++ for*)
++ Set.empty
+
+
+ let infection (m : M) : int =
+
+ let rec burst (i, j) (di, dj) n m =
+ if n = 0 then
+ ()
+ else
+ burst (i, j) (di, dj) (n - 1) m
+
+ 23
+
let input = File.ReadAllLines "Data/day20.input" |> Day20.parseInput
sprintf "part1 = %A, part2 = %A" (Day20.nearestZero input) (Day20.nbAlive input)
++let day21 () =
++ let input = File.ReadAllLines "Data/day21.input" |> Day21.parseInput
++ sprintf "part1 = %A, part2 = %A" (Day21.fractalArt input 5) (Day21.fractalArt input 18)
++
++let day22 () =
++ //let input = File.ReadAllLines "Data/day21.input" |> Day21.parseInput
++ sprintf "part1 = %A, part2 = %A" () ()
++
let doDay (n : int) =
let sw = Diagnostics.Stopwatch ()
sw.Start ()
| 18 -> day18 ()
| 19 -> day19 ()
| 20 -> day20 ()
++ | 21 -> day21 ()
++ | 22 -> day22 ()
| _ -> raise <| NotImplementedException ()
printfn "Result of day %i: %s (time : %i ms)" n result sw.ElapsedMilliseconds
--- /dev/null
- let ``(Part1) From web page`` () =
- ()
-
- [<Fact>]
- let ``(Part2) From web page`` () =
- ()
+namespace AdventOfCode2017.Tests
+
+open System
+open Xunit
+open Xunit.Abstractions
+open Swensen.Unquote
+
+open AdventOfCode2017
+
+type ``Day21 tests`` (output : ITestOutputHelper) =
+
+ [<Fact>]
++ let ``From web page`` () =
++ let input =
++ [|
++ "../.# => ##./#../..."
++ ".#./..#/### => #..#/..../..../#..#"
++ |] |> Day21.parseInput
++ Day21.fractalArt input 2 =! 12
--- /dev/null
-type ``Day20 tests`` (output : ITestOutputHelper) =
+ namespace AdventOfCode2017.Tests
+
+ open System
+ open Xunit
+ open Xunit.Abstractions
+ open Swensen.Unquote
+
+ open AdventOfCode2017
+
- let input =
- [|
- "p=< 3,0,0>, v=< 2,0,0>, a=<-1,0,0>"
- "p=< 4,0,0>, v=< 0,0,0>, a=<-2,0,0>"
- |] |> Day20.parseInput
-
- Day20.nearestZero input =! 0
++type ``Day22 tests`` (output : ITestOutputHelper) =
+
+ [<Fact>]
+ let ``(Part1) From web page`` () =
- let input =
- [|
- "p=<-6,0,0>, v=< 3,0,0>, a=< 0,0,0>"
- "p=<-4,0,0>, v=< 2,0,0>, a=< 0,0,0>"
- "p=<-2,0,0>, v=< 1,0,0>, a=< 0,0,0>"
- "p=< 3,0,0>, v=<-1,0,0>, a=< 0,0,0>"
- |] |> Day20.parseInput
-
- Day20.nbAlive input =! 1
++ ()
+
+ [<Fact>]
+ let ``(Part2) From web page`` () =
++ ()
<Compile Include="Day18 tests.fs" />
<Compile Include="Day19 tests.fs" />
<Compile Include="Day20 tests.fs" />
+ <Compile Include="Day21 tests.fs" />
+ <Compile Include="Day22 tests.fs" />
<Content Include="App.config" />
<Content Include="packages.config" />
</ItemGroup>