-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day12.fs
61 lines (52 loc) · 2 KB
/
Day12.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
module Day12
open System
type Known = Map<string * int list, int64>
let parseLines lines =
let parseLine (line: string) =
let [|springTxt; recordTxt|] = line.Split(' ')
(springTxt.ToCharArray() |> List.ofArray,
recordTxt.Split(',') |> Array.map int |> List.ofArray)
lines |> List.map parseLine
let rec fits springs entry =
match entry, springs with
| 0, [] -> Some []
| 0, ('.' :: rest)
| 0, ('?' :: rest) -> Some rest
| _, ('?'::sprs)
| _, ('#'::sprs) -> fits sprs (entry - 1)
| _ -> None
let rec arrangements springs record known : (int64 * Known) =
let key = (springs |> Array.ofList |> String, record)
match Map.tryFind key known with
| Some n -> (n, known)
| None ->
let (rslt: int64, known) =
match springs, record with
| _, [] when springs |> List.forall (fun c -> c = '.' || c = '?') ->
(1L, known)
| [], _ | _, [] -> (0L, known)
| (spring::rstSprings), (entry::rstRecords) ->
let (useCount, known) =
match fits springs entry with
| Some sprs -> arrangements sprs rstRecords known
| None -> (0, known)
let (skipCount, known) =
match spring with
| '#' -> (0L, known)
| _ -> arrangements rstSprings record known
(useCount + skipCount, known)
(rslt, Map.add key rslt known)
let countArrangements (springs, record) : int64 =
arrangements springs record (Map.empty: Known)
|> fst
let unfold (springs, record) =
let springs5 =
'?'::springs |> List.replicate 5 |> List.collect id |> List.tail
let record5 = record |> List.replicate 5 |> List.collect id
(springs5, record5)
let part1 getLines =
"input" |> getLines |> parseLines
|> List.sumBy countArrangements
let part2 getLines =
"input" |> getLines |> parseLines
|> List.sumBy (unfold >> countArrangements)