This repository has been archived by the owner on Nov 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpuzzle07.fs
75 lines (64 loc) · 2.44 KB
/
puzzle07.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//
// https://adventofcode.com/2020/day/7
//
#if !INTERACTIVE
module Puzzle7
#else
#load "common.fs"
#r "nuget:FParsec, Version=1.1.1"
#endif
open System.IO
open System.Text.RegularExpressions
open FParsec
open common
let input =
Path.Combine(__SOURCE_DIRECTORY__, "puzzle07.txt")
|> readLines
|> Array.ofSeq
let parseLine line =
let swap (x, y) = y, x
let p =
manyCharsTill anyChar (pstring " bags contain ")
.>>.
(
pstring "no other bags" >>. preturn []
<|>
sepBy (pint32 .>> spaces .>>. manyCharsTill anyChar (pstring " bags" <|> pstring " bag") |>> swap) (pstring ", ")
)
match run p line with
| Success(result, _, _) -> result
| _ -> failwith "not parsed"
let containingMap =
input
|> Seq.map parseLine
|> Seq.map (fun (contained, containing) -> contained, Map.ofList containing)
|> Map.ofSeq
let containedMap =
let folder map (key,value) =
let mapValue x = match x with | Some xx -> Some (Set.add value xx) | None -> Some (Set.singleton value)
Map.change key mapValue map
input
|> Seq.map parseLine
|> Seq.collect (fun (containing, contained) -> contained |> List.map (fun (color, _) -> color, containing))
|> Seq.fold folder Map.empty
let rec findContaining colorContained =
containedMap
|> Map.tryFind colorContained
|> Option.map (fun containing -> Seq.collect findContaining containing
|> Set.ofSeq
|> Set.union containing)
|> Option.defaultValue Set.empty
let rec findContained colorContaining =
let folder accMap map =
let addOrAdd key value map =
Map.change key (fun maybeFound -> maybeFound |> Option.map ((+) value >> Some) |> Option.defaultValue (Some value)) map
Map.fold (fun acc key value -> addOrAdd key value acc) accMap map
containingMap
|> Map.tryFind colorContaining
|> Option.map (fun contained -> contained
|> Seq.map (fun x -> findContained x.Key |> Map.map (fun _ count -> x.Value * count))
|> Seq.fold folder contained
)
|> Option.defaultValue Map.empty
let puzzle7_1 = findContaining "shiny gold" |> Set.count
let puzzle7_2 = findContained "shiny gold" |> Map.toSeq |> Seq.sumBy snd