Skip to content

Commit

Permalink
2023 - F# - Day 06 - Part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
NicoVIII committed Jul 30, 2024
1 parent df8092f commit 9a78d23
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 48 deletions.
2 changes: 1 addition & 1 deletion 2023/outputs/06/output-example.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
288
-
71503
2 changes: 1 addition & 1 deletion 2023/outputs/06/output-puzzle.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
1084752
-
28228952
33 changes: 24 additions & 9 deletions 2023/solutions/fsharp/06/src/Functions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,38 @@ module String =

[<AutoOpen>]
module Functions =
let parseLine line =
let parseLineV1 line : Base array =
// Remove title
(String.split ":" line)[1]
|> String.trim
|> String.split " "
|> Array.choose (fun x -> if x <> "" then uint16 x |> Some else None)
|> Array.choose (fun x -> if x <> "" then Base.convertTo x |> Some else None)

let parseInput input =
let parseInputV1 input =
let lines = String.split "\n" input
let times = parseLine lines[0]
let distances = parseLine lines[1]
let times = parseLineV1 lines[0]
let distances = parseLineV1 lines[1]

Array.zip times distances
|> Array.map (fun (time, distance) -> { time = time; distance = distance })
|> List.ofArray

let beatRecordCount record =
let parseLineV2 line : Base =
// Remove title
(String.split ":" line)[1]
|> String.trim
|> String.filter (fun c -> c <> ' ')
|> Base.convertTo

let parseInputV2 input =
let lines = String.split "\n" input

{
time = parseLineV2 lines[0]
distance = parseLineV2 lines[1]
}

let beatRecordCount record : Base =
// We can express the problem like this
// distance < (x-y)(x+y) with y < x and x = time / 2
// count how many ys element of integers are there which solve that
Expand All @@ -45,14 +60,14 @@ module Functions =
// y - 0.5 < sqrt (x² - distance)
// y < sqrt (x² - distance) + 0.5
// biggest y = round-down (sqrt (x² - distance) + 0.5 - 0.0001)
let timeIsOdd = record.time % 2us <> 0us
let timeIsOdd = record.time % 2UL <> 0UL

let biggestY =
pown (float record.time / 2.) 2 - float record.distance
|> sqrt
|> if timeIsOdd then (+) 0.5 else id
|> (+) -0.0001
|> floor
|> uint16
|> Base.convertTo

if timeIsOdd then biggestY * 2us else biggestY * 2us + 1us
if timeIsOdd then biggestY * 2UL else biggestY * 2UL + 1UL
8 changes: 6 additions & 2 deletions 2023/solutions/fsharp/06/src/Program.fs
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
namespace Day06

open Microsoft.FSharp.Core.Operators.Checked

[<AutoOpen>]
module Expose =
open System.IO

let readInput = File.ReadAllText >> parseInput
let part1 = List.map beatRecordCount >> List.map uint >> List.reduce (*)
let readInput = File.ReadAllText
let part1 = parseInputV1 >> List.map beatRecordCount >> List.reduce (*)
let part2 = parseInputV2 >> beatRecordCount

module Program =
[<EntryPoint>]
let main args =
let input = readInput args[0]

part1 input |> printfn "Part 1: %i"
part2 input |> printfn "Part 2: %i"
0
6 changes: 5 additions & 1 deletion 2023/solutions/fsharp/06/src/Types.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
namespace Day06

type Base = uint16
type Base = uint64
type Record = { time: Base; distance: Base }

[<RequireQualifiedAccess>]
module Base =
let inline convertTo x = uint64 x
38 changes: 19 additions & 19 deletions 2023/solutions/fsharp/06/test/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ open Tests

type RecordGen() =
static member Record() : Arbitrary<Record> =
Arb.from<uint16 * uint16>
Arb.from<Base * Base>
|> Arb.convert (fun (time, distance) -> { time = time; distance = distance }) (fun record ->
record.time, record.distance)
|> Arb.filter (fun record ->
record.time > 0us && pown (float record.time / 2.) 2 > float record.distance)
record.time > 0UL && pown (float record.time / 2.) 2 > float record.distance)

[<AutoOpen>]
module Auto =
Expand All @@ -22,46 +22,46 @@ module Auto =

let testProperty = testPropertyWithConfig config

let alternativeImplementation record =
[ 0us .. record.time ]
let alternativeImplementation record : Base =
[ 0UL .. record.time ]
|> List.filter (fun loadingTime -> (record.time - loadingTime) * loadingTime > record.distance)
|> List.length
|> uint16
|> Base.convertTo

[<Tests>]
let unitTests =
testList (nameof Functions) [
testList (nameof parseInput) [
testList (nameof parseInputV1) [
let paramList = [
[ "Time: 7 15 30"; "Distance: 9 40 200" ],
[
{ time = 7us; distance = 9us }
{ time = 15us; distance = 40us }
{ time = 30us; distance = 200us }
{ time = 7UL; distance = 9UL }
{ time = 15UL; distance = 40UL }
{ time = 30UL; distance = 200UL }
]
[
"Time: 40 70 98 79"
"Distance: 215 1051 2147 1005"
],
[
{ time = 40us; distance = 215us }
{ time = 70us; distance = 1051us }
{ time = 98us; distance = 2147us }
{ time = 79us; distance = 1005us }
{ time = 40UL; distance = 215UL }
{ time = 70UL; distance = 1051UL }
{ time = 98UL; distance = 2147UL }
{ time = 79UL; distance = 1005UL }
]
]

for (input, expected) in paramList do
test $"{expected}" {
Expect.equal (String.concat "\n" input |> parseInput) expected ""
Expect.equal (String.concat "\n" input |> parseInputV1) expected ""
}
]
testList (nameof beatRecordCount) [
let paramList = [
{ time = 7us; distance = 9us }, 4us
{ time = 30us; distance = 200us }, 9us
{ time = 40us; distance = 215us }, 27us
{ time = 79us; distance = 1005us }, 48us
{ time = 7UL; distance = 9UL }, 4UL
{ time = 30UL; distance = 200UL }, 9UL
{ time = 40UL; distance = 215UL }, 27UL
{ time = 79UL; distance = 1005UL }, 48UL
]

for (record, expected) in paramList do
Expand All @@ -84,7 +84,7 @@ let integrationTests =
{
day = 6
part1 = part1 >> string
part2 = fun _ -> failwith "Not implemented"
part2 = part2 >> string
readInput = readInput
}
|> Tests.build
Expand Down
35 changes: 20 additions & 15 deletions 2023/solutions/fsharp/testBase/Library.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Tests =
|> Seq.filter (fun filePath ->
let fileName = Path.GetFileName filePath
fileName.StartsWith "input-" && fileName.EndsWith ".txt")
|> Seq.choose (fun filePath ->
|> Seq.collect (fun filePath ->
// Fetch input identifier
let fileName = Path.GetFileName filePath
let pattern = @"input-(.*).txt"
Expand All @@ -37,24 +37,29 @@ module Tests =
failwith
$"Expected output file {outputFilePath} to contain exactly two lines"

test $"Input: {fileName}" {
let input = config.readInput filePath

[
if part1Output <> "-" then
Expect.equal
(config.part1 input |> string)
part1Output
"Part 1 result wrong"
test $"Input: {fileName} - Part 1" {
let input = config.readInput filePath

Expect.equal
(config.part1 input |> string)
part1Output
"Part 1 result wrong"
}

if part2Output <> "-" then
Expect.equal
(config.part2 input |> string)
part2Output
"Part 2 result wrong"
}
|> Some
test $"Input: {fileName} - Part 2" {
let input = config.readInput filePath

Expect.equal
(config.part2 input |> string)
part2Output
"Part 2 result wrong"
}
]
else
printfn "Warning: No matching output file for %s" fileName
None)
[])
|> Seq.toList
|> testList $"Day {config.day}"

0 comments on commit 9a78d23

Please sign in to comment.