Skip to content

Commit da92303

Browse files
committed
2018
1 parent 63c85d0 commit da92303

File tree

1 file changed

+36
-27
lines changed

1 file changed

+36
-27
lines changed

2018/day23/day23.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! [Day 23: Experimental Emergency Teleportation](https://adventofcode.com/2018/day/23)
22
33
use regex::Regex;
4+
use std::ops::AddAssign;
5+
use z3::ast::Int;
46

57
struct Nanobot {
68
x: i64,
@@ -57,46 +59,53 @@ impl Puzzle {
5759

5860
/// Solve part two.
5961
fn part2(&self) -> i64 {
60-
use z3::ast;
61-
6262
let cfg = z3::Config::new();
6363
let ctx = z3::Context::new(&cfg);
6464

6565
let o = z3::Optimize::new(&ctx);
6666

67-
let x = ast::Int::new_const(&ctx, "x");
68-
let y = ast::Int::new_const(&ctx, "y");
69-
let z = ast::Int::new_const(&ctx, "z");
67+
let x = Int::new_const(&ctx, "x");
68+
let y = Int::new_const(&ctx, "y");
69+
let z = Int::new_const(&ctx, "z");
7070

71-
for bot in &self.nanobots {
72-
let px = ast::Int::from_i64(&ctx, bot.x);
73-
let py = ast::Int::from_i64(&ctx, bot.y);
74-
let pz = ast::Int::from_i64(&ctx, bot.z);
71+
let one = Int::from_u64(&ctx, 1);
72+
let zero = Int::from_u64(&ctx, 0);
73+
let mut count = Int::from_u64(&ctx, 0);
7574

76-
// px.gt(&x).implies(other)
75+
let dist = |px, py, pz| -> _ {
76+
let px = Int::from_i64(&ctx, px);
77+
let py = Int::from_i64(&ctx, py);
78+
let pz = Int::from_i64(&ctx, pz);
7779

78-
let dx = x.gt(&px).ite(
79-
&ast::Int::sub(&ctx, &[&x, &px]),
80-
&ast::Int::sub(&ctx, &[&px, &x]),
81-
);
80+
let dx = x
81+
.ge(&px) // x-px if x>=px, px-x otherwises
82+
.ite(&Int::sub(&ctx, &[&x, &px]), &Int::sub(&ctx, &[&px, &x]));
8283

83-
let dy = y.gt(&py).ite(
84-
&ast::Int::sub(&ctx, &[&y, &py]),
85-
&ast::Int::sub(&ctx, &[&py, &y]),
86-
);
84+
let dy = y
85+
.ge(&py)
86+
.ite(&Int::sub(&ctx, &[&y, &py]), &Int::sub(&ctx, &[&py, &y]));
8787

88-
let dz = z.gt(&pz).ite(
89-
&ast::Int::sub(&ctx, &[&z, &pz]),
90-
&ast::Int::sub(&ctx, &[&pz, &z]),
91-
);
88+
let dz = z
89+
.ge(&pz)
90+
.ite(&Int::sub(&ctx, &[&z, &pz]), &Int::sub(&ctx, &[&pz, &z]));
9291

93-
let manhattan = ast::Int::add(&ctx, &[&dx, &dy, &dz]);
92+
Int::add(&ctx, &[&dx, &dy, &dz])
93+
};
9494

95-
let cond = manhattan.le(&ast::Int::from_u64(&ctx, bot.r));
95+
for bot in &self.nanobots {
96+
let d = dist(bot.x, bot.y, bot.z);
9697

97-
o.assert_soft(&cond, 1, None);
98+
count.add_assign(
99+
d // manhattan distance
100+
.le(&Int::from_u64(&ctx, bot.r)) // <=r
101+
.ite(&one, &zero), // count of
102+
);
98103
}
99104

105+
o.maximize(&count);
106+
107+
o.minimize(&dist(0, 0, 0));
108+
100109
match o.check(&[]) {
101110
z3::SatResult::Sat => {
102111
if let Some(model) = o.get_model() {
@@ -106,8 +115,8 @@ impl Puzzle {
106115
return xx.as_i64().unwrap() + yy.as_i64().unwrap() + zz.as_i64().unwrap();
107116
}
108117
}
109-
z3::SatResult::Unsat => eprintln!("z3::SatResult::Unsat"),
110-
z3::SatResult::Unknown => eprintln!("z3::SatResult::Unknown"),
118+
z3::SatResult::Unsat => eprintln!("result Unsat"),
119+
z3::SatResult::Unknown => eprintln!("result Unknown"),
111120
}
112121

113122
0

0 commit comments

Comments
 (0)