|
1 | 1 | use std::collections::HashMap; |
2 | 2 | use std::env::args; |
3 | 3 | use std::fs::File; |
| 4 | +use std::hash::{Hash, Hasher}; |
4 | 5 | use std::io::{self, BufRead, BufWriter, Write}; |
5 | 6 | use std::path::Path; |
6 | | -use std::hash::{Hash, Hasher}; |
7 | 7 |
|
8 | 8 | type Dictionary = HashMap<DigitBytes, Vec<String>>; |
9 | 9 |
|
@@ -140,68 +140,68 @@ fn char_to_digit(ch: u8) -> Option<u8> { |
140 | 140 |
|
141 | 141 | #[derive(Debug, Eq, Clone)] |
142 | 142 | struct DigitBytes { |
143 | | - even: bool, |
144 | | - full: bool, |
145 | | - write_index: usize, |
146 | | - bytes: [u8; 25], |
| 143 | + high: bool, |
| 144 | + shl: usize, |
| 145 | + bytes: [u128; 2], |
147 | 146 | } |
148 | 147 |
|
149 | 148 | impl DigitBytes { |
150 | 149 | fn new() -> DigitBytes { |
151 | | - DigitBytes { even: true, write_index: 0, bytes: [0; 25], full: false } |
| 150 | + DigitBytes { high: false, shl: 0, bytes: [0; 2] } |
152 | 151 | } |
153 | 152 |
|
154 | 153 | fn push(&mut self, b: u8) { |
155 | | - if self.full { |
156 | | - panic!("too many digits pushed") |
157 | | - } |
158 | | - if self.even { |
159 | | - self.bytes[self.write_index] = b; |
160 | | - } else { |
161 | | - self.bytes[self.write_index] += b << 4; |
162 | | - if self.write_index + 1 == self.bytes.len() { |
163 | | - // can't increase index anymore otherwise will break Eq and Hash checks |
164 | | - self.full = true; |
165 | | - } else { |
166 | | - self.write_index += 1; |
167 | | - } |
| 154 | + let idx = if self.high { 1 } else { 0 }; |
| 155 | + self.bytes[idx] += (b as u128) << self.shl; |
| 156 | + self.shl += 4; |
| 157 | + if self.shl == 128 { |
| 158 | + self.shl = 0; |
| 159 | + self.high = true; |
168 | 160 | } |
169 | | - self.even = !self.even; |
170 | 161 | } |
171 | 162 | } |
172 | 163 |
|
173 | 164 | impl PartialEq<Self> for DigitBytes { |
174 | 165 | fn eq(&self, other: &Self) -> bool { |
175 | | - self.full == other.full && |
176 | | - self.even == other.even && |
177 | | - self.bytes[0..=self.write_index] == other.bytes[0..=other.write_index] |
| 166 | + self.high == other.high && |
| 167 | + self.shl == other.shl && |
| 168 | + self.bytes == other.bytes |
178 | 169 | } |
179 | 170 | } |
180 | 171 |
|
181 | 172 | impl Hash for DigitBytes { |
182 | 173 | fn hash<H: Hasher>(&self, state: &mut H) { |
183 | | - self.bytes[0..=self.write_index].hash(state); |
184 | | - self.even.hash(state); |
185 | | - self.full.hash(state); |
| 174 | + self.high.hash(state); |
| 175 | + self.shl.hash(state); |
| 176 | + self.bytes.hash(state); |
186 | 177 | } |
187 | 178 | } |
188 | 179 |
|
189 | 180 | #[cfg(test)] |
190 | 181 | mod digit_bytes_test { |
191 | | - use crate::DigitBytes; |
192 | 182 | use std::collections::HashMap; |
193 | 183 |
|
| 184 | + use crate::DigitBytes; |
| 185 | + |
194 | 186 | #[test] |
195 | 187 | fn can_write() { |
196 | | - let mut expected_bytes = [0; 25]; |
| 188 | + let mut expected_bytes = [0u128; 2]; |
197 | 189 | let mut bytes = DigitBytes::new(); |
198 | 190 | assert_eq!(bytes.bytes, expected_bytes); |
199 | 191 | bytes.push(9); |
200 | 192 | bytes.push(2); |
201 | 193 | expected_bytes[0] = 41; |
202 | 194 | assert_eq!(bytes.bytes, expected_bytes); |
203 | 195 | bytes.push(4); |
204 | | - expected_bytes[1] = 4; |
| 196 | + expected_bytes[0] = 1065; |
| 197 | + assert_eq!(bytes.bytes, expected_bytes); |
| 198 | + |
| 199 | + // get to the high value |
| 200 | + for _ in 1..30 { |
| 201 | + bytes.push(0); |
| 202 | + } |
| 203 | + bytes.push(2); |
| 204 | + expected_bytes[1] = 2; |
205 | 205 | assert_eq!(bytes.bytes, expected_bytes); |
206 | 206 | } |
207 | 207 |
|
@@ -283,7 +283,7 @@ mod digit_bytes_test { |
283 | 283 | for _ in 0..50 { |
284 | 284 | a.push(0); |
285 | 285 | } |
286 | | - assert!(a.full); |
| 286 | + assert!(a.high); |
287 | 287 |
|
288 | 288 | // make sure an instance filled with zero is not equal to an empty one |
289 | 289 | let b = DigitBytes::new(); |
|
0 commit comments