@@ -36,24 +36,6 @@ fn parse_input<'a>(input: &'a str) -> impl Iterator<Item = Secret> + 'a {
36
36
. map ( |l| l. parse :: < Secret > ( ) . unwrap ( ) )
37
37
}
38
38
39
- #[ memoize]
40
- fn gen_all_seq ( ) -> Vec < u32 > {
41
- ( -9 ..9 )
42
- . flat_map ( |a| {
43
- ( -9 ..9 ) . flat_map ( move |b| {
44
- ( -9 ..9 ) . flat_map ( move |c| {
45
- ( -9 ..9 ) . map ( move |d| {
46
- ( diff_to_seq_part ( a) << 24 )
47
- | ( diff_to_seq_part ( b) << 16 )
48
- | ( diff_to_seq_part ( c) << 8 )
49
- | diff_to_seq_part ( d)
50
- } )
51
- } )
52
- } )
53
- } )
54
- . collect ( )
55
- }
56
-
57
39
pub fn part_one ( input : & str ) -> Option < u64 > {
58
40
let seeds = parse_input ( input) . collect :: < Vec < _ > > ( ) ;
59
41
let res = seeds
@@ -64,38 +46,61 @@ pub fn part_one(input: &str) -> Option<u64> {
64
46
Some ( res)
65
47
}
66
48
49
+ const SEQ_PART_SIZE : usize = 5 ;
50
+ const SEQ_MASK_4 : u32 = ( 1 << ( SEQ_PART_SIZE * 4 ) ) - 1 ;
51
+ const SEQ_MASK_1 : u32 = ( 1 << SEQ_PART_SIZE ) - 1 ;
52
+
67
53
type Seq = u32 ;
68
54
type SeqDiff = i8 ;
69
55
70
56
#[ inline]
71
57
fn diff_to_seq_part ( diff : SeqDiff ) -> Seq {
72
- ( diff as Seq ) & 0xFF
58
+ ( diff as Seq & SEQ_MASK_1 ) as Seq
73
59
}
74
60
75
61
#[ inline]
76
- fn push_seq ( seq : Seq , diff : SeqDiff ) -> u32 {
62
+ fn push_seq ( seq : Seq , diff : SeqDiff ) -> Seq {
77
63
// we are working mod 10 so + 10 is fine
78
- ( seq << 8 ) | diff_to_seq_part ( diff)
64
+ ( ( seq << SEQ_PART_SIZE ) | diff_to_seq_part ( diff) ) & SEQ_MASK_4
65
+ }
66
+
67
+ #[ memoize]
68
+ fn gen_all_seq ( ) -> Vec < Seq > {
69
+ ( -9 ..9 )
70
+ . flat_map ( |a| {
71
+ ( -9 ..9 ) . flat_map ( move |b| {
72
+ ( -9 ..9 ) . flat_map ( move |c| {
73
+ ( -9 ..9 ) . map ( move |d| {
74
+ ( diff_to_seq_part ( a) << ( SEQ_PART_SIZE * 3 ) )
75
+ | ( diff_to_seq_part ( b) << ( SEQ_PART_SIZE * 2 ) )
76
+ | ( diff_to_seq_part ( c) << SEQ_PART_SIZE )
77
+ | diff_to_seq_part ( d)
78
+ } )
79
+ } )
80
+ } )
81
+ } )
82
+ . collect ( )
79
83
}
80
84
81
85
pub fn part_two ( input : & str ) -> Option < i32 > {
82
86
let seeds = parse_input ( input) . collect :: < Vec < _ > > ( ) ;
83
- let seeds_prices = seeds
87
+ let seeds_seq_map = seeds
84
88
. par_iter ( )
85
89
. map ( |seed| {
86
- let mut prices = [ ( 0_i8 , 0_u32 ) ; 2000 ] ;
87
-
90
+ let mut seq_map = vec ! [ None ; 1 << ( SEQ_PART_SIZE * 4 ) ] ;
88
91
let mut prev_price = 0 ;
89
92
let mut secret = * seed;
90
93
let mut seq = 0 ;
91
- for i in 0 ..2000 {
94
+ for _ in 0 ..2000 {
92
95
secret = next_secret ( secret) ;
93
96
let new_price = ( secret % 10 ) as i8 ;
94
97
seq = push_seq ( seq, new_price - prev_price) ;
95
- prices[ i] = ( new_price, seq) ;
98
+ if seq_map[ seq as usize ] == None {
99
+ seq_map[ seq as usize ] = Some ( new_price as i8 ) ;
100
+ }
96
101
prev_price = new_price;
97
102
}
98
- prices
103
+ seq_map
99
104
} )
100
105
. collect :: < Vec < _ > > ( ) ;
101
106
@@ -104,20 +109,10 @@ pub fn part_two(input: &str) -> Option<i32> {
104
109
let max_bananas = seq_to_test
105
110
. par_iter ( )
106
111
. map ( |& target_seq| {
107
- let bananas = seeds_prices
112
+ let bananas = seeds_seq_map
108
113
. iter ( )
109
- . map ( |& seed_data| {
110
- let bananas = seed_data
111
- . iter ( )
112
- . skip ( 4 )
113
- . find ( |& ( _, seq) | * seq == target_seq)
114
- . map ( |( p, _) | * p)
115
- . unwrap_or ( 0 ) ;
116
-
117
- bananas as i32
118
- } )
114
+ . map ( |seq_map| seq_map[ target_seq as usize ] . unwrap_or ( 0 ) as i32 )
119
115
. sum ( ) ;
120
-
121
116
bananas
122
117
} )
123
118
. max ( ) ;
0 commit comments