1
- use std:: iter:: repeat;
1
+ use std:: iter:: { once , repeat} ;
2
2
3
3
use common:: { solution, Answer } ;
4
4
use itertools:: Itertools ;
@@ -11,18 +11,9 @@ fn part_a(input: &str) -> Answer {
11
11
12
12
for num in input. lines ( ) {
13
13
let mut num = num. parse :: < u64 > ( ) . unwrap ( ) ;
14
-
15
- for _ in 0 ..2000 {
16
- num ^= num * 64 ;
17
- num %= 16777216 ;
18
-
19
- num ^= num / 32 ;
20
- num %= 16777216 ;
21
-
22
- num ^= num * 2048 ;
23
- num %= 16777216 ;
24
- }
25
-
14
+ ( 0 ..2000 ) . for_each ( |_| {
15
+ next ( & mut num) ;
16
+ } ) ;
26
17
sum += num;
27
18
}
28
19
@@ -31,51 +22,35 @@ fn part_a(input: &str) -> Answer {
31
22
32
23
fn part_b ( input : & str ) -> Answer {
33
24
let mut buyers = Vec :: new ( ) ;
34
- let mut diffs = Vec :: new ( ) ;
35
-
36
25
for num in input. lines ( ) {
37
26
let mut num = num. parse :: < u64 > ( ) . unwrap ( ) ;
38
- let mut seq = vec ! [ num] ;
39
-
40
- for _ in 0 ..2000 {
41
- num ^= num * 64 ;
42
- num %= 16777216 ;
43
-
44
- num ^= num / 32 ;
45
- num %= 16777216 ;
46
-
47
- num ^= num * 2048 ;
48
- num %= 16777216 ;
49
-
50
- seq. push ( num) ;
51
- }
52
-
27
+ let seq = once ( num)
28
+ . chain ( ( 0 ..2000 ) . map ( |_| next ( & mut num) ) )
29
+ . collect :: < Vec < _ > > ( ) ;
53
30
buyers. push ( seq) ;
54
31
}
55
32
56
- for buyer in buyers. iter ( ) {
57
- let mut diff = Vec :: new ( ) ;
58
- for ( & a, & b) in buyer. iter ( ) . tuple_windows ( ) {
59
- diff. push ( ( b % 10 ) as i8 - ( a % 10 ) as i8 ) ;
60
- }
61
- diffs. push ( diff) ;
62
- }
33
+ let diffs = buyers
34
+ . iter ( )
35
+ . map ( |buyer| {
36
+ buyer
37
+ . iter ( )
38
+ . tuple_windows ( )
39
+ . map ( |( & a, & b) | ( b % 10 ) as i8 - ( a % 10 ) as i8 )
40
+ . collect :: < Vec < _ > > ( )
41
+ } )
42
+ . collect :: < Vec < _ > > ( ) ;
63
43
64
44
let out = repeat ( -9 ..=9 )
65
45
. take ( 4 )
66
46
. multi_cartesian_product ( )
47
+ . map ( |x| ( x[ 0 ] , x[ 1 ] , x[ 2 ] , x[ 3 ] ) )
67
48
. par_bridge ( )
68
- . map ( |x| {
69
- let ( a, b, c, d) = ( x[ 0 ] , x[ 1 ] , x[ 2 ] , x[ 3 ] ) ;
49
+ . map ( |( a, b, c, d) | {
70
50
let mut sum = 0 ;
71
51
72
52
for ( diff, nums) in diffs. iter ( ) . zip ( buyers. iter ( ) ) {
73
- let idx = diff
74
- . iter ( )
75
- . tuple_windows ( )
76
- . position ( |( & ax, & bx, & cx, & dx) | ax == a && bx == b && cx == c && dx == d) ;
77
-
78
- if let Some ( idx) = idx {
53
+ if let Some ( idx) = find_sequence ( diff, ( a, b, c, d) ) {
79
54
sum += nums[ idx + 4 ] % 10 ;
80
55
}
81
56
}
@@ -88,6 +63,26 @@ fn part_b(input: &str) -> Answer {
88
63
out. into ( )
89
64
}
90
65
66
+ fn next ( num : & mut u64 ) -> u64 {
67
+ * num ^= * num * 64 ;
68
+ * num %= 16777216 ;
69
+
70
+ * num ^= * num / 32 ;
71
+ * num %= 16777216 ;
72
+
73
+ * num ^= * num * 2048 ;
74
+ * num %= 16777216 ;
75
+
76
+ * num
77
+ }
78
+
79
+ fn find_sequence ( haystack : & [ i8 ] , ( a, b, c, d) : ( i8 , i8 , i8 , i8 ) ) -> Option < usize > {
80
+ haystack
81
+ . iter ( )
82
+ . tuple_windows ( )
83
+ . position ( |( & ax, & bx, & cx, & dx) | ax == a && bx == b && cx == c && dx == d)
84
+ }
85
+
91
86
#[ cfg( test) ]
92
87
mod test {
93
88
use indoc:: indoc;
0 commit comments