|
1 | 1 | #r "nuget: Flips"
|
| 2 | + |
2 | 3 | open Flips
|
3 | 4 | open Flips.Types
|
4 | 5 | open Flips.SliceMap
|
@@ -28,64 +29,79 @@ type Robot =
|
28 | 29 | | GeodeRobot
|
29 | 30 |
|
30 | 31 | let readBlueprint (s: string) =
|
31 |
| - match s with |
32 |
| - | Match |
33 |
| - "Each ore robot costs (.*) ore. Each clay robot costs (.*) ore. Each obsidian robot costs (.*) ore and (.*) clay. Each geode robot costs (.*) ore and (.*) obsidian." |
34 |
| - [ oo; co; bo; bc; go; gb ] -> [ |
35 |
| - OreRobot, [ Ore, int oo ] |
36 |
| - ClayRobot, [ Ore, int co ] |
37 |
| - ObsidianRobot, [ Ore, int bo; Clay, int bc ] |
38 |
| - GeodeRobot, [ Ore, int go; Obsidian, int gb ] |
39 |
| - ] |
| 32 | + match s with |
| 33 | + | Match "Each ore robot costs (.*) ore. Each clay robot costs (.*) ore. Each obsidian robot costs (.*) ore and (.*) clay. Each geode robot costs (.*) ore and (.*) obsidian." [ oo |
| 34 | + co |
| 35 | + bo |
| 36 | + bc |
| 37 | + go |
| 38 | + gb ] -> |
| 39 | + [ OreRobot, [ Ore, int oo ] |
| 40 | + ClayRobot, [ Ore, int co ] |
| 41 | + ObsidianRobot, [ Ore, int bo; Clay, int bc ] |
| 42 | + GeodeRobot, [ Ore, int go; Obsidian, int gb ] ] |
40 | 43 |
|
41 | 44 | let blueprints = lines |> Array.map readBlueprint
|
42 | 45 |
|
43 | 46 | let model blueprint totalSteps =
|
44 |
| - let steps = [1..totalSteps] |
| 47 | + let steps = [ 1..totalSteps ] |
45 | 48 | let robotTypes = [ OreRobot; ClayRobot; ObsidianRobot; GeodeRobot ]
|
46 | 49 | let resourceTypes = [ Ore; Clay; Obsidian; Geode ]
|
47 |
| - let costs = blueprint |> List.collect (fun (r, res) -> res |> List.map (fun (o, x) -> (r, o), float x)) |> SMap2.ofList |
48 |
| - let robots = |
| 50 | + |
| 51 | + let costs = |
| 52 | + blueprint |
| 53 | + |> List.collect (fun (r, res) -> res |> List.map (fun (o, x) -> (r, o), float x)) |
| 54 | + |> SMap2.ofList |
| 55 | + |
| 56 | + let robots = |
49 | 57 | DecisionBuilder "robot" {
|
50 | 58 | for _ in steps do
|
51 |
| - for t in robotTypes -> |
52 |
| - Boolean |
53 |
| - } |
54 |
| - |> SMap2.ofSeq |
55 |
| - let robotsCons = |
| 59 | + for t in robotTypes -> Boolean |
| 60 | + } |
| 61 | + |> SMap2.ofSeq |
| 62 | + |
| 63 | + let robotsCons = |
56 | 64 | ConstraintBuilder "factoryLimit" {
|
57 | 65 | for i in steps do
|
58 | 66 | yield sum robots[i, All] <== 1.0
|
59 |
| - } |
60 |
| - let collectMult i = [1..i-1] |> List.map (fun j -> j, float (i-j)) |> SMap.ofList |
61 |
| - let buys = |
| 67 | + } |
| 68 | + |
| 69 | + let collectMult i = |
| 70 | + [ 1 .. i - 1 ] |> List.map (fun j -> j, float (i - j)) |> SMap.ofList |
| 71 | + |
| 72 | + let buys = |
62 | 73 | ConstraintBuilder "buy" {
|
63 | 74 | for i in steps do
|
64 |
| - for (t,r) in Seq.zip robotTypes resourceTypes -> |
65 |
| - sum (robots[LessThan (i-1), t] .* (collectMult (i-1))) + (if t=OreRobot && i > 1 then float (i-1) else 0.0) >== sum (robots[LessOrEqual i,All] .* costs[All,r]) |
66 |
| - } |
| 75 | + for (t, r) in Seq.zip robotTypes resourceTypes -> |
| 76 | + sum (robots[LessThan(i - 1), t] .* (collectMult (i - 1))) |
| 77 | + + (if t = OreRobot && i > 1 then float (i - 1) else 0.0) |
| 78 | + >== sum (robots[LessOrEqual i, All] .* costs[All, r]) |
| 79 | + } |
| 80 | + |
67 | 81 | let objExpr = sum (robots.[All, GeodeRobot] .* collectMult totalSteps)
|
68 | 82 | let objective = Objective.create "Obj" Maximize objExpr
|
| 83 | + |
69 | 84 | let model =
|
70 | 85 | Model.create objective
|
71 | 86 | |> Model.addConstraints robotsCons
|
72 | 87 | |> Model.addConstraints buys
|
| 88 | + |
73 | 89 | match Solver.solve Settings.basic model with
|
74 | 90 | | Optimal sol ->
|
75 | 91 | //sol.DecisionResults |> Map.filter (fun _ x -> x > 0.0) |> Map.toSeq |> Seq.map (fun (k, x) -> k.Name, x) |> Seq.sort |> Seq.iter (printfn "%A")
|
76 | 92 | sol.ObjectiveResult |> int
|
77 | 93 |
|
78 | 94 |
|
79 |
| -let part1() = |
| 95 | +let part1 () = |
80 | 96 | let results = blueprints |> Array.mapi (fun i b -> i, model b 24)
|
81 | 97 | printfn "%A" results
|
82 |
| - results |> Seq.map (fun (i, x) -> (i+1) * x) |> Seq.sum |
| 98 | + results |> Seq.map (fun (i, x) -> (i + 1) * x) |> Seq.sum |
83 | 99 |
|
84 |
| -printfn $"PART1: {part1()}" |
| 100 | +printfn $"PART1: {part1 ()}" |
85 | 101 |
|
86 |
| -let part2() = |
| 102 | +let part2 () = |
87 | 103 | let results = blueprints[..2] |> Array.map (fun b -> model b 32)
|
88 | 104 | printfn "%A" results
|
89 | 105 | results |> Seq.reduce (*)
|
90 | 106 |
|
91 |
| -printfn $"PART2: {part2()}" |
| 107 | +printfn $"PART2: {part2 ()}" |
0 commit comments