mirror of
https://github.com/Smaug123/AdventOfCode2022
synced 2025-10-12 04:58:39 +00:00
Day 6 and standalone app (#7)
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
<Compile Include="Day3Efficient.fs" />
|
||||
<Compile Include="Day4.fs" />
|
||||
<Compile Include="Day5.fs" />
|
||||
<Compile Include="Day6.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -1,5 +1,7 @@
|
||||
namespace AdventOfCode2022
|
||||
|
||||
open System
|
||||
|
||||
[<Measure>]
|
||||
type Priority
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
31
AdventOfCode2022/Day6.fs
Normal 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
|
Reference in New Issue
Block a user