mirror of
https://github.com/Smaug123/AdventOfCode2022
synced 2025-10-05 17:48:40 +00:00
Day 22 and speedups (#34)
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day19.txt" />
|
||||
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day20.txt" />
|
||||
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day21.txt" />
|
||||
<EmbeddedResource Include="..\AdventOfCode2022.Test\Inputs\Day22.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -2,5 +2,5 @@ namespace AdventOfCode2022.App
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Inputs =
|
||||
let days = Array.init 21 (fun day -> Assembly.readResource $"Day%i{day + 1}.txt")
|
||||
let days = Array.init 22 (fun day -> Assembly.readResource $"Day%i{day + 1}.txt")
|
||||
let inline day (i : int) = days.[i - 1]
|
||||
|
@@ -79,7 +79,7 @@ type Benchmark21To25 () =
|
||||
[<GlobalSetup>]
|
||||
member _.Setup () = Run.shouldWrite <- false
|
||||
|
||||
[<Params(21)>]
|
||||
[<Params(21, 22)>]
|
||||
member val Day = 0 with get, set
|
||||
|
||||
[<Params(false, true)>]
|
||||
|
@@ -303,6 +303,20 @@ module Run =
|
||||
if shouldWrite then
|
||||
printfn "%i" output
|
||||
|
||||
let day22 (partTwo : bool) (input : string) =
|
||||
let day22 = StringSplitEnumerator.make '\n' input
|
||||
|
||||
if not partTwo then
|
||||
let output = Day22.part1 day22
|
||||
|
||||
if shouldWrite then
|
||||
printfn "%i" output
|
||||
else
|
||||
let output = Day22.part2 day22
|
||||
|
||||
if shouldWrite then
|
||||
printfn "%i" output
|
||||
|
||||
let allRuns =
|
||||
[|
|
||||
day1
|
||||
@@ -326,4 +340,5 @@ module Run =
|
||||
day19
|
||||
day20
|
||||
day21
|
||||
day22
|
||||
|]
|
||||
|
@@ -29,6 +29,7 @@
|
||||
<Compile Include="Day19.fs" />
|
||||
<Compile Include="Day20.fs" />
|
||||
<Compile Include="Day21.fs" />
|
||||
<Compile Include="Day22.fs" />
|
||||
<EmbeddedResource Include="Inputs\Day1.txt" />
|
||||
<EmbeddedResource Include="Inputs\Day2.txt" />
|
||||
<EmbeddedResource Include="Inputs\Day3.txt" />
|
||||
@@ -50,6 +51,7 @@
|
||||
<EmbeddedResource Include="Inputs\Day19.txt" />
|
||||
<EmbeddedResource Include="Inputs\Day20.txt" />
|
||||
<EmbeddedResource Include="Inputs\Day21.txt" />
|
||||
<EmbeddedResource Include="Inputs\Day22.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
46
AdventOfCode2022.Test/Day22.fs
Normal file
46
AdventOfCode2022.Test/Day22.fs
Normal file
@@ -0,0 +1,46 @@
|
||||
namespace AdventOfCode2022.Test
|
||||
|
||||
open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
open AdventOfCode2022
|
||||
|
||||
[<TestFixture>]
|
||||
module TestDay22 =
|
||||
|
||||
let input =
|
||||
""" ...#
|
||||
.#..
|
||||
#...
|
||||
....
|
||||
...#.......#
|
||||
........#...
|
||||
..#....#....
|
||||
..........#.
|
||||
...#....
|
||||
.....#..
|
||||
.#......
|
||||
......#.
|
||||
|
||||
10R5L5R10L4R5L5
|
||||
"""
|
||||
|
||||
[<Test>]
|
||||
let ``Part 1, given`` () =
|
||||
Day22.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 6032
|
||||
|
||||
[<Test>]
|
||||
let ``Part 1`` () =
|
||||
let input = Assembly.readResource "Day22.txt"
|
||||
|
||||
Day22.part1 (StringSplitEnumerator.make '\n' input) |> shouldEqual 103224
|
||||
|
||||
|
||||
[<Test>]
|
||||
let ``Part 2, given`` () =
|
||||
Day22.part2Example (StringSplitEnumerator.make '\n' input) |> shouldEqual 5031
|
||||
|
||||
[<Test>]
|
||||
let ``Part 2`` () =
|
||||
let input = Assembly.readResource "Day22.txt"
|
||||
|
||||
Day22.part2 (StringSplitEnumerator.make '\n' input) |> shouldEqual 189097
|
202
AdventOfCode2022.Test/Inputs/Day22.txt
Normal file
202
AdventOfCode2022.Test/Inputs/Day22.txt
Normal file
File diff suppressed because one or more lines are too long
@@ -33,6 +33,7 @@
|
||||
<Compile Include="Day19.fs" />
|
||||
<Compile Include="Day20.fs" />
|
||||
<Compile Include="Day21.fs" />
|
||||
<Compile Include="Day22.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -11,6 +11,7 @@ open Checked
|
||||
#nowarn "9"
|
||||
#endif
|
||||
|
||||
[<Struct>]
|
||||
type Coordinate =
|
||||
{
|
||||
X : int
|
||||
|
@@ -12,28 +12,73 @@ open Checked
|
||||
[<Struct>]
|
||||
[<IsReadOnly>]
|
||||
type Day13Packet =
|
||||
| PacketList of leaf : Day13Packet[]
|
||||
| Int of int : int
|
||||
{
|
||||
Packet : Day13Packet ResizeArray ValueOption
|
||||
/// If Packet is None, this is an int.
|
||||
/// If Packet is Some, this is the start index of a slice.
|
||||
StartIndexOrInt : int
|
||||
}
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Day13 =
|
||||
|
||||
/// True if they're in the right order.
|
||||
let rec cmp (packet1 : Day13Packet) (packet2 : Day13Packet) : bool option =
|
||||
match packet1, packet2 with
|
||||
| Day13Packet.Int i1, Day13Packet.Int i2 ->
|
||||
if i1 < i2 then Some true
|
||||
elif i1 > i2 then Some false
|
||||
else None
|
||||
| PacketList [||], PacketList [||] -> None
|
||||
| PacketList [||], PacketList _ -> Some true
|
||||
| PacketList _, PacketList [||] -> Some false
|
||||
| PacketList arr1, PacketList arr2 ->
|
||||
match cmp arr1.[0] arr2.[0] with
|
||||
| Some v -> Some v
|
||||
| None -> cmp (PacketList arr1.[1..]) (PacketList arr2.[1..])
|
||||
| PacketList _, Int _ -> cmp packet1 (PacketList [| packet2 |])
|
||||
| Int _, PacketList _ -> cmp (PacketList [| packet1 |]) packet2
|
||||
let rec cmp (packet1 : Day13Packet) (packet2 : Day13Packet) : bool ValueOption =
|
||||
match packet1.Packet, packet2.Packet with
|
||||
| ValueNone, ValueNone ->
|
||||
if packet1.StartIndexOrInt < packet2.StartIndexOrInt then
|
||||
ValueSome true
|
||||
elif packet1.StartIndexOrInt > packet2.StartIndexOrInt then
|
||||
ValueSome false
|
||||
else
|
||||
ValueNone
|
||||
| ValueSome arr1, ValueSome arr2 ->
|
||||
if packet1.StartIndexOrInt = arr1.Count then
|
||||
if packet2.StartIndexOrInt = arr2.Count then
|
||||
ValueNone
|
||||
else
|
||||
ValueSome true
|
||||
elif packet2.StartIndexOrInt = arr2.Count then
|
||||
ValueSome false
|
||||
else
|
||||
match cmp arr1.[packet1.StartIndexOrInt] arr2.[packet2.StartIndexOrInt] with
|
||||
| ValueSome v -> ValueSome v
|
||||
| ValueNone ->
|
||||
let advanced1 =
|
||||
{
|
||||
Packet = ValueSome arr1
|
||||
StartIndexOrInt = packet1.StartIndexOrInt + 1
|
||||
}
|
||||
|
||||
let advanced2 =
|
||||
{
|
||||
Packet = ValueSome arr2
|
||||
StartIndexOrInt = packet2.StartIndexOrInt + 1
|
||||
}
|
||||
|
||||
cmp advanced1 advanced2
|
||||
| ValueSome arr1, ValueNone ->
|
||||
if packet1.StartIndexOrInt = arr1.Count then
|
||||
ValueSome true
|
||||
else
|
||||
match cmp arr1.[packet1.StartIndexOrInt] packet2 with
|
||||
| ValueSome v -> ValueSome v
|
||||
| ValueNone ->
|
||||
if packet1.StartIndexOrInt + 1 = arr1.Count then
|
||||
ValueNone
|
||||
else
|
||||
ValueSome false
|
||||
| ValueNone, ValueSome arr2 ->
|
||||
if packet2.StartIndexOrInt = arr2.Count then
|
||||
ValueSome false
|
||||
else
|
||||
match cmp packet1 arr2.[packet2.StartIndexOrInt] with
|
||||
| ValueSome v -> ValueSome v
|
||||
| ValueNone ->
|
||||
if packet2.StartIndexOrInt + 1 = arr2.Count then
|
||||
ValueNone
|
||||
else
|
||||
ValueSome true
|
||||
|
||||
let parse (lines : StringSplitEnumerator) : Day13Packet ResizeArray =
|
||||
use mutable enum = lines
|
||||
@@ -54,12 +99,20 @@ module Day13 =
|
||||
curr <- curr.Slice 1
|
||||
|
||||
if curr.[0] <> ']' then
|
||||
stack
|
||||
.Peek()
|
||||
.Add (Day13Packet.Int (Int32.Parse (curr.TrimEnd ']', NumberStyles.None)))
|
||||
let int =
|
||||
{
|
||||
StartIndexOrInt = Int32.Parse (curr.TrimEnd ']', NumberStyles.None)
|
||||
Packet = ValueNone
|
||||
}
|
||||
|
||||
stack.Peek().Add int
|
||||
|
||||
while curr.Length > 0 && curr.[curr.Length - 1] = ']' do
|
||||
let closed = Day13Packet.PacketList (stack.Pop().ToArray ())
|
||||
let closed =
|
||||
{
|
||||
Packet = ValueSome (stack.Pop ())
|
||||
StartIndexOrInt = 0
|
||||
}
|
||||
|
||||
if stack.Count = 0 then
|
||||
output.Add closed
|
||||
@@ -77,39 +130,66 @@ module Day13 =
|
||||
|
||||
for i in 0..2 .. data.Count - 1 do
|
||||
match cmp data.[i] data.[i + 1] with
|
||||
| None -> failwith "should have decided"
|
||||
| Some false -> ()
|
||||
| Some true -> sum <- sum + (i / 2 + 1)
|
||||
| ValueNone -> failwith "should have decided"
|
||||
| ValueSome false -> ()
|
||||
| ValueSome true -> sum <- sum + (i / 2 + 1)
|
||||
|
||||
sum
|
||||
|
||||
|
||||
let part2 (lines : StringSplitEnumerator) : int =
|
||||
let data = parse lines
|
||||
|
||||
let marker1 =
|
||||
Day13Packet.PacketList [| Day13Packet.PacketList [| Day13Packet.Int 2 |] |]
|
||||
let arr = ResizeArray 1
|
||||
let arr2 = ResizeArray 1
|
||||
|
||||
data.Add marker1
|
||||
arr2.Add
|
||||
{
|
||||
StartIndexOrInt = 2
|
||||
Packet = ValueNone
|
||||
}
|
||||
|
||||
arr.Add
|
||||
{
|
||||
StartIndexOrInt = 0
|
||||
Packet = ValueSome arr2
|
||||
}
|
||||
|
||||
{
|
||||
Packet = ValueSome arr
|
||||
StartIndexOrInt = 0
|
||||
}
|
||||
|
||||
let marker2 =
|
||||
Day13Packet.PacketList [| Day13Packet.PacketList [| Day13Packet.Int 6 |] |]
|
||||
let arr = ResizeArray 1
|
||||
let arr2 = ResizeArray 1
|
||||
|
||||
data.Add marker2
|
||||
let data = data.ToArray () |> Array.indexed
|
||||
Array.sortInPlaceWith (fun (_, a) (_, b) -> if Option.get (cmp a b) then -1 else 1) data
|
||||
arr2.Add
|
||||
{
|
||||
StartIndexOrInt = 6
|
||||
Packet = ValueNone
|
||||
}
|
||||
|
||||
let mutable answer = 1
|
||||
let mutable keepGoing = true
|
||||
let mutable i = 0
|
||||
arr.Add
|
||||
{
|
||||
StartIndexOrInt = 0
|
||||
Packet = ValueSome arr2
|
||||
}
|
||||
|
||||
while keepGoing do
|
||||
if answer = 1 && fst data.[i] = data.Length - 2 then
|
||||
answer <- answer * (i + 1)
|
||||
elif fst data.[i] = data.Length - 1 then
|
||||
answer <- answer * (i + 1)
|
||||
keepGoing <- false
|
||||
{
|
||||
Packet = ValueSome arr
|
||||
StartIndexOrInt = 0
|
||||
}
|
||||
|
||||
i <- i + 1
|
||||
let mutable howManyLessThan = 0
|
||||
let mutable howManyGreaterThan = 0
|
||||
|
||||
answer
|
||||
for i in 0 .. data.Count - 1 do
|
||||
match cmp data.[i] marker1 with
|
||||
| ValueSome true -> howManyLessThan <- howManyLessThan + 1
|
||||
| _ ->
|
||||
match cmp marker2 data.[i] with
|
||||
| ValueSome true -> howManyGreaterThan <- howManyGreaterThan + 1
|
||||
| _ -> ()
|
||||
|
||||
(howManyLessThan + 1) * (data.Count - howManyGreaterThan + 2)
|
||||
|
@@ -14,6 +14,13 @@ open Checked
|
||||
|
||||
type Day14Shape = Coordinate ResizeArray
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
type MutableCoordinate =
|
||||
{
|
||||
mutable X : int
|
||||
mutable Y : int
|
||||
}
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Day14 =
|
||||
|
||||
@@ -33,7 +40,7 @@ module Day14 =
|
||||
let y = StringSplitEnumerator.consumeInt &coords
|
||||
|
||||
{
|
||||
X = x
|
||||
Coordinate.X = x
|
||||
Y = y
|
||||
}
|
||||
|> thisLine.Add
|
||||
@@ -55,12 +62,6 @@ module Day14 =
|
||||
for x = min point1.X point2.X to max point1.X point2.X do
|
||||
Arr2D.set arr x point1.Y true
|
||||
|
||||
type MutableCoordinate =
|
||||
{
|
||||
mutable X : int
|
||||
mutable Y : int
|
||||
}
|
||||
|
||||
let inline fallOnce (sandPos : MutableCoordinate) (arr : Arr2D<bool>) : bool =
|
||||
if not (Arr2D.get arr sandPos.X (sandPos.Y + 1)) then
|
||||
sandPos.Y <- sandPos.Y + 1
|
||||
@@ -101,7 +102,7 @@ module Day14 =
|
||||
let sandPos =
|
||||
{
|
||||
MutableCoordinate.X = 500
|
||||
Y = 0
|
||||
MutableCoordinate.Y = 0
|
||||
}
|
||||
|
||||
let mutable stillFalling = true
|
||||
@@ -166,7 +167,7 @@ module Day14 =
|
||||
let sandPos =
|
||||
{
|
||||
MutableCoordinate.X = 1000
|
||||
Y = 0
|
||||
MutableCoordinate.Y = 0
|
||||
}
|
||||
|
||||
let mutable stillFalling = true
|
||||
|
@@ -79,14 +79,13 @@ module Day15 =
|
||||
keepGoing
|
||||
|
||||
let toHashSet (arr : Coordinate ResizeArray) : Coordinate HashSet =
|
||||
let output = HashSet ()
|
||||
let output = HashSet arr.Count
|
||||
|
||||
for beacon in arr do
|
||||
output.Add beacon |> ignore
|
||||
|
||||
output
|
||||
|
||||
|
||||
let part1 (y : int) (lines : StringSplitEnumerator) : int =
|
||||
let sensors, beacons = parse lines
|
||||
|
||||
|
@@ -31,7 +31,6 @@ module Day21 =
|
||||
type Day21Input =
|
||||
| Literal of int
|
||||
| Operation of Day21Name * Day21Name * Day21Operation
|
||||
| Calculated of float
|
||||
|
||||
/// Returns the name of the root node and human node, too.
|
||||
let parse (line : StringSplitEnumerator) : Dictionary<Day21Name, Day21Input> * Day21Name * Day21Name =
|
||||
@@ -77,20 +76,28 @@ module Day21 =
|
||||
| Day21Operation.Divide -> v1 / v2
|
||||
| _ -> failwith "bad enum"
|
||||
|
||||
let rec evaluate (d : Dictionary<Day21Name, Day21Input>) (s : Day21Name) : float =
|
||||
let rec evaluate
|
||||
(calculated : Dictionary<Day21Name, float>)
|
||||
(d : Dictionary<Day21Name, Day21Input>)
|
||||
(s : Day21Name)
|
||||
: float
|
||||
=
|
||||
match calculated.TryGetValue s with
|
||||
| true, v -> v
|
||||
| false, _ ->
|
||||
|
||||
match d.[s] with
|
||||
| Day21Input.Literal v ->
|
||||
let result = float v
|
||||
d.[s] <- Day21Input.Calculated result
|
||||
calculated.[s] <- result
|
||||
result
|
||||
| Day21Input.Calculated f -> f
|
||||
| Day21Input.Operation (s1, s2, op) ->
|
||||
let v1 = evaluate d s1
|
||||
let v2 = evaluate d s2
|
||||
let v1 = evaluate calculated d s1
|
||||
let v2 = evaluate calculated d s2
|
||||
|
||||
let result = compute v1 v2 op
|
||||
|
||||
d.[s] <- Day21Input.Calculated result
|
||||
calculated.[s] <- result
|
||||
result
|
||||
|
||||
let inline round (v : float) : int64 =
|
||||
@@ -103,8 +110,9 @@ module Day21 =
|
||||
|
||||
let part1 (lines : StringSplitEnumerator) : int64 =
|
||||
let original, root, _ = parse lines
|
||||
let calculated = Dictionary original.Count
|
||||
|
||||
let result = evaluate original root
|
||||
let result = evaluate calculated original root
|
||||
|
||||
round result
|
||||
|
||||
@@ -135,7 +143,6 @@ module Day21 =
|
||||
let answer = Day21Expr.Literal (float v)
|
||||
result.[key] <- answer
|
||||
answer
|
||||
| Day21Input.Calculated _ -> failwith "no never"
|
||||
| Day21Input.Operation (s1, s2, op) ->
|
||||
let v1 = convert human s1 d result
|
||||
let v2 = convert human s2 d result
|
||||
@@ -153,8 +160,7 @@ module Day21 =
|
||||
|
||||
let lhs, rhs =
|
||||
match original.[root] with
|
||||
| Day21Input.Literal _
|
||||
| Day21Input.Calculated _ -> failwith "expected operation"
|
||||
| Day21Input.Literal _ -> failwith "expected operation"
|
||||
| Day21Input.Operation (s1, s2, _) -> s1, s2
|
||||
|
||||
let converted = Dictionary original.Count
|
||||
|
550
AdventOfCode2022/Day22.fs
Normal file
550
AdventOfCode2022/Day22.fs
Normal file
@@ -0,0 +1,550 @@
|
||||
namespace AdventOfCode2022
|
||||
|
||||
open System
|
||||
|
||||
#if DEBUG
|
||||
open Checked
|
||||
#else
|
||||
#nowarn "9"
|
||||
#endif
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Day22 =
|
||||
|
||||
/// Returns the board (where 0 means "nothing here", 1 means "space", 2 means "wall"),
|
||||
/// the set of instructions (move * change-direction), and the final trailing instruction to move.
|
||||
let parse (line : StringSplitEnumerator) : int[][] * ResizeArray<struct (int * Direction)> * int =
|
||||
use mutable enum = line.GetEnumerator ()
|
||||
let output = ResizeArray ()
|
||||
|
||||
let mutable maxBoardLength = 0
|
||||
let row = ResizeArray ()
|
||||
// 2 here in case there's a trailing \r
|
||||
while enum.MoveNext () && enum.Current.Length >= 2 do
|
||||
for i = 0 to enum.Current.Length - 1 do
|
||||
match enum.Current.[i] with
|
||||
| ' ' -> row.Add 0
|
||||
| '.' -> row.Add 1
|
||||
| '#' -> row.Add 2
|
||||
| '\r' -> ()
|
||||
| c -> failwithf "unexpected char: %c" c
|
||||
|
||||
output.Add (row.ToArray ())
|
||||
maxBoardLength <- max maxBoardLength row.Count
|
||||
row.Clear ()
|
||||
|
||||
if not (enum.MoveNext ()) then
|
||||
failwith "expected instruction line"
|
||||
|
||||
let directions = ResizeArray ()
|
||||
let line = enum.Current.TrimEnd ()
|
||||
let mutable i = 0
|
||||
|
||||
for count = 0 to line.Length - 1 do
|
||||
if '0' <= line.[count] && line.[count] <= '9' then
|
||||
i <- i * 10 + (int line.[count] - int '0')
|
||||
else
|
||||
let dir =
|
||||
match line.[count] with
|
||||
| 'L' -> Direction.Left
|
||||
| 'R' -> Direction.Right
|
||||
| c -> failwithf "Unexpected: %c" c
|
||||
|
||||
directions.Add (struct (i, dir))
|
||||
i <- 0
|
||||
|
||||
let finalOutput =
|
||||
Array.init
|
||||
output.Count
|
||||
(fun i -> Array.append output.[i] (Array.zeroCreate (maxBoardLength - output.[i].Length)))
|
||||
|
||||
finalOutput, directions, i
|
||||
|
||||
let inline rotateRight (dir : Direction) =
|
||||
match dir with
|
||||
| Direction.Up -> Direction.Right
|
||||
| Direction.Right -> Direction.Down
|
||||
| Direction.Down -> Direction.Left
|
||||
| Direction.Left -> Direction.Up
|
||||
| _ -> failwith "bad direction"
|
||||
|
||||
let inline rotateLeft (dir : Direction) =
|
||||
match dir with
|
||||
| Direction.Up -> Direction.Left
|
||||
| Direction.Right -> Direction.Up
|
||||
| Direction.Down -> Direction.Right
|
||||
| Direction.Left -> Direction.Down
|
||||
| _ -> failwith "bad direction"
|
||||
|
||||
/// Returns false if we got stuck due to a wall.
|
||||
let private moveOneStep (currPos : MutableCoordinate) (direction : Direction) (board : int[][]) : bool =
|
||||
let answer =
|
||||
{
|
||||
MutableCoordinate.X = currPos.X
|
||||
MutableCoordinate.Y = currPos.Y
|
||||
}
|
||||
|
||||
match direction with
|
||||
| Direction.Up ->
|
||||
if answer.Y = 0 then
|
||||
answer.Y <- board.Length - 1
|
||||
else
|
||||
answer.Y <- answer.Y - 1
|
||||
|
||||
while board.[answer.Y].[answer.X] = 0 do
|
||||
if answer.Y = 0 then
|
||||
answer.Y <- board.Length - 1
|
||||
else
|
||||
answer.Y <- answer.Y - 1
|
||||
| Direction.Down ->
|
||||
if answer.Y = board.Length - 1 then
|
||||
answer.Y <- 0
|
||||
else
|
||||
answer.Y <- answer.Y + 1
|
||||
|
||||
while board.[answer.Y].[answer.X] = 0 do
|
||||
if answer.Y = board.Length - 1 then
|
||||
answer.Y <- 0
|
||||
else
|
||||
answer.Y <- answer.Y + 1
|
||||
| Direction.Left ->
|
||||
if answer.X = 0 then
|
||||
answer.X <- board.[0].Length - 1
|
||||
else
|
||||
answer.X <- answer.X - 1
|
||||
|
||||
while board.[answer.Y].[answer.X] = 0 do
|
||||
if answer.X = 0 then
|
||||
answer.X <- board.[0].Length - 1
|
||||
else
|
||||
answer.X <- answer.X - 1
|
||||
| Direction.Right ->
|
||||
if answer.X = board.[0].Length - 1 then
|
||||
answer.X <- 0
|
||||
else
|
||||
answer.X <- answer.X + 1
|
||||
|
||||
while board.[answer.Y].[answer.X] = 0 do
|
||||
if answer.X = board.[0].Length - 1 then
|
||||
answer.X <- 0
|
||||
else
|
||||
answer.X <- answer.X + 1
|
||||
| _ -> failwith "noooo"
|
||||
|
||||
if board.[answer.Y].[answer.X] <> 2 then
|
||||
currPos.X <- answer.X
|
||||
currPos.Y <- answer.Y
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
let moveDistance (currPos : MutableCoordinate) (direction : Direction) (distance : int) (board : int[][]) : unit =
|
||||
let mutable i = 0
|
||||
let mutable keepGoing = true
|
||||
|
||||
while keepGoing && i < distance do
|
||||
keepGoing <- moveOneStep currPos direction board
|
||||
i <- i + 1
|
||||
|
||||
let inline answer (position : Coordinate) (direction : Direction) =
|
||||
let finalFacing =
|
||||
match direction with
|
||||
| Direction.Right -> 0
|
||||
| Direction.Down -> 1
|
||||
| Direction.Left -> 2
|
||||
| Direction.Up -> 3
|
||||
| _ -> failwith "oh no"
|
||||
|
||||
1000 * (position.Y + 1) + 4 * (position.X + 1) + finalFacing
|
||||
|
||||
let part1 (lines : StringSplitEnumerator) : int =
|
||||
let board, instructions, finalDistance = parse lines
|
||||
|
||||
let position =
|
||||
{
|
||||
MutableCoordinate.Y = 0
|
||||
MutableCoordinate.X = Array.IndexOf (board.[0], 1)
|
||||
}
|
||||
|
||||
let mutable direction = Direction.Right
|
||||
|
||||
for struct (distance, rotation) in instructions do
|
||||
moveDistance position direction distance board
|
||||
|
||||
direction <-
|
||||
match rotation with
|
||||
| Direction.Right -> rotateRight direction
|
||||
| Direction.Left -> rotateLeft direction
|
||||
| _ -> failwith "bad rotation"
|
||||
|
||||
moveDistance position direction finalDistance board
|
||||
|
||||
answer
|
||||
{
|
||||
X = position.X
|
||||
Y = position.Y
|
||||
}
|
||||
direction
|
||||
|
||||
/// If we walk off the given number of face in the given direction, where do we end up?
|
||||
/// Returns an additional "true" if we need to interchange Y and X.
|
||||
let newFaceOnExample
|
||||
(cubeSize : int)
|
||||
(face : int)
|
||||
(direction : Direction)
|
||||
: int * Direction * (struct (int * int) -> struct (int * int))
|
||||
=
|
||||
match face, direction with
|
||||
| 1, Direction.Up -> 2, Direction.Down, (fun (struct (x, y)) -> struct (cubeSize - x - 1, 0))
|
||||
| 1, Direction.Down -> 4, Direction.Down, (fun (struct (x, _)) -> struct (x, 0))
|
||||
| 1, Direction.Left -> 3, Direction.Down, (fun (struct (_, y)) -> struct (y, 0))
|
||||
| 1, Direction.Right -> 6, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, cubeSize - y - 1))
|
||||
| 2, Direction.Up -> 1, Direction.Down, (fun (struct (x, y)) -> struct (cubeSize - x - 1, 0))
|
||||
| 2, Direction.Down -> 5, Direction.Up, (fun (struct (x, y)) -> struct (cubeSize - x - 1, cubeSize - 1))
|
||||
| 2, Direction.Left -> 6, Direction.Up, (fun (struct (_, y)) -> struct (cubeSize - y - 1, cubeSize - 1))
|
||||
| 2, Direction.Right -> 3, Direction.Right, (fun (struct (x, y)) -> struct (0, y))
|
||||
| 3, Direction.Up -> 1, Direction.Right, (fun (struct (x, y)) -> struct (0, x))
|
||||
| 3, Direction.Down -> 5, Direction.Right, (fun (struct (x, y)) -> struct (0, cubeSize - 1 - y))
|
||||
| 3, Direction.Left -> 2, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, y))
|
||||
| 3, Direction.Right -> 4, Direction.Right, (fun (struct (x, y)) -> struct (0, y))
|
||||
| 4, Direction.Up -> 1, Direction.Up, (fun (struct (x, _)) -> struct (x, cubeSize - 1))
|
||||
| 4, Direction.Down -> 5, Direction.Down, (fun (struct (x, _)) -> struct (x, 0))
|
||||
| 4, Direction.Left -> 3, Direction.Left, (fun (struct (x, _)) -> struct (x, cubeSize - 1))
|
||||
| 4, Direction.Right -> 6, Direction.Down, (fun (struct (_, y)) -> struct (cubeSize - 1 - y, 0))
|
||||
| 5, Direction.Up -> 4, Direction.Up, (fun (struct (x, y)) -> struct (x, cubeSize - 1))
|
||||
| 5, Direction.Down -> 2, Direction.Up, (fun (struct (x, y)) -> struct (cubeSize - x - 1, cubeSize - 1))
|
||||
| 5, Direction.Left -> 3, Direction.Up, (fun (struct (x, y)) -> struct (cubeSize - y - 1, cubeSize - 1))
|
||||
| 5, Direction.Right -> 6, Direction.Right, (fun (struct (x, y)) -> struct (0, y))
|
||||
| 6, Direction.Up -> 4, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, cubeSize - x - 1))
|
||||
| 6, Direction.Down -> 2, Direction.Right, (fun (struct (x, y)) -> failwith "TODO")
|
||||
| 6, Direction.Left -> 5, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, y))
|
||||
| 6, Direction.Right -> 1, Direction.Left, (fun (struct (x, y)) -> failwith "TODO")
|
||||
| _ -> failwith "bad face"
|
||||
|
||||
let inline toArrayElementOnExample (faceSize : int) (face : int) (position : Coordinate) : Coordinate =
|
||||
match face with
|
||||
| 1 ->
|
||||
{
|
||||
X = position.X + 2 * faceSize
|
||||
Y = position.Y
|
||||
}
|
||||
| 2 ->
|
||||
{
|
||||
X = position.X
|
||||
Y = position.Y + faceSize
|
||||
}
|
||||
| 3 ->
|
||||
{
|
||||
X = position.X + faceSize
|
||||
Y = position.Y + faceSize
|
||||
}
|
||||
| 4 ->
|
||||
{
|
||||
X = position.X + 2 * faceSize
|
||||
Y = position.Y + faceSize
|
||||
}
|
||||
| 5 ->
|
||||
{
|
||||
X = position.X + 2 * faceSize
|
||||
Y = position.Y + 2 * faceSize
|
||||
}
|
||||
| 6 ->
|
||||
{
|
||||
X = position.X + 3 * faceSize
|
||||
Y = position.Y + 2 * faceSize
|
||||
}
|
||||
| _ -> failwith "bad face"
|
||||
|
||||
/// Returns false if we got stuck due to a wall.
|
||||
/// The position is referring to the position within the given face.
|
||||
let inline private moveOneStepCube
|
||||
(cubeSize : int)
|
||||
([<InlineIfLambda>] toArrayElement : int -> Coordinate -> Coordinate)
|
||||
([<InlineIfLambda>] newFace : int -> Direction -> int * Direction * (struct (int * int) -> struct (int * int)))
|
||||
(currFace : byref<int>)
|
||||
(currPos : MutableCoordinate)
|
||||
(direction : byref<Direction>)
|
||||
(board : int[][])
|
||||
: bool
|
||||
=
|
||||
// If we do walk off this face, where do we end up?
|
||||
let faceAfterSpill, directionAfterSpill, transformPosition =
|
||||
newFace currFace direction
|
||||
|
||||
let intendedDest, face, newDirection =
|
||||
match direction with
|
||||
| Direction.Up ->
|
||||
if currPos.Y = 0 then
|
||||
let struct (x, y) = transformPosition (struct (currPos.X, currPos.Y))
|
||||
|
||||
{
|
||||
X = x
|
||||
Y = y
|
||||
},
|
||||
faceAfterSpill,
|
||||
directionAfterSpill
|
||||
else
|
||||
{
|
||||
X = currPos.X
|
||||
Y = currPos.Y - 1
|
||||
},
|
||||
currFace,
|
||||
direction
|
||||
| Direction.Down ->
|
||||
if currPos.Y = cubeSize - 1 then
|
||||
let struct (x, y) = transformPosition (struct (currPos.X, currPos.Y))
|
||||
|
||||
{
|
||||
X = x
|
||||
Y = y
|
||||
},
|
||||
faceAfterSpill,
|
||||
directionAfterSpill
|
||||
else
|
||||
{
|
||||
X = currPos.X
|
||||
Y = currPos.Y + 1
|
||||
},
|
||||
currFace,
|
||||
direction
|
||||
| Direction.Left ->
|
||||
if currPos.X = 0 then
|
||||
let struct (x, y) = transformPosition (struct (currPos.X, currPos.Y))
|
||||
|
||||
{
|
||||
X = x
|
||||
Y = y
|
||||
},
|
||||
faceAfterSpill,
|
||||
directionAfterSpill
|
||||
else
|
||||
{
|
||||
X = currPos.X - 1
|
||||
Y = currPos.Y
|
||||
},
|
||||
currFace,
|
||||
direction
|
||||
| Direction.Right ->
|
||||
if currPos.X = cubeSize - 1 then
|
||||
let struct (x, y) = transformPosition (struct (currPos.X, currPos.Y))
|
||||
|
||||
{
|
||||
X = x
|
||||
Y = y
|
||||
},
|
||||
faceAfterSpill,
|
||||
directionAfterSpill
|
||||
else
|
||||
{
|
||||
X = currPos.X + 1
|
||||
Y = currPos.Y
|
||||
},
|
||||
currFace,
|
||||
direction
|
||||
| _ -> failwith "noooo"
|
||||
|
||||
let pos = toArrayElement face intendedDest
|
||||
|
||||
if board.[pos.Y].[pos.X] <> 2 then
|
||||
currPos.X <- intendedDest.X
|
||||
currPos.Y <- intendedDest.Y
|
||||
currFace <- face
|
||||
direction <- newDirection
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
let inline moveCubeDistance
|
||||
(cubeSize : int)
|
||||
([<InlineIfLambda>] toArrayElement : int -> Coordinate -> Coordinate)
|
||||
([<InlineIfLambda>] newFace : int -> Direction -> int * Direction * (struct (int * int) -> struct (int * int)))
|
||||
(currFace : byref<int>)
|
||||
(currPos : MutableCoordinate)
|
||||
(direction : byref<Direction>)
|
||||
(distance : int)
|
||||
(board : int[][])
|
||||
: unit
|
||||
=
|
||||
let mutable i = 0
|
||||
let mutable keepGoing = true
|
||||
|
||||
while keepGoing && i < distance do
|
||||
keepGoing <- moveOneStepCube cubeSize toArrayElement newFace &currFace currPos &direction board
|
||||
i <- i + 1
|
||||
|
||||
let part2Example (lines : StringSplitEnumerator) : int =
|
||||
let board, instructions, finalDistance = parse lines
|
||||
let faceSize = 4
|
||||
|
||||
let position =
|
||||
{
|
||||
MutableCoordinate.X = 0
|
||||
MutableCoordinate.Y = 0
|
||||
}
|
||||
|
||||
let mutable direction = Direction.Right
|
||||
let mutable face = 1
|
||||
|
||||
for struct (distance, rotation) in instructions do
|
||||
moveCubeDistance
|
||||
faceSize
|
||||
(toArrayElementOnExample faceSize)
|
||||
(newFaceOnExample faceSize)
|
||||
&face
|
||||
position
|
||||
&direction
|
||||
distance
|
||||
board
|
||||
|
||||
direction <-
|
||||
match rotation with
|
||||
| Direction.Right -> rotateRight direction
|
||||
| Direction.Left -> rotateLeft direction
|
||||
| _ -> failwith "bad rotation"
|
||||
|
||||
moveCubeDistance
|
||||
faceSize
|
||||
(toArrayElementOnExample faceSize)
|
||||
(newFaceOnExample faceSize)
|
||||
&face
|
||||
position
|
||||
&direction
|
||||
finalDistance
|
||||
board
|
||||
|
||||
let faceDimension = board.Length / 3
|
||||
|
||||
let position =
|
||||
toArrayElementOnExample
|
||||
faceDimension
|
||||
face
|
||||
{
|
||||
X = position.X
|
||||
Y = position.Y
|
||||
}
|
||||
|
||||
answer position direction
|
||||
|
||||
// The real thing has shape:
|
||||
// _12
|
||||
// _3_
|
||||
// 45_
|
||||
// 6__
|
||||
|
||||
let inline toArrayElement (faceSize : int) (face : int) (position : Coordinate) : Coordinate =
|
||||
match face with
|
||||
| 1 ->
|
||||
{
|
||||
X = position.X + faceSize
|
||||
Y = position.Y
|
||||
}
|
||||
| 2 ->
|
||||
{
|
||||
X = position.X + 2 * faceSize
|
||||
Y = position.Y
|
||||
}
|
||||
| 3 ->
|
||||
{
|
||||
X = position.X + faceSize
|
||||
Y = position.Y + faceSize
|
||||
}
|
||||
| 4 ->
|
||||
{
|
||||
X = position.X
|
||||
Y = position.Y + 2 * faceSize
|
||||
}
|
||||
| 5 ->
|
||||
{
|
||||
X = position.X + faceSize
|
||||
Y = position.Y + 2 * faceSize
|
||||
}
|
||||
| 6 ->
|
||||
{
|
||||
X = position.X
|
||||
Y = position.Y + 3 * faceSize
|
||||
}
|
||||
| _ -> failwith "bad face"
|
||||
|
||||
let inline newFace
|
||||
(cubeSize : int)
|
||||
(face : int)
|
||||
(direction : Direction)
|
||||
: int * Direction * (struct (int * int) -> struct (int * int))
|
||||
=
|
||||
match face, direction with
|
||||
| 1, Direction.Up -> 6, Direction.Right, (fun (struct (x, y)) -> struct (0, x))
|
||||
| 1, Direction.Down -> 3, Direction.Down, (fun (struct (x, _)) -> struct (x, 0))
|
||||
| 1, Direction.Left -> 4, Direction.Right, (fun (struct (x, y)) -> struct (0, cubeSize - 1 - y))
|
||||
| 1, Direction.Right -> 2, Direction.Right, (fun (struct (x, y)) -> struct (0, y))
|
||||
| 2, Direction.Up -> 6, Direction.Up, (fun (struct (x, y)) -> (x, cubeSize - 1))
|
||||
| 2, Direction.Down -> 3, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, x))
|
||||
| 2, Direction.Left -> 1, Direction.Left, (fun (struct (_, y)) -> struct (cubeSize - 1, y))
|
||||
| 2, Direction.Right -> 5, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, cubeSize - 1 - y))
|
||||
| 3, Direction.Up -> 1, Direction.Up, (fun (struct (x, y)) -> struct (x, cubeSize - 1))
|
||||
| 3, Direction.Down -> 5, Direction.Down, (fun (struct (x, y)) -> struct (x, 0))
|
||||
| 3, Direction.Left -> 4, Direction.Down, (fun (struct (x, y)) -> struct (y, 0))
|
||||
| 3, Direction.Right -> 2, Direction.Up, (fun (struct (x, y)) -> struct (y, cubeSize - 1))
|
||||
| 4, Direction.Up -> 3, Direction.Right, (fun (struct (x, _)) -> struct (0, x))
|
||||
| 4, Direction.Down -> 6, Direction.Down, (fun (struct (x, _)) -> struct (x, 0))
|
||||
| 4, Direction.Left -> 1, Direction.Right, (fun (struct (x, y)) -> struct (0, cubeSize - 1 - y))
|
||||
| 4, Direction.Right -> 5, Direction.Right, (fun (struct (_, y)) -> struct (0, y))
|
||||
| 5, Direction.Up -> 3, Direction.Up, (fun (struct (x, y)) -> struct (x, cubeSize - 1))
|
||||
| 5, Direction.Down -> 6, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, x))
|
||||
| 5, Direction.Left -> 4, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, y))
|
||||
| 5, Direction.Right -> 2, Direction.Left, (fun (struct (x, y)) -> struct (cubeSize - 1, cubeSize - 1 - y))
|
||||
| 6, Direction.Up -> 4, Direction.Up, (fun (struct (x, y)) -> struct (x, cubeSize - 1))
|
||||
| 6, Direction.Down -> 2, Direction.Down, (fun (struct (x, y)) -> struct (x, 0))
|
||||
| 6, Direction.Left -> 1, Direction.Down, (fun (struct (x, y)) -> struct (y, 0))
|
||||
| 6, Direction.Right -> 5, Direction.Up, (fun (struct (x, y)) -> struct (y, cubeSize - 1))
|
||||
| _ -> failwith "bad face"
|
||||
|
||||
let part2 (lines : StringSplitEnumerator) : int =
|
||||
let board, instructions, finalDistance = parse lines
|
||||
let faceSize = board.[0].Length / 3
|
||||
|
||||
let position =
|
||||
{
|
||||
MutableCoordinate.X = 0
|
||||
MutableCoordinate.Y = 0
|
||||
}
|
||||
|
||||
let mutable direction = Direction.Right
|
||||
let mutable face = 1
|
||||
|
||||
for struct (distance, rotation) in instructions do
|
||||
moveCubeDistance
|
||||
faceSize
|
||||
(toArrayElement faceSize)
|
||||
(newFace faceSize)
|
||||
&face
|
||||
position
|
||||
&direction
|
||||
distance
|
||||
board
|
||||
|
||||
direction <-
|
||||
match rotation with
|
||||
| Direction.Right -> rotateRight direction
|
||||
| Direction.Left -> rotateLeft direction
|
||||
| _ -> failwith "bad rotation"
|
||||
|
||||
moveCubeDistance
|
||||
faceSize
|
||||
(toArrayElement faceSize)
|
||||
(newFace faceSize)
|
||||
&face
|
||||
position
|
||||
&direction
|
||||
finalDistance
|
||||
board
|
||||
|
||||
let position =
|
||||
toArrayElement
|
||||
faceSize
|
||||
face
|
||||
{
|
||||
X = position.X
|
||||
Y = position.Y
|
||||
}
|
||||
|
||||
answer position direction
|
@@ -5,7 +5,7 @@ open System
|
||||
[<RequireQualifiedAccess>]
|
||||
module Day6 =
|
||||
|
||||
let findDuplicateSorted (a : 'a array) : int ValueOption =
|
||||
let inline findDuplicateSorted< ^a when ^a : equality> (a : 'a array) : int ValueOption =
|
||||
let mutable i = 0
|
||||
let mutable result = ValueNone
|
||||
|
||||
|
@@ -1,37 +1,38 @@
|
||||
namespace AdventOfCode2022
|
||||
|
||||
open System.Collections.Generic
|
||||
open System
|
||||
|
||||
#if DEBUG
|
||||
#else
|
||||
#nowarn "9"
|
||||
#endif
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Day8 =
|
||||
|
||||
let parse (lines : StringSplitEnumerator) : byte[,] =
|
||||
let parse (lines : StringSplitEnumerator) : byte array * int =
|
||||
use mutable enum = lines
|
||||
let output = ResizeArray ()
|
||||
let mutable lineCount = 0
|
||||
|
||||
for line in enum do
|
||||
let line = line.TrimEnd ()
|
||||
|
||||
if not (line.IsWhiteSpace ()) then
|
||||
let arr = Array.zeroCreate line.Length
|
||||
let mutable i = 0
|
||||
lineCount <- lineCount + 1
|
||||
|
||||
for c in line do
|
||||
arr.[i] <- byte c - byte '0'
|
||||
i <- i + 1
|
||||
output.Add (byte c - byte '0')
|
||||
|
||||
output.Add arr
|
||||
output.ToArray (), lineCount
|
||||
|
||||
Array2D.init output.Count output.[0].Length (fun x y -> output.[x].[y])
|
||||
|
||||
let isVisible (board : byte[,]) (x : int) (y : int) : bool =
|
||||
let isVisible (board : Arr2D<byte>) (x : int) (y : int) : bool =
|
||||
// From the left?
|
||||
let mutable isVisible = true
|
||||
let mutable i = 0
|
||||
|
||||
while i < x && isVisible do
|
||||
if board.[y, i] >= board.[y, x] then
|
||||
if Arr2D.get board i y >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
i <- i + 1
|
||||
@@ -42,10 +43,10 @@ module Day8 =
|
||||
|
||||
// From the right?
|
||||
let mutable isVisible = true
|
||||
let mutable i = board.GetLength 1 - 1
|
||||
let mutable i = board.Height - 1
|
||||
|
||||
while i > x && isVisible do
|
||||
if board.[y, i] >= board.[y, x] then
|
||||
if Arr2D.get board i y >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
i <- i - 1
|
||||
@@ -59,7 +60,7 @@ module Day8 =
|
||||
let mutable i = 0
|
||||
|
||||
while i < y && isVisible do
|
||||
if board.[i, x] >= board.[y, x] then
|
||||
if Arr2D.get board x i >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
i <- i + 1
|
||||
@@ -70,10 +71,10 @@ module Day8 =
|
||||
|
||||
// From the bottom?
|
||||
let mutable isVisible = true
|
||||
let mutable i = board.GetLength 0 - 1
|
||||
let mutable i = board.Width - 1
|
||||
|
||||
while i > y && isVisible do
|
||||
if board.[i, x] >= board.[y, x] then
|
||||
if Arr2D.get board x i >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
i <- i - 1
|
||||
@@ -81,18 +82,34 @@ module Day8 =
|
||||
isVisible
|
||||
|
||||
let part1 (lines : StringSplitEnumerator) : int =
|
||||
let board = parse lines
|
||||
let board, height = parse lines
|
||||
#if DEBUG
|
||||
let board =
|
||||
{
|
||||
Arr2D.Elements = board
|
||||
Width = board.Length / height
|
||||
}
|
||||
#else
|
||||
use p = fixed board
|
||||
|
||||
let board =
|
||||
{
|
||||
Arr2D.Elements = p
|
||||
Length = board.Length
|
||||
Width = board.Length / height
|
||||
}
|
||||
#endif
|
||||
|
||||
let mutable visibleCount = 0
|
||||
|
||||
for y = 0 to board.GetLength 0 - 1 do
|
||||
for x = 0 to board.GetLength 1 - 1 do
|
||||
for y = 0 to board.Height - 1 do
|
||||
for x = 0 to board.Width - 1 do
|
||||
if isVisible board x y then
|
||||
visibleCount <- visibleCount + 1
|
||||
|
||||
visibleCount
|
||||
|
||||
let scenicScore (board : byte[,]) (x : int) (y : int) : int =
|
||||
let scenicScore (board : Arr2D<byte>) (x : int) (y : int) : int =
|
||||
let mutable scenicCount = 0
|
||||
|
||||
do
|
||||
@@ -100,7 +117,7 @@ module Day8 =
|
||||
let mutable i = y - 1
|
||||
|
||||
while i >= 0 && isVisible do
|
||||
if board.[i, x] >= board.[y, x] then
|
||||
if Arr2D.get board x i >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
scenicCount <- scenicCount + 1
|
||||
@@ -112,8 +129,8 @@ module Day8 =
|
||||
let mutable i = y + 1
|
||||
let mutable subCount = 0
|
||||
|
||||
while i < board.GetLength 0 && isVisible do
|
||||
if board.[i, x] >= board.[y, x] then
|
||||
while i < board.Height && isVisible do
|
||||
if Arr2D.get board x i >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
subCount <- subCount + 1
|
||||
@@ -128,7 +145,7 @@ module Day8 =
|
||||
let mutable subCount = 0
|
||||
|
||||
while i >= 0 && isVisible do
|
||||
if board.[y, i] >= board.[y, x] then
|
||||
if Arr2D.get board i y >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
subCount <- subCount + 1
|
||||
@@ -142,8 +159,8 @@ module Day8 =
|
||||
let mutable i = x + 1
|
||||
let mutable subCount = 0
|
||||
|
||||
while i < board.GetLength 1 && isVisible do
|
||||
if board.[y, i] >= board.[y, x] then
|
||||
while i < board.Width && isVisible do
|
||||
if Arr2D.get board i y >= Arr2D.get board x y then
|
||||
isVisible <- false
|
||||
|
||||
subCount <- subCount + 1
|
||||
@@ -156,11 +173,28 @@ module Day8 =
|
||||
|
||||
|
||||
let part2 (lines : StringSplitEnumerator) : int =
|
||||
let board = parse lines
|
||||
let board, height = parse lines
|
||||
#if DEBUG
|
||||
let board =
|
||||
{
|
||||
Arr2D.Elements = board
|
||||
Width = board.Length / height
|
||||
}
|
||||
#else
|
||||
use p = fixed board
|
||||
|
||||
let board =
|
||||
{
|
||||
Arr2D.Elements = p
|
||||
Length = board.Length
|
||||
Width = board.Length / height
|
||||
}
|
||||
#endif
|
||||
|
||||
let mutable scenicMax = 0
|
||||
|
||||
for y = 0 to board.GetLength 0 - 1 do
|
||||
for x = 0 to board.GetLength 1 - 1 do
|
||||
for y = 0 to board.Height - 1 do
|
||||
for x = 0 to board.Width - 1 do
|
||||
scenicMax <- max scenicMax (scenicScore board x y)
|
||||
|
||||
scenicMax
|
||||
|
@@ -74,7 +74,7 @@ module Day9 =
|
||||
tailVisits.Add (struct (0, 0)) |> ignore
|
||||
|
||||
for direction, distance in directions do
|
||||
for _ in 1uy .. distance do
|
||||
for _ = 1 to int distance do
|
||||
let newHead = newHead (fst knots.[0]) (snd knots.[0]) direction
|
||||
knots.[0] <- newHead
|
||||
|
||||
|
@@ -10,5 +10,5 @@ Apple M1 Max, 1 CPU, 10 logical and 10 physical cores
|
||||
```
|
||||
| Method | Day | IsPartOne | Mean | Error | StdDev |
|
||||
|---------- |---- |---------- |---------:|---------:|---------:|
|
||||
| **Benchmark** | **21** | **False** | **678.3 μs** | **13.00 μs** | **15.48 μs** |
|
||||
| **Benchmark** | **21** | **True** | **612.3 μs** | **9.40 μs** | **8.79 μs** |
|
||||
| **Benchmark** | **21** | **False** | **654.8 μs** | **12.87 μs** | **13.22 μs** |
|
||||
| **Benchmark** | **21** | **True** | **577.8 μs** | **6.50 μs** | **6.08 μs** |
|
||||
|
@@ -1,3 +1,3 @@
|
||||
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Day,IsPartOne,Mean,Error,StdDev
|
||||
Benchmark,DefaultJob,False,Default,Default,Default,Default,Default,Default,0000000000,Empty,RyuJit,Arm64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 7.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,21,False,678.3 μs,13.00 μs,15.48 μs
|
||||
Benchmark,DefaultJob,False,Default,Default,Default,Default,Default,Default,0000000000,Empty,RyuJit,Arm64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 7.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,21,True,612.3 μs,9.40 μs,8.79 μs
|
||||
Benchmark,DefaultJob,False,Default,Default,Default,Default,Default,Default,0000000000,Empty,RyuJit,Arm64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 7.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,21,False,654.8 μs,12.87 μs,13.22 μs
|
||||
Benchmark,DefaultJob,False,Default,Default,Default,Default,Default,Default,0000000000,Empty,RyuJit,Arm64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 7.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,21,True,577.8 μs,6.50 μs,6.08 μs
|
||||
|
|
@@ -2,7 +2,7 @@
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<title>AdventOfCode2022.App.Benchmark21To25-20221221-100214</title>
|
||||
<title>AdventOfCode2022.App.Benchmark21To25-20221221-110833</title>
|
||||
|
||||
<style type="text/css">
|
||||
table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
|
||||
@@ -24,8 +24,8 @@ Apple M1 Max, 1 CPU, 10 logical and 10 physical cores
|
||||
<table>
|
||||
<thead><tr><th>Method</th><th>Day</th><th>IsPartOne</th><th>Mean</th><th>Error</th><th>StdDev</th>
|
||||
</tr>
|
||||
</thead><tbody><tr><td>Benchmark</td><td>21</td><td>False</td><td>678.3 μs</td><td>13.00 μs</td><td>15.48 μs</td>
|
||||
</tr><tr><td>Benchmark</td><td>21</td><td>True</td><td>612.3 μs</td><td>9.40 μs</td><td>8.79 μs</td>
|
||||
</thead><tbody><tr><td>Benchmark</td><td>21</td><td>False</td><td>654.8 μs</td><td>12.87 μs</td><td>13.22 μs</td>
|
||||
</tr><tr><td>Benchmark</td><td>21</td><td>True</td><td>577.8 μs</td><td>6.50 μs</td><td>6.08 μs</td>
|
||||
</tr></tbody></table>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user