Lower level
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
namespace AdventOfCode2023
|
||||
|
||||
open System
|
||||
open System.Collections.Generic
|
||||
|
||||
[<Struct>]
|
||||
type Range =
|
||||
@@ -14,12 +13,6 @@ type Range =
|
||||
[<RequireQualifiedAccess>]
|
||||
module Day5 =
|
||||
|
||||
let remap (range : Range) (i : uint32) =
|
||||
if range.SourceStart <= i && i - range.SourceStart < range.Len then
|
||||
i + (range.DestStart - range.SourceStart) |> ValueSome
|
||||
else
|
||||
ValueNone
|
||||
|
||||
let parse (s : string) =
|
||||
use mutable lines = StringSplitEnumerator.make '\n' s
|
||||
lines.MoveNext () |> ignore
|
||||
@@ -75,11 +68,12 @@ module Day5 =
|
||||
|
||||
for interval in map do
|
||||
if not hasRemappedThisLayer then
|
||||
match remap interval remapped with
|
||||
| ValueNone -> ()
|
||||
| ValueSome n ->
|
||||
if
|
||||
interval.SourceStart <= remapped
|
||||
&& remapped - interval.SourceStart < interval.Len
|
||||
then
|
||||
hasRemappedThisLayer <- true
|
||||
remapped <- n
|
||||
remapped <- remapped + (interval.DestStart - interval.SourceStart)
|
||||
|
||||
if remapped < best then
|
||||
best <- remapped
|
||||
@@ -89,22 +83,22 @@ module Day5 =
|
||||
// The input ranges are inclusive at both ends.
|
||||
// Returns any range we didn't map.
|
||||
let private split
|
||||
(result : ResizeArray<uint32 * uint32>)
|
||||
(start, finish)
|
||||
(resultStarts : ResizeArray<uint32>)
|
||||
(resultEnds : ResizeArray<uint32>)
|
||||
start
|
||||
finish
|
||||
(rangeFromLayer : Range)
|
||||
: (uint32 * uint32 * (uint32 * uint32) voption) voption
|
||||
=
|
||||
let low, high =
|
||||
rangeFromLayer.SourceStart, rangeFromLayer.SourceStart + rangeFromLayer.Len - 1ul
|
||||
let low = rangeFromLayer.SourceStart
|
||||
let high = rangeFromLayer.SourceStart + rangeFromLayer.Len - 1ul
|
||||
|
||||
if low <= start then
|
||||
if finish <= high then
|
||||
// low ... start .. finish .. high
|
||||
// so the entire input range gets mapped down
|
||||
result.Add (
|
||||
start + rangeFromLayer.DestStart - rangeFromLayer.SourceStart,
|
||||
finish + rangeFromLayer.DestStart - rangeFromLayer.SourceStart
|
||||
)
|
||||
resultStarts.Add (start + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
resultEnds.Add (finish + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
|
||||
ValueNone
|
||||
elif start <= high then
|
||||
@@ -112,10 +106,8 @@ module Day5 =
|
||||
// so start .. high gets mapped down
|
||||
// and high + 1 .. finish stays where it is.
|
||||
// high < finish is already guaranteed by previous if block.
|
||||
result.Add (
|
||||
start + rangeFromLayer.DestStart - rangeFromLayer.SourceStart,
|
||||
high + rangeFromLayer.DestStart - rangeFromLayer.SourceStart
|
||||
)
|
||||
resultStarts.Add (start + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
resultEnds.Add (high + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
|
||||
ValueSome (high + 1ul, finish, ValueNone)
|
||||
else
|
||||
@@ -125,20 +117,16 @@ module Day5 =
|
||||
// so start .. low - 1 stays where it is
|
||||
// low .. high gets mapped down
|
||||
// and high + 1 .. finish stays where it is
|
||||
result.Add (
|
||||
low + rangeFromLayer.DestStart - rangeFromLayer.SourceStart,
|
||||
high + rangeFromLayer.DestStart - rangeFromLayer.SourceStart
|
||||
)
|
||||
resultStarts.Add (low + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
resultEnds.Add (high + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
|
||||
ValueSome (start, low - 1ul, ValueSome (high + 1ul, finish))
|
||||
elif low < finish then
|
||||
// start .. low .. finish .. high
|
||||
// so start .. low - 1 stays where it is
|
||||
// and low .. finish gets mapped down
|
||||
result.Add (
|
||||
low + rangeFromLayer.DestStart - rangeFromLayer.SourceStart,
|
||||
finish + rangeFromLayer.DestStart - rangeFromLayer.SourceStart
|
||||
)
|
||||
resultStarts.Add (low + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
resultEnds.Add (finish + rangeFromLayer.DestStart - rangeFromLayer.SourceStart)
|
||||
|
||||
ValueSome (start, low - 1ul, ValueNone)
|
||||
else
|
||||
@@ -147,18 +135,20 @@ module Day5 =
|
||||
let part2 (s : string) : uint32 =
|
||||
let seeds, mappings = parse s
|
||||
|
||||
let mutable intervals = ResizeArray ()
|
||||
let mutable intervalStarts = ResizeArray ()
|
||||
let mutable intervalEnds = ResizeArray ()
|
||||
|
||||
for i = 0 to (seeds.Length - 1) / 2 do
|
||||
let t = seeds.[2 * i], seeds.[2 * i + 1] + seeds.[2 * i] - 1ul
|
||||
intervals.Add t
|
||||
intervalStarts.Add seeds.[2 * i]
|
||||
intervalEnds.Add (seeds.[2 * i + 1] + seeds.[2 * i] - 1ul)
|
||||
|
||||
let mutable nextIntervals = ResizeArray ()
|
||||
let mutable nextIntervalStarts = ResizeArray ()
|
||||
let mutable nextIntervalEnds = ResizeArray ()
|
||||
|
||||
for mapLayer in mappings do
|
||||
let mutable i = 0
|
||||
|
||||
while i < intervals.Count do
|
||||
while i < intervalStarts.Count do
|
||||
// split interval according to every map
|
||||
let mutable allMoved = false
|
||||
let mutable currentRange = 0
|
||||
@@ -166,30 +156,36 @@ module Day5 =
|
||||
while not allMoved && currentRange < mapLayer.Count do
|
||||
let range = mapLayer.[currentRange]
|
||||
// range is e.g. 50 98 2, i.e. "98-99 goes to 50-51"
|
||||
match split nextIntervals intervals.[i] range with
|
||||
match split nextIntervalStarts nextIntervalEnds intervalStarts.[i] intervalEnds.[i] range with
|
||||
| ValueNone -> allMoved <- true
|
||||
| ValueSome (start, finish, v) ->
|
||||
intervals.[i] <- (start, finish)
|
||||
intervalStarts.[i] <- start
|
||||
intervalEnds.[i] <- finish
|
||||
|
||||
match v with
|
||||
| ValueNone -> ()
|
||||
| ValueSome (start, finish) -> intervals.Add (start, finish)
|
||||
| ValueSome (start, finish) ->
|
||||
intervalStarts.Add start
|
||||
intervalEnds.Add finish
|
||||
|
||||
currentRange <- currentRange + 1
|
||||
|
||||
if not allMoved then
|
||||
nextIntervals.Add intervals.[i]
|
||||
nextIntervalStarts.Add intervalStarts.[i]
|
||||
nextIntervalEnds.Add intervalEnds.[i]
|
||||
|
||||
i <- i + 1
|
||||
|
||||
let oldIntervals = intervals
|
||||
let oldIntervals = intervalStarts
|
||||
oldIntervals.Clear ()
|
||||
intervals <- nextIntervals
|
||||
nextIntervals <- oldIntervals
|
||||
intervalStarts <- nextIntervalStarts
|
||||
nextIntervalStarts <- oldIntervals
|
||||
|
||||
let mutable best = UInt32.MaxValue
|
||||
let oldIntervals = intervalEnds
|
||||
oldIntervals.Clear ()
|
||||
intervalEnds <- nextIntervalEnds
|
||||
nextIntervalEnds <- oldIntervals
|
||||
|
||||
for i, _ in intervals do
|
||||
best <- min best i
|
||||
|
||||
best
|
||||
// SIMD go brrr
|
||||
System.Linq.Enumerable.Min intervalStarts
|
||||
|
Reference in New Issue
Block a user