Merge branch 'master' of github.com:Ummon/AdventOfCode2017
authorGreg Burri <greg.burri@gmail.com>
Fri, 22 Dec 2017 22:04:02 +0000 (23:04 +0100)
committerGreg Burri <greg.burri@gmail.com>
Fri, 22 Dec 2017 22:04:02 +0000 (23:04 +0100)
# Conflicts:
# AdventOfCode2017/AdventOfCode2017.fsproj
# Tests/Tests.fsproj

Plus Day 21

1  2 
AdventOfCode2017.sln
AdventOfCode2017/AdventOfCode2017.fsproj
AdventOfCode2017/Day21.fs
AdventOfCode2017/Day22.fs
AdventOfCode2017/Program.fs
Tests/Day21 tests.fs
Tests/Day22 tests.fs
Tests/Tests.fsproj

@@@ -43,4 -43,4 +43,7 @@@ Globa
        GlobalSection(Performance) = preSolution
                HasPerformanceSessions = true
        EndGlobalSection
++      GlobalSection(Performance) = preSolution
++              HasPerformanceSessions = true
++      EndGlobalSection
  EndGlobal
@@@ -79,7 -79,7 +79,8 @@@
      <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>
index ff0da05,0000000..f724b4b
mode 100644,000000..100644
--- /dev/null
@@@ -1,79 -1,0 +1,78 @@@
- 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
index 0000000,a651517..21ddf63
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,19 +1,20 @@@
 -    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
@@@ -92,6 -92,6 +92,14 @@@ let day20 () 
      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
  
index c5677c5,0000000..b611497
mode 100644,000000..100644
--- /dev/null
@@@ -1,18 -1,0 +1,19 @@@
-     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
index 0000000,27cc33f..ce41f5f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,32 +1,18 @@@
 -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`` () =
++        ()
@@@ -75,7 -75,7 +75,8 @@@
      <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>