Skip to content

Commit 5fbf9b9

Browse files
committed
Day 14-2
1 parent b155f6f commit 5fbf9b9

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

day14-2.ts

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import * as fs from "fs"
2+
3+
const input = fs.readFileSync("input-day14.txt", "utf8")
4+
const lines = input.trim().split("\n")
5+
const recipes = lines
6+
.map(line => {
7+
const [i, o] = line.split("=>")
8+
return [i.split(",").map(s => s.trim()).map(parse), parse(o.trim())] as const
9+
})
10+
.reduce((a, v) => {
11+
a.set(v[1][1], v)
12+
return a
13+
}, new Map<Element, Recipe>())
14+
15+
function parse(ingredient: string): Ingredient {
16+
const [c, n] = ingredient.split(" ")
17+
return [Number(c), n]
18+
}
19+
20+
function print(recipe: Recipe) {
21+
console.log(recipe[0].map(i => `${i[0]} ${i[1]}`).join(", "), " => ", recipe[1][0], recipe[1][1])
22+
}
23+
24+
type Quantity = number
25+
type Element = string
26+
type Ingredient = readonly [Quantity, Element]
27+
type Recipe = readonly [Ingredient[], Ingredient]
28+
29+
class Bag {
30+
private readonly bag = new Map<Element, Quantity>()
31+
get(e: Element) {
32+
return this.bag.get(e) ?? 0
33+
}
34+
add(e: Element, q: Quantity) {
35+
this.bag.set(e, Math.max(0, q + this.get(e)))
36+
}
37+
remove(e: Element, q: Quantity) {
38+
this.add(e, -q)
39+
}
40+
delete(e: Element) {
41+
this.bag.delete(e)
42+
}
43+
entries() {
44+
return this.bag.entries()
45+
}
46+
get size() {
47+
return this.bag.size
48+
}
49+
}
50+
51+
52+
function oreForFuel(quantity: Quantity) {
53+
const need = new Bag()
54+
need.add("FUEL", quantity)
55+
56+
const spares = new Bag()
57+
58+
do {
59+
const [e, q] = Array.from(need.entries()).filter(([e,]) => e !== "ORE")[0]
60+
need.delete(e)
61+
62+
const needs = ingredients(recipes.get(e), q, spares)
63+
needs.forEach(([q, e]) => {
64+
need.add(e, q)
65+
})
66+
} while (need.size > 1)
67+
return need.get("ORE")
68+
}
69+
70+
function ingredients(recipe: Recipe, quantity: Quantity, spares: Bag): Ingredient[] {
71+
const e = recipe[1][1]
72+
73+
const spare = spares.get(e)
74+
quantity = Math.max(0, quantity - spare)
75+
spares.remove(e, quantity)
76+
if (quantity === 0) {
77+
return []
78+
}
79+
80+
const factor = Math.ceil(quantity / recipe[1][0])
81+
const producing = recipe[1][0] * factor
82+
spares.add(e, producing - quantity)
83+
return recipe[0].map(r => ([r[0] * factor, r[1]]))
84+
}
85+
86+
const maxOre = 1000000000000
87+
let fuelL = 1
88+
let fuelU = 1000000000000
89+
90+
do {
91+
let fuel = fuelL + Math.floor((fuelU - fuelL) / 2)
92+
let ore = oreForFuel(fuel)
93+
if (ore < maxOre && oreForFuel(fuel + 1) > maxOre) {
94+
console.log(fuel)
95+
break
96+
}
97+
if (ore > maxOre) {
98+
fuelU = fuel - 1
99+
} else if (ore < maxOre) {
100+
fuelL = fuel + 1
101+
}
102+
} while (true)

0 commit comments

Comments
 (0)