AoC 2023, Day 5, Fertilizer
I am currently quite a few days behind. I will try catching up bit by bit.
My first attempt at the Day 5 puzzle, called If You Give A Seed A Fertilizer did not go so well, so this is my second attempt.
Part 1
let sampleText =
"seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4"
I want to create a couple of types, a map entry type and a map type, this is to hold the input data.
Some of the numbers on the actual data are quite high, and there are no negatives, so I chose to use uint
values.
type MapEntry = MapEntry of destination: uint * source: uint * length: uint
type Map = Map of MapEntry list
I need a few functions to parse the text into data types.
let parseSeeds (text: string) =
text.Split(':').[1].Split(' ')
|> Array.filter (fun x -> x.Length > 0)
|> Array.map uint
let parseMapEntry (text: string) =
if (System.Char.IsDigit text[0]) then
let [|d;s;l|] = text.Split(' ') |> Array.map uint
Some (MapEntry (d, s, l))
else None
let parseAllMaps (texts: string[]) =
let rec maps allMaps currentMap i =
if i < texts.Length then
match parseMapEntry texts[i], currentMap with
| Some r, _ -> maps allMaps (currentMap@[r]) (i + 1)
| None, [] -> maps allMaps [] (i + 1)
| None, m -> maps (allMaps@[Map m]) [] (i + 1)
else match currentMap with
| [] -> allMaps
| _ -> allMaps@[Map currentMap]
maps [] [] 1
let parseAll (text: string) =
let lines =
text.Split('\n') |> Array.filter (fun x -> x.Length > 0)
let seeds = parseSeeds lines[0]
let maps = parseAllMaps lines
seeds, maps
I want a function that will be able to lookup the destination from a map.
let findDestination (Map entries) source =
entries
|> Seq.filter (fun (MapEntry (_, s, _)) -> s <= source)
|> Seq.filter (fun (MapEntry (_, s, l)) -> s + l >= source)
|> Seq.map (fun (MapEntry (d, s, _)) -> d + source - s)
|> Seq.tryHead
|> Option.defaultValue source
And another that will step through each map.
let rec findFinalDestination maps source =
match maps with
| [] -> source
| [ map ] -> findDestination map source
| map :: rest -> findFinalDestination rest (findDestination map source)
Putting this all together
let result =
let (seeds, maps) =
sampleText
|> parseAll
seeds
|> Array.map (findFinalDestination maps)
|> Array.min
35u
Because 35
is the answer I am expecting, and my answer with the full puzzle text is also correct, I finally get another star.
Read other posts