diff options
Diffstat (limited to 'aoc-2022-dotnet')
-rw-r--r-- | aoc-2022-dotnet/Common/Common.fsproj | 4 | ||||
-rw-r--r-- | aoc-2022-dotnet/Common/Library.fs | 8 | ||||
-rw-r--r-- | aoc-2022-dotnet/Common/Util.fs | 43 | ||||
-rw-r--r-- | aoc-2022-dotnet/Common/Vec2.fs | 13 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day01/Day01.fsproj | 4 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day01/Program.fs | 20 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day02/Day02.fsproj | 4 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day02/Program.fs | 8 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day03/Day03.fsproj | 4 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day03/Program.fs | 7 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day04/Program.fs | 7 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day05/Program.fs | 5 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day06/Day06.fsproj | 4 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day06/Program.fs | 3 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day07/Program.fs | 15 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day08/Day08.fsproj | 4 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day08/Program.fs | 9 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day09/Day09.fsproj | 4 | ||||
-rw-r--r-- | aoc-2022-dotnet/Day09/Program.fs | 28 |
19 files changed, 119 insertions, 75 deletions
diff --git a/aoc-2022-dotnet/Common/Common.fsproj b/aoc-2022-dotnet/Common/Common.fsproj index c8a185a..32057cf 100644 --- a/aoc-2022-dotnet/Common/Common.fsproj +++ b/aoc-2022-dotnet/Common/Common.fsproj @@ -6,11 +6,13 @@ </PropertyGroup> <ItemGroup> - <Compile Include="Library.fs" /> + <Compile Include="Vec2.fs" /> + <Compile Include="Util.fs" /> </ItemGroup> <ItemGroup> <PackageReference Include="FParsec" Version="1.1.1" /> + <PackageReference Include="FSharpPlus" Version="1.3.2" /> </ItemGroup> </Project> diff --git a/aoc-2022-dotnet/Common/Library.fs b/aoc-2022-dotnet/Common/Library.fs deleted file mode 100644 index 7354509..0000000 --- a/aoc-2022-dotnet/Common/Library.fs +++ /dev/null @@ -1,8 +0,0 @@ -module Common - -open FParsec - -let parse parser input = - match run parser input with - | Success (result, _, _) -> result - | _ -> failwith "Invalid input format!" diff --git a/aoc-2022-dotnet/Common/Util.fs b/aoc-2022-dotnet/Common/Util.fs new file mode 100644 index 0000000..a9f3a1e --- /dev/null +++ b/aoc-2022-dotnet/Common/Util.fs @@ -0,0 +1,43 @@ +namespace Common + +module Util = + open System.Globalization + open FParsec + open FSharpPlus + + let parse parser input = + match run parser input with + | Success (result, _, _) -> result + | _ -> failwith "Invalid input format!" + + let countDistinct seq = seq |> Set |> Set.count + + let countWhere pred = Seq.filter pred >> Seq.length + + let charToInt = CharUnicodeInfo.GetDigitValue + + let cutInHalf xs = + let half = Seq.length xs / 2 + [ Seq.take half xs; Seq.skip half xs ] + + let splitStringToTuple sep str = + match Seq.toList <| String.split [ sep ] str with + | [ x; y ] -> x, y + | _ -> failwith "Invalid string format!" + + let topN n xs = + let rec insertSorted x = + function + | h :: t -> min h x :: (insertSorted (max h x) t) + | _ -> [ x ] + + Seq.fold + (fun acc x -> + if List.length acc < n then + insertSorted x acc + elif List.head acc < x then + insertSorted x <| List.tail acc + else + acc) + List.empty + xs diff --git a/aoc-2022-dotnet/Common/Vec2.fs b/aoc-2022-dotnet/Common/Vec2.fs new file mode 100644 index 0000000..20b9956 --- /dev/null +++ b/aoc-2022-dotnet/Common/Vec2.fs @@ -0,0 +1,13 @@ +namespace Common + +type Vec2 = + | Vec2 of int * int + + static member zero = Vec2(0, 0) + + static member (+)(Vec2 (x1, y1), Vec2 (x2, y2)) = Vec2(x1 + x2, y1 + y2) + static member (-)(Vec2 (x1, y1), Vec2 (x2, y2)) = Vec2(x1 - x2, y1 - y2) + + static member apply f (Vec2 (x, y)) = Vec2(f x, f y) + static member sign = Vec2.apply sign + static member chebyshevDist (Vec2 (x1, y1)) (Vec2 (x2, y2)) = max (abs <| x2 - x1) (abs <| y2 - y1) diff --git a/aoc-2022-dotnet/Day01/Day01.fsproj b/aoc-2022-dotnet/Day01/Day01.fsproj index 0e98abc..795d59c 100644 --- a/aoc-2022-dotnet/Day01/Day01.fsproj +++ b/aoc-2022-dotnet/Day01/Day01.fsproj @@ -19,4 +19,8 @@ <PackageReference Include="FSharpPlus" Version="1.3.2" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Common\Common.fsproj" /> + </ItemGroup> + </Project> diff --git a/aoc-2022-dotnet/Day01/Program.fs b/aoc-2022-dotnet/Day01/Program.fs index 71faaae..3a06ef1 100644 --- a/aoc-2022-dotnet/Day01/Program.fs +++ b/aoc-2022-dotnet/Day01/Program.fs @@ -2,6 +2,7 @@ open System.IO open FSharpPlus +open Common let parseLine = function @@ -10,27 +11,10 @@ let parseLine = let caloriesPerElf = Seq.split [ [ -1 ] ] >> Seq.map Seq.sum -let topN n xs = - let rec insertSorted x = - function - | h :: t -> min h x :: (insertSorted (max h x) t) - | _ -> [ x ] - - Seq.fold - (fun acc x -> - if List.length acc < n then - insertSorted x acc - elif List.head acc < x then - insertSorted x <| List.tail acc - else - acc) - List.empty - xs - let solution n = Seq.map parseLine >> caloriesPerElf - >> topN n + >> Util.topN n >> List.sum let test = File.ReadLines "test.txt" diff --git a/aoc-2022-dotnet/Day02/Day02.fsproj b/aoc-2022-dotnet/Day02/Day02.fsproj index 0e98abc..795d59c 100644 --- a/aoc-2022-dotnet/Day02/Day02.fsproj +++ b/aoc-2022-dotnet/Day02/Day02.fsproj @@ -19,4 +19,8 @@ <PackageReference Include="FSharpPlus" Version="1.3.2" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Common\Common.fsproj" /> + </ItemGroup> + </Project> diff --git a/aoc-2022-dotnet/Day02/Program.fs b/aoc-2022-dotnet/Day02/Program.fs index 0546195..8568f9a 100644 --- a/aoc-2022-dotnet/Day02/Program.fs +++ b/aoc-2022-dotnet/Day02/Program.fs @@ -2,6 +2,7 @@ open System.IO open FSharpPlus +open Common type Move = | Rock @@ -36,11 +37,6 @@ type Strategy = | "Z" -> Z | s -> failwithf "Invalid strategy: %s" s -let splitToTuple sep str = - match Seq.toList <| String.split [ sep ] str with - | [ x; y ] -> x, y - | _ -> failwith "Invalid string format!" - let scoreRound (enemy, player) = let selectionScore = match player with @@ -70,7 +66,7 @@ let guide2 (enemy: Move) = let parseRound guide roundStr = let (enemy, strategy) = roundStr - |> splitToTuple " " + |> Util.splitStringToTuple " " |> mapItem1 Move.parse |> mapItem2 Strategy.parse diff --git a/aoc-2022-dotnet/Day03/Day03.fsproj b/aoc-2022-dotnet/Day03/Day03.fsproj index e337a41..b9a3919 100644 --- a/aoc-2022-dotnet/Day03/Day03.fsproj +++ b/aoc-2022-dotnet/Day03/Day03.fsproj @@ -15,4 +15,8 @@ <Compile Include="Program.fs" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Common\Common.fsproj" /> + </ItemGroup> + </Project> diff --git a/aoc-2022-dotnet/Day03/Program.fs b/aoc-2022-dotnet/Day03/Program.fs index 153e639..512ef40 100644 --- a/aoc-2022-dotnet/Day03/Program.fs +++ b/aoc-2022-dotnet/Day03/Program.fs @@ -1,6 +1,7 @@ module Day03 open System.IO +open Common let priority item = if 'a' <= item && item <= 'z' then @@ -10,13 +11,9 @@ let priority item = else failwithf "Invalid item: %c" item -let cutInHalf xs = - let half = Seq.length xs / 2 - [ Seq.take half xs; Seq.skip half xs ] - let solution1 = Seq.sumBy ( - cutInHalf + Util.cutInHalf >> Seq.map Set >> Set.intersectMany >> Seq.exactlyOne diff --git a/aoc-2022-dotnet/Day04/Program.fs b/aoc-2022-dotnet/Day04/Program.fs index 2221a4a..7d37d3e 100644 --- a/aoc-2022-dotnet/Day04/Program.fs +++ b/aoc-2022-dotnet/Day04/Program.fs @@ -2,19 +2,20 @@ open System.IO open FParsec +open Common let parseLine line = let prange = pint32 .>> pstring "-" .>>. pint32 let ppair = prange .>> pstring "," .>>. prange .>> eof - Common.parse ppair line + Util.parse ppair line let fullyOverlap ((a, b), (c, d)) = (a <= c && d <= b) || (c <= a && b <= d) let overlapAtAll ((a, b), (c, d)) = a <= d && b >= c -let solution pred = - Seq.map parseLine >> Seq.filter pred >> Seq.length +let solution predicate = + Seq.map parseLine >> Util.countWhere predicate let test = File.ReadLines "test.txt" assert (solution fullyOverlap test = 2) diff --git a/aoc-2022-dotnet/Day05/Program.fs b/aoc-2022-dotnet/Day05/Program.fs index f471a31..7bad269 100644 --- a/aoc-2022-dotnet/Day05/Program.fs +++ b/aoc-2022-dotnet/Day05/Program.fs @@ -3,6 +3,7 @@ open System open System.IO open FParsec +open Common type Move = | Move of int * int * int @@ -11,7 +12,7 @@ type Move = let dec n = n - 1 let pPart str = pstring str >>. pint32 let pMove = tuple3 (pPart "move ") (pPart " from " |>> dec) (pPart " to " |>> dec) - Common.parse pMove str |> Move + Util.parse pMove str |> Move static member execute order stacks (Move (n, fi, ti)) = List.mapi @@ -33,7 +34,7 @@ let parseStacks str = let pHeader = many pCrateLine str - |> Common.parse pHeader + |> Util.parse pHeader |> List.transpose |> List.map (List.choose id) diff --git a/aoc-2022-dotnet/Day06/Day06.fsproj b/aoc-2022-dotnet/Day06/Day06.fsproj index 249287d..e7e4a65 100644 --- a/aoc-2022-dotnet/Day06/Day06.fsproj +++ b/aoc-2022-dotnet/Day06/Day06.fsproj @@ -12,4 +12,8 @@ <Compile Include="Program.fs" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Common\Common.fsproj" /> + </ItemGroup> + </Project> diff --git a/aoc-2022-dotnet/Day06/Program.fs b/aoc-2022-dotnet/Day06/Program.fs index c9f6568..78902cd 100644 --- a/aoc-2022-dotnet/Day06/Program.fs +++ b/aoc-2022-dotnet/Day06/Program.fs @@ -1,10 +1,11 @@ module Day06 open System.IO +open Common let solution n = Seq.windowed n - >> Seq.findIndex (Set >> Set.count >> (=) n) + >> Seq.findIndex (Util.countDistinct >> (=) n) >> (+) n assert diff --git a/aoc-2022-dotnet/Day07/Program.fs b/aoc-2022-dotnet/Day07/Program.fs index 7e16cb6..e48bb53 100644 --- a/aoc-2022-dotnet/Day07/Program.fs +++ b/aoc-2022-dotnet/Day07/Program.fs @@ -2,6 +2,7 @@ open System.IO open FParsec +open Common let fileSizeThreshold = 100_000 let totalDiskSpace = 70_000_000 @@ -28,7 +29,7 @@ let parseCommands input = let pcmd = pcd <|> pls let pinput = many pcmd - Common.parse pinput input + Util.parse pinput input let combine = function @@ -46,11 +47,11 @@ let buildFilesystem commands = commands |> helper [] |> Map.ofList -let rec directorySize fileSystem path = - fileSystem +let rec dirSize filesystem path = + filesystem |> Map.find path |> List.sumBy (function - | Dir dir -> directorySize fileSystem <| combine (path, dir) + | Dir dir -> dirSize filesystem <| combine (path, dir) | File size -> size) let part1 = Seq.filter ((>=) fileSizeThreshold) >> Seq.sum @@ -62,11 +63,11 @@ let part2 sizes = sizes |> Seq.filter ((<=) missingSpace) |> Seq.min let solution reduceSizes input = - let fileSystem = input |> parseCommands |> buildFilesystem + let filesystem = input |> parseCommands |> buildFilesystem - fileSystem + filesystem |> Map.keys - |> Seq.map (directorySize fileSystem) + |> Seq.map (dirSize filesystem) |> reduceSizes let test = File.ReadAllText("test.txt") diff --git a/aoc-2022-dotnet/Day08/Day08.fsproj b/aoc-2022-dotnet/Day08/Day08.fsproj index e337a41..b9a3919 100644 --- a/aoc-2022-dotnet/Day08/Day08.fsproj +++ b/aoc-2022-dotnet/Day08/Day08.fsproj @@ -15,4 +15,8 @@ <Compile Include="Program.fs" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Common\Common.fsproj" /> + </ItemGroup> + </Project> diff --git a/aoc-2022-dotnet/Day08/Program.fs b/aoc-2022-dotnet/Day08/Program.fs index 1a98c6d..23f93c0 100644 --- a/aoc-2022-dotnet/Day08/Program.fs +++ b/aoc-2022-dotnet/Day08/Program.fs @@ -1,11 +1,9 @@ module Day08 open System.IO -open System.Globalization +open Common -let parseMatrix = - array2D - >> Array2D.map CharUnicodeInfo.GetDigitValue +let parseMatrix = array2D >> Array2D.map Util.charToInt let mapEachToSeq mapping m = seq { @@ -35,8 +33,7 @@ let scenicScore (m: 'a [,]) r c = let solution1 = parseMatrix >> mapEachToSeq isVisible - >> Seq.filter id - >> Seq.length + >> Util.countWhere id let solution2 = parseMatrix >> mapEachToSeq scenicScore >> Seq.max diff --git a/aoc-2022-dotnet/Day09/Day09.fsproj b/aoc-2022-dotnet/Day09/Day09.fsproj index e337a41..b9a3919 100644 --- a/aoc-2022-dotnet/Day09/Day09.fsproj +++ b/aoc-2022-dotnet/Day09/Day09.fsproj @@ -15,4 +15,8 @@ <Compile Include="Program.fs" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Common\Common.fsproj" /> + </ItemGroup> + </Project> diff --git a/aoc-2022-dotnet/Day09/Program.fs b/aoc-2022-dotnet/Day09/Program.fs index 5f49c63..df9f040 100644 --- a/aoc-2022-dotnet/Day09/Program.fs +++ b/aoc-2022-dotnet/Day09/Program.fs @@ -1,16 +1,10 @@ module Day09 open System.IO - -type Vec2D = - | Vec2D of int * int - static member zero = Vec2D(0, 0) - static member (+)(Vec2D (x1, y1), Vec2D (x2, y2)) = Vec2D(x1 + x2, y1 + y2) - static member (-)(Vec2D (x1, y1), Vec2D (x2, y2)) = Vec2D(x1 - x2, y1 - y2) - static member chebyshevDist (Vec2D (x1, y1)) (Vec2D (x2, y2)) = max (abs <| x2 - x1) (abs <| y2 - y1) +open Common let directionToVec = - Vec2D + Vec2 << function | 'U' -> (0, 1) | 'R' -> (1, 0) @@ -19,28 +13,26 @@ let directionToVec = | char -> failwithf "Invalid direction: %c" char let parseHeadMoves = - Seq.collect (fun (line: string) -> List.replicate (int line[2..]) (directionToVec line[0])) + Seq.collect (fun (line: string) -> Seq.replicate (int line[2..]) (directionToVec line[0])) -let constrainTail head tail = - if Vec2D.chebyshevDist head tail <= 1 then +let moveTail head tail = + if Vec2.chebyshevDist head tail <= 1 then tail else - let (Vec2D (dx, dy)) = head - tail - tail + Vec2D(sign dx, sign dy) + tail + Vec2.sign (head - tail) -let createRope length = List.replicate length Vec2D.zero +let createRope length = List.replicate length Vec2.zero let solution ropeLength = parseHeadMoves >> Seq.scan - (fun rope move -> + (fun rope headMove -> match rope with - | h :: t -> List.scan constrainTail (h + move) t + | head :: tail -> List.scan moveTail (head + headMove) tail | [] -> []) (createRope ropeLength) >> Seq.map Seq.last - >> Set - >> Set.count + >> Util.countDistinct let test = File.ReadLines("test.txt") assert (solution 2 test = 13) |