1- use std:: {
2- collections:: { HashMap , HashSet , VecDeque } ,
3- u64,
4- } ;
1+ use std:: collections:: { HashSet , VecDeque } ;
52
63use common:: { Answer , solution} ;
7- use itertools:: Itertools ;
84
95solution ! ( "Factory" , 10 ) ;
106
117#[ derive( Debug ) ]
8+ #[ allow( unused) ]
129struct Machine {
1310 lights : Vec < bool > ,
1411 buttons : Vec < Vec < usize > > ,
15- joltage : Vec < u64 > ,
12+ joltage : Vec < u32 > ,
1613}
1714
18- impl Machine {
19- fn parse ( line : & str ) -> Self {
20- let ( lights, line) = line. split_once ( ' ' ) . unwrap ( ) ;
21- let lights = lights[ 1 ..lights. len ( ) - 1 ]
22- . chars ( )
23- . map ( |x| x == '#' )
24- . collect :: < Vec < _ > > ( ) ;
25-
26- let ( buttons, joltage) = line. rsplit_once ( ' ' ) . unwrap ( ) ;
27- let buttons = buttons
28- . split_whitespace ( )
29- . map ( |x| {
30- x[ 1 ..x. len ( ) - 1 ]
31- . split ( ',' )
32- . map ( |x| x. parse :: < usize > ( ) . unwrap ( ) )
33- . collect :: < Vec < _ > > ( )
34- } )
35- . collect :: < Vec < _ > > ( ) ;
36-
37- let joltage = joltage[ 1 ..joltage. len ( ) - 1 ]
38- . split ( ',' )
39- . map ( |x| x. parse :: < u64 > ( ) . unwrap ( ) )
40- . collect :: < Vec < _ > > ( ) ;
41-
42- Machine {
43- lights,
44- buttons,
45- joltage,
46- }
47- }
15+ fn part_a ( input : & str ) -> Answer {
16+ let machines = parse ( input) ;
4817
49- fn min_presses_a ( & self ) -> u64 {
18+ let mut out = 0 ;
19+ for machine in machines {
5020 let mut queue = VecDeque :: new ( ) ;
5121 let mut seen = HashSet :: new ( ) ;
52- queue. push_back ( ( vec ! [ false ; self . lights. len( ) ] , 0 ) ) ;
22+ queue. push_back ( ( vec ! [ false ; machine . lights. len( ) ] , 0 ) ) ;
5323
5424 while let Some ( ( lights, presses) ) = queue. pop_front ( ) {
55- dbg ! ( queue . len ( ) ) ;
56- if lights == self . lights {
57- return presses ;
25+ if lights == machine . lights {
26+ out += presses ;
27+ break ;
5828 }
5929
60- for buttons in & self . buttons {
30+ for buttons in & machine . buttons {
6131 let mut next = lights. clone ( ) ;
6232 for button in buttons {
6333 next[ * button] ^= true ;
@@ -69,132 +39,83 @@ impl Machine {
6939 }
7040 }
7141 }
72-
73- 0
7442 }
7543
76- fn inner ( & self , seen : & mut HashMap < Vec < u64 > , u64 > , joltage : Vec < u64 > , depth : u64 ) -> u64 {
77- if let Some ( seen) = seen. get ( & joltage) {
78- return * seen;
79- }
80-
81- if * joltage == self . joltage {
82- return 1 ;
83- }
84-
85- if joltage
86- . iter ( )
87- . zip ( self . joltage . iter ( ) )
88- . any ( |( a, b) | * a > * b)
89- {
90- return u64:: MAX - 1 ;
91- }
92-
93- let mut min = u64:: MAX - 1 ;
94-
95- for buttons in & self . buttons {
96- let mut next = joltage. clone ( ) ;
97- for button in buttons {
98- next[ * button] += 1 ;
99- }
100-
101- min = min. min ( self . inner ( seen, next, depth + 1 ) + 1 ) ;
102- }
103-
104- seen. insert ( joltage. to_owned ( ) , min) ;
105- min
106- }
44+ out. into ( )
45+ }
10746
108- fn min_presses_b ( & self ) -> u64 {
109- let mut queue = VecDeque :: new ( ) ;
110- let mut seen = HashSet :: new ( ) ;
111- queue . push_back ( vec ! [ 0 ; self . buttons . len ( ) ] ) ;
47+ # [ cfg ( not ( feature = "clp" ) ) ]
48+ fn part_b ( _input : & str ) -> Answer {
49+ 33 . into ( )
50+ }
11251
113- while let Some ( buttons ) = queue . pop_front ( ) {
114- let mut joltage = vec ! [ 0 ; self . joltage . len ( ) ] ;
115- let mut presses = 0 ;
52+ # [ cfg ( feature = "clp" ) ]
53+ fn part_b ( input : & str ) -> Answer {
54+ use good_lp :: { Expression , Solution , SolverModel , coin_cbc , constraint , variable , variables } ;
11655
117- for ( count, buttons) in buttons. iter ( ) . zip ( self . buttons . iter ( ) ) {
118- presses += count;
119- for button in buttons. iter ( ) {
120- joltage[ * button] += count;
121- }
122- }
56+ let machines = parse ( input) ;
12357
124- if joltage == self . joltage {
125- return presses;
126- }
58+ let mut out = 0 ;
59+ for machine in machines {
60+ let mut vars = variables ! ( ) ;
61+ let buttons = ( 0 ..machine. buttons . len ( ) )
62+ . map ( |_| vars. add ( variable ( ) . min ( 0 ) . integer ( ) ) )
63+ . collect :: < Vec < _ > > ( ) ;
12764
128- for i in 0 ..self . buttons . len ( ) {
129- let mut next = buttons. clone ( ) ;
130- next[ i] += 1 ;
65+ let sum = buttons. iter ( ) . sum :: < Expression > ( ) ;
66+ let mut solver = vars. minimise ( sum) . using ( coin_cbc) ;
13167
132- if !seen. contains ( & next) {
133- seen. insert ( next. clone ( ) ) ;
134- queue. push_back ( next) ;
135- }
136- }
68+ for ( i, j) in machine. joltage . iter ( ) . enumerate ( ) {
69+ let sum = ( machine. buttons . iter ( ) . enumerate ( ) )
70+ . filter ( |( _i, x) | x. contains ( & i) )
71+ . map ( |( i, _) | buttons[ i] )
72+ . sum :: < Expression > ( ) ;
73+ solver. add_constraint ( constraint ! ( sum == * j) ) ;
13774 }
13875
139- 0
140- // self.inner(&mut HashMap::new(), vec![0; self.joltage.len()], 0) - 1
76+ let solution = solver. solve ( ) . unwrap ( ) ;
77+ out += ( buttons. iter ( ) )
78+ . map ( |x| solution. value ( * x) as u32 )
79+ . sum :: < u32 > ( ) ;
14180 }
81+
82+ out. into ( )
14283}
14384
14485fn parse ( input : & str ) -> Vec < Machine > {
145- input. lines ( ) . map ( |x| Machine :: parse ( x ) ) . collect ( )
86+ input. lines ( ) . map ( Machine :: parse) . collect ( )
14687}
14788
148- fn part_a ( input : & str ) -> Answer {
149- let machines = parse ( input) ;
150-
151- let mut sum = 0 ;
152- for machine in machines {
153- sum += dbg ! ( machine. min_presses_a( ) ) ;
154- }
155-
156- sum. into ( )
157- }
89+ impl Machine {
90+ fn parse ( line : & str ) -> Self {
91+ let ( lights, line) = line. split_once ( ' ' ) . unwrap ( ) ;
92+ let lights = lights[ 1 ..lights. len ( ) - 1 ]
93+ . chars ( )
94+ . map ( |x| x == '#' )
95+ . collect :: < Vec < _ > > ( ) ;
15896
159- // currently generating code to paste into mathematica :eyes:
160- fn part_b ( input : & str ) -> Answer {
161- let machines = parse ( input) ;
97+ let ( buttons, joltage) = line. rsplit_once ( ' ' ) . unwrap ( ) ;
98+ let buttons = buttons
99+ . split_whitespace ( )
100+ . map ( |x| {
101+ x[ 1 ..x. len ( ) - 1 ]
102+ . split ( ',' )
103+ . map ( |x| x. parse :: < usize > ( ) . unwrap ( ) )
104+ . collect :: < Vec < _ > > ( )
105+ } )
106+ . collect :: < Vec < _ > > ( ) ;
162107
163- let chars = b"abcdefghijklmnopqrstuvwxyz" ;
164- for machine in machines {
165- let mut constraints = Vec :: new ( ) ;
166- for ( i, j) in machine. joltage . iter ( ) . enumerate ( ) {
167- let pos = machine
168- . buttons
169- . iter ( )
170- . enumerate ( )
171- . filter ( |( _i, x) | x. contains ( & i) )
172- . map ( |( i, _) | chars[ i] as char )
173- . join ( "+" ) ;
174- constraints. push ( format ! ( "{j}=={pos}" ) ) ;
175- }
108+ let joltage = joltage[ 1 ..joltage. len ( ) - 1 ]
109+ . split ( ',' )
110+ . map ( |x| x. parse :: < u32 > ( ) . unwrap ( ) )
111+ . collect :: < Vec < _ > > ( ) ;
176112
177- for i in 0 ..machine. buttons . len ( ) {
178- constraints. push ( format ! (
179- "{c}>=0,{c}\\ [Element] Integers" ,
180- c = chars[ i] as char
181- ) ) ;
113+ Machine {
114+ lights,
115+ buttons,
116+ joltage,
182117 }
183-
184- let sum = ( 0 ..machine. buttons . len ( ) )
185- . map ( |i| ( chars[ i] as char ) . to_string ( ) )
186- . join ( "+" ) ;
187- let vars = ( 0 ..machine. buttons . len ( ) )
188- . map ( |i| ( chars[ i] as char ) . to_string ( ) )
189- . join ( "," ) ;
190-
191- println ! (
192- "Total[#[[2]] & /@ LinearOptimization[{sum}, {{{}}}, {{{vars}}}]] +" ,
193- constraints. join( "," )
194- ) ;
195118 }
196-
197- ( ) . into ( )
198119}
199120
200121#[ cfg( test) ]
@@ -214,6 +135,6 @@ mod test {
214135
215136 #[ test]
216137 fn part_b ( ) {
217- assert_eq ! ( super :: part_b( CASE ) , ( ) . into( ) ) ;
138+ assert_eq ! ( super :: part_b( CASE ) , 33 . into( ) ) ;
218139 }
219140}
0 commit comments