11//! [Day 23: Experimental Emergency Teleportation](https://adventofcode.com/2018/day/23)
22
33use regex:: Regex ;
4+ use std:: ops:: AddAssign ;
5+ use z3:: ast:: Int ;
46
57struct 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