Day 6 and standalone app (#7)

This commit is contained in:
Patrick Stevens
2022-12-06 08:25:16 +00:00
committed by GitHub
parent 0a498ac7d4
commit ef903b33a9
18 changed files with 288 additions and 99 deletions

View File

@@ -14,6 +14,7 @@
<Compile Include="Day3Efficient.fs" />
<Compile Include="Day4.fs" />
<Compile Include="Day5.fs" />
<Compile Include="Day6.fs" />
</ItemGroup>
</Project>

View File

@@ -1,34 +1,44 @@
namespace AdventOfCode2022
open System
open System.Collections.Generic
[<RequireQualifiedAccess>]
module Day1 =
let counts (lines : string seq) : int list =
((0, []), lines)
||> Seq.fold (fun (acc, counts) line ->
if String.IsNullOrWhiteSpace line then
0, (acc :: counts)
let counts (lines : byref<StringSplitEnumerator>) : int IReadOnlyList =
let counts = ResizeArray ()
let mutable acc = 0
for line in lines do
if line.IsWhiteSpace () then
counts.Add acc
acc <- 0
else
acc + int line, counts
)
|> snd
acc <- acc + Int32.Parse line
if acc <> 0 then
counts.Add acc
counts
/// Expects a trailing newline (as is present in the given input data).
let part1 (lines : string seq) : int = lines |> counts |> List.max
let part1 (lines : StringSplitEnumerator) : int =
let mutable lines = lines
counts &lines |> Seq.max
/// I wanted to save cloning the entire seq, so here is some bonus efficiency.
let maxThree (inputs : int list) : struct (int * int * int) =
let maxThree (inputs : int IReadOnlyList) : struct (int * int * int) =
((struct (Int32.MinValue, Int32.MinValue, Int32.MinValue)), inputs)
||> List.fold (fun (struct (max1, max2, max3) as maxes) input ->
||> Seq.fold (fun (struct (max1, max2, max3) as maxes) input ->
if input <= max3 then maxes
elif input <= max2 then struct (max1, max2, input)
elif input <= max1 then struct (max1, input, max2)
else struct (input, max1, max2)
)
let part2 (lines : string seq) : int =
let struct (a, b, c) = lines |> counts |> maxThree
let part2 (lines : StringSplitEnumerator) : int =
let mutable lines = lines
let struct (a, b, c) = counts &lines |> maxThree
a + b + c

View File

@@ -43,46 +43,54 @@ module RockPaperScissors =
[<RequireQualifiedAccess>]
module Day2 =
let part1 (lines : string seq) : int =
lines
|> Seq.filter (not << String.IsNullOrWhiteSpace)
|> Seq.map (fun s ->
let s = s.Trim ()
let part1 (lines : StringSplitEnumerator) : int =
let mutable sum = 0
if s.Length <> 3 || s.[1] <> ' ' then
failwithf $"Bad format of string: %s{s}"
for line in lines do
if not (line.IsWhiteSpace ()) then
let line = line.Trim ()
RockPaperScissors.parse s.[0], RockPaperScissors.parse s.[2]
)
|> Seq.map (fun (opponent, self) -> RockPaperScissors.outcome self opponent + RockPaperScissors.shapeScore self)
|> Seq.sum
if line.Length <> 3 || line.[1] <> ' ' then
failwithf $"Bad format of string: %s{line.ToString ()}"
let opponent = RockPaperScissors.parse line.[0]
let self = RockPaperScissors.parse line.[2]
let part2 (lines : string seq) : int =
lines
|> Seq.filter (not << String.IsNullOrWhiteSpace)
|> Seq.map (fun s ->
let s = s.Trim ()
sum <-
sum
+ RockPaperScissors.outcome self opponent
+ RockPaperScissors.shapeScore self
if s.Length <> 3 || s.[1] <> ' ' then
failwithf $"Bad format of string: %s{s}"
sum
let move = RockPaperScissors.parse s.[0]
let part2 (lines : StringSplitEnumerator) : int =
let mutable sum = 0
let myMove =
match Char.ToLower s.[2] with
| 'x' ->
// Need to lose
RockPaperScissors.wouldBeBeaten move
| 'y' ->
// Need to draw
move
| 'z' ->
// Need to win
RockPaperScissors.wouldBeat move
| c -> failwithf $"Unexpected strategy: %c{c}"
for line in lines do
if not (line.IsWhiteSpace ()) then
let line = line.Trim ()
move, myMove
)
|> Seq.map (fun (opponent, self) -> RockPaperScissors.outcome self opponent + RockPaperScissors.shapeScore self)
|> Seq.sum
if line.Length <> 3 || line.[1] <> ' ' then
failwithf $"Bad format of string: %s{line.ToString ()}"
let opponent = RockPaperScissors.parse line.[0]
let self =
match Char.ToLower line.[2] with
| 'x' ->
// Need to lose
RockPaperScissors.wouldBeBeaten opponent
| 'y' ->
// Need to draw
opponent
| 'z' ->
// Need to win
RockPaperScissors.wouldBeat opponent
| c -> failwithf $"Unexpected strategy: %c{c}"
sum <-
sum
+ RockPaperScissors.outcome self opponent
+ RockPaperScissors.shapeScore self
sum

View File

@@ -1,5 +1,7 @@
namespace AdventOfCode2022
open System
[<Measure>]
type Priority

View File

@@ -68,18 +68,20 @@ module Day3Efficient =
else
go set s (i + 1)
let part1 (lines : string seq) : int<Priority> =
lines
|> Seq.map (fun s ->
let s = s.AsSpan().Trim ()
let part1 (lines : StringSplitEnumerator) : int<Priority> =
let mutable sum = 0<Priority>
for s in lines do
let s = s.Trim ()
let set = CharSet.ofSpan (s.Slice (0, s.Length / 2))
go set (s.Slice (s.Length / 2)) 0
)
|> Seq.sum
sum <- sum + go set (s.Slice (s.Length / 2)) 0
sum
let part2 (lines : string seq) : int<Priority> =
lines
|> Seq.filter (not << String.IsNullOrEmpty)
|> Seq.chunkBySize 3
|> Seq.map (fun strArr ->
strArr

View File

@@ -22,15 +22,24 @@ module Day4 =
let secondElf2 = secondElf.Slice (secondDashIndex + 1)
(Int32.Parse firstElf1, Int32.Parse firstElf2), (Int32.Parse secondElf1, Int32.Parse secondElf2)
let part1 (lines : string seq) : int =
lines
|> Seq.map (fun s -> parse (s.AsSpan ()))
|> Seq.filter (fun (firstElf, secondElf) -> fullyContains firstElf secondElf || fullyContains secondElf firstElf
)
|> Seq.length
let part1 (lines : StringSplitEnumerator) : int =
let mutable count = 0
let part2 (lines : string seq) : int =
lines
|> Seq.map (fun s -> parse (s.AsSpan ()))
|> Seq.filter (fun (firstElf, secondElf) -> overlaps firstElf secondElf)
|> Seq.length
for line in lines do
let firstElf, secondElf = parse line
if fullyContains firstElf secondElf || fullyContains secondElf firstElf then
count <- count + 1
count
let part2 (lines : StringSplitEnumerator) : int =
let mutable count = 0
for line in lines do
let firstElf, secondElf = parse line
if overlaps firstElf secondElf then
count <- count + 1
count

31
AdventOfCode2022/Day6.fs Normal file
View File

@@ -0,0 +1,31 @@
namespace AdventOfCode2022
open System
[<RequireQualifiedAccess>]
module Day6 =
let findDuplicateSorted (a : 'a array) : int ValueOption =
let mutable i = 0
let mutable result = ValueNone
while result.IsNone && i + 1 < a.Length do
if a.[i] = a.[i + 1] then
result <- ValueSome i
i <- i + 1
result
let rec private go (count : int) (s : ReadOnlySpan<char>) (i : int) =
let fourChars = s.Slice (i - count + 1, count)
let arr = fourChars.ToArray ()
Array.sortInPlace arr
match findDuplicateSorted arr with
| ValueSome _ -> go count s (i + 1)
| ValueNone -> i + 1
let part1 (line : string) : int = go 4 (line.AsSpan ()) 3
let part2 (line : string) : int = go 14 (line.AsSpan ()) 13