aboutsummaryrefslogtreecommitdiff
path: root/2022/19
diff options
context:
space:
mode:
Diffstat (limited to '2022/19')
-rw-r--r--2022/19/a.rs18
-rw-r--r--2022/19/common.rs169
2 files changed, 187 insertions, 0 deletions
diff --git a/2022/19/a.rs b/2022/19/a.rs
new file mode 100644
index 0000000..57e83e6
--- /dev/null
+++ b/2022/19/a.rs
@@ -0,0 +1,18 @@
1use std::collections::HashMap;
2mod common;
3use common::*;
4
5fn main() {
6 const MINUTES: i32 = 24;
7 let mut mem = HashMap::<(Status, i32), i32>::new();
8 let mut i = 1;
9 let mut sum = 0;
10 for bp in read_blueprints_from_stdin() {
11 let mg = most_geodes(&bp, Status::new(), MINUTES, &mut mem);
12 println!("{i}: {mg}");
13 sum += i * mg;
14 mem.clear();
15 i += 1;
16 }
17 println!("{sum}");
18}
diff --git a/2022/19/common.rs b/2022/19/common.rs
new file mode 100644
index 0000000..bfeaa9b
--- /dev/null
+++ b/2022/19/common.rs
@@ -0,0 +1,169 @@
1// This works for part 1, but it is too slow for part 2.
2// May be I am doing something wrong with caching?
3
4use std::cmp::{max, Ordering};
5use std::ops::{AddAssign, SubAssign};
6use std::collections::HashMap;
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
9pub struct Stock {
10 pub ore: i32,
11 pub cla: i32,
12 pub obs: i32,
13 pub geo: i32
14}
15
16impl Stock {
17 pub fn all_lower(&self, other: &Self) -> bool {
18 self.ore <= other.ore && self.cla <= other.cla &&
19 self.obs <= other.obs && self.geo <= other.geo
20 }
21}
22
23impl PartialOrd for Stock {
24 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
25 if self == other { return Some(Ordering::Equal); }
26 if self.all_lower(other) { return Some(Ordering::Less); }
27 if other.all_lower(self) { return Some(Ordering::Greater); }
28 None
29 }
30}
31
32impl AddAssign<&Stock> for Stock {
33 fn add_assign(&mut self, other: &Self) {
34 self.ore += other.ore;
35 self.cla += other.cla;
36 self.obs += other.obs;
37 self.geo += other.geo;
38 }
39}
40
41impl SubAssign<&Stock> for Stock {
42 fn sub_assign(&mut self, other: &Self) {
43 self.ore -= other.ore;
44 self.cla -= other.cla;
45 self.obs -= other.obs;
46 self.geo -= other.geo;
47 }
48}
49
50#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
51pub struct Status {
52 pub bots: Stock,
53 pub resources: Stock
54}
55
56impl Status {
57 pub fn new() -> Status {
58 Status {
59 bots: Stock { ore: 1, cla: 0, obs: 0, geo: 0 },
60 resources: Stock { ore: 0, cla: 0, obs: 0, geo: 0 }
61 }
62 }
63}
64
65#[derive(Debug, Clone, Hash)]
66pub struct Blueprint {
67 ore_bot_cost: Stock,
68 cla_bot_cost: Stock,
69 obs_bot_cost: Stock,
70 geo_bot_cost: Stock
71}
72
73impl Blueprint {
74 fn parse_one_resource(line: &str, i: &mut usize) -> i32 {
75 *i = line[*i..].find("costs ").unwrap() + 6 + *i;
76 let j = line[*i..].find(' ').unwrap() + *i;
77 line[*i..j].parse::<i32>().unwrap()
78 }
79
80 fn parse_two_resources(line: &str, i: &mut usize) -> (i32, i32) {
81 *i = line[*i..].find("costs ").unwrap() + 6 + *i;
82 let j = line[*i..].find(' ').unwrap() + *i;
83 let a = line[*i..j].parse::<i32>().unwrap();
84
85 *i = line[*i..].find("and ").unwrap() + 4 + *i;
86 let j = line[*i..].find(' ').unwrap() + *i;
87 let b = line[*i..j].parse::<i32>().unwrap();
88
89 (a, b)
90 }
91
92 pub fn from_line(line: &str) -> Blueprint {
93 let mut i = 0;
94
95 let ore = Blueprint::parse_one_resource(&line, &mut i);
96 let ore_bot_cost = Stock { ore, cla: 0, obs: 0, geo: 0 };
97
98 let ore = Blueprint::parse_one_resource(&line, &mut i);
99 let cla_bot_cost = Stock { ore, cla: 0, obs: 0, geo: 0 };
100
101 let (ore, cla) = Blueprint::parse_two_resources(&line, &mut i);
102 let obs_bot_cost = Stock { ore, cla, obs: 0, geo: 0 };
103
104 let (ore, obs) = Blueprint::parse_two_resources(&line, &mut i);
105 let geo_bot_cost = Stock { ore, cla: 0, obs, geo: 0 };
106
107 Blueprint { ore_bot_cost, cla_bot_cost, obs_bot_cost, geo_bot_cost }
108 }
109}
110
111pub fn read_blueprints_from_stdin() -> Vec<Blueprint> {
112 let mut v = vec![];
113 let mut line = String::new();
114 while std::io::stdin().read_line(&mut line).unwrap() > 0 {
115 v.push(Blueprint::from_line(&line));
116 line.clear();
117 }
118 v
119}
120
121pub fn most_geodes(
122 bp: &Blueprint,
123 s: Status,
124 m: i32,
125 mem: &mut HashMap<(Status, i32), i32>
126) -> i32 {
127 if let Some(r) = mem.get(&(s, m)) { return *r; }
128 if m == 0 { return s.resources.geo; }
129
130 let mut new_status = s;
131 new_status.resources += &new_status.bots;
132
133 let mut result = most_geodes(bp, new_status, m-1, mem);
134
135 if m > 4 && s.resources >= bp.ore_bot_cost {
136 new_status.resources -= &bp.ore_bot_cost;
137 new_status.bots.ore += 1;
138 result = max(result, most_geodes(bp, new_status, m-1, mem));
139 new_status.bots.ore -= 1;
140 new_status.resources += &bp.ore_bot_cost;
141 }
142
143 if m > 3 && s.resources >= bp.cla_bot_cost {
144 new_status.resources -= &bp.cla_bot_cost;
145 new_status.bots.cla += 1;
146 result = max(result, most_geodes(bp, new_status, m-1, mem));
147 new_status.bots.cla -= 1;
148 new_status.resources += &bp.cla_bot_cost;
149 }
150
151 if m > 2 && s.resources >= bp.obs_bot_cost {
152 new_status.resources -= &bp.obs_bot_cost;
153 new_status.bots.obs += 1;
154 result = max(result, most_geodes(bp, new_status, m-1, mem));
155 new_status.bots.obs -= 1;
156 new_status.resources += &bp.obs_bot_cost;
157 }
158
159 if m > 1 && s.resources >= bp.geo_bot_cost {
160 new_status.resources -= &bp.geo_bot_cost;
161 new_status.bots.geo += 1;
162 result = max(result, most_geodes(bp, new_status, m-1, mem));
163 new_status.bots.geo -= 1;
164 new_status.resources += &bp.geo_bot_cost;
165 }
166
167 mem.insert((s, m), result);
168 result
169}

Generated with cgit - Back to sebastiano.tronto.net