|
1 | | -use memoize::memoize; |
| 1 | +use bitvec::bitvec; |
2 | 2 | use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; |
3 | 3 |
|
4 | 4 | advent_of_code::solution!(22); |
@@ -53,71 +53,44 @@ const SEQ_MASK_1: u32 = (1 << SEQ_PART_SIZE) - 1; |
53 | 53 | type Seq = u32; |
54 | 54 | type SeqDiff = i8; |
55 | 55 |
|
56 | | -#[inline] |
57 | | -fn diff_to_seq_part(diff: SeqDiff) -> Seq { |
58 | | - (diff as Seq & SEQ_MASK_1) as Seq |
59 | | -} |
60 | | - |
61 | 56 | #[inline] |
62 | 57 | fn push_seq(seq: Seq, diff: SeqDiff) -> Seq { |
63 | 58 | // we are working mod 10 so + 10 is fine |
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() |
| 59 | + ((seq << SEQ_PART_SIZE) | (diff as Seq & SEQ_MASK_1)) & SEQ_MASK_4 |
83 | 60 | } |
84 | 61 |
|
85 | 62 | pub fn part_two(input: &str) -> Option<i32> { |
86 | 63 | let seeds = parse_input(input).collect::<Vec<_>>(); |
87 | | - let seeds_seq_map = seeds |
88 | | - .par_iter() |
89 | | - .map(|seed| { |
90 | | - let mut seq_map = vec![None; 1 << (SEQ_PART_SIZE * 4)]; |
91 | | - let mut prev_price = 0; |
92 | | - let mut secret = *seed; |
93 | | - let mut seq = 0; |
94 | | - for _ in 0..2000 { |
95 | | - secret = next_secret(secret); |
96 | | - let new_price = (secret % 10) as i8; |
97 | | - seq = push_seq(seq, new_price - prev_price); |
98 | | - if seq_map[seq as usize] == None { |
99 | | - seq_map[seq as usize] = Some(new_price as i8); |
100 | | - } |
101 | | - prev_price = new_price; |
| 64 | + |
| 65 | + let mut seq_bananas = vec![0; 1 << (SEQ_PART_SIZE * 4)]; |
| 66 | + |
| 67 | + seeds.iter().for_each(|seed| { |
| 68 | + let mut seen = bitvec![0; 1 << (SEQ_PART_SIZE * 4)]; |
| 69 | + |
| 70 | + let mut prev_price = 0; |
| 71 | + let mut secret = *seed; |
| 72 | + let mut seq = 0; |
| 73 | + |
| 74 | + for i in 0..2000 { |
| 75 | + secret = next_secret(secret); |
| 76 | + let new_price = (secret % 10) as i8; |
| 77 | + seq = push_seq(seq, new_price - prev_price); |
| 78 | + prev_price = new_price; |
| 79 | + |
| 80 | + if i < 4 { |
| 81 | + continue; |
| 82 | + } |
| 83 | + if seen[seq as usize] { |
| 84 | + continue; |
102 | 85 | } |
103 | | - seq_map |
104 | | - }) |
105 | | - .collect::<Vec<_>>(); |
106 | 86 |
|
107 | | - let seq_to_test = gen_all_seq(); |
| 87 | + seen.set(seq as usize, true); |
| 88 | + seq_bananas[seq as usize] += new_price as i32; |
| 89 | + } |
| 90 | + }); |
108 | 91 |
|
109 | | - let max_bananas = seq_to_test |
110 | | - .par_iter() |
111 | | - .map(|&target_seq| { |
112 | | - let bananas = seeds_seq_map |
113 | | - .iter() |
114 | | - .map(|seq_map| seq_map[target_seq as usize].unwrap_or(0) as i32) |
115 | | - .sum(); |
116 | | - bananas |
117 | | - }) |
118 | | - .max(); |
119 | | - |
120 | | - Some(max_bananas.unwrap()) |
| 92 | + let max_bananas = seq_bananas.into_iter().max().unwrap(); |
| 93 | + Some(max_bananas) |
121 | 94 | } |
122 | 95 |
|
123 | 96 | #[cfg(test)] |
|
0 commit comments