Skip to content

Commit 16fdd73

Browse files
committed
Faster approach using custom modulo function
1 parent 7c0973f commit 16fdd73

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ Performance is reasonable even on older hardware, for example a 2011 MacBook Pro
313313
| 12 | [Digital Plumber](https://adventofcode.com/2017/day/12) | [Source](src/year2017/day12.rs) | 61 |
314314
| 13 | [Packet Scanners](https://adventofcode.com/2017/day/13) | [Source](src/year2017/day13.rs) | 1 |
315315
| 14 | [Disk Defragmentation](https://adventofcode.com/2017/day/14) | [Source](src/year2017/day14.rs) | 438 |
316-
| 15 | [Dueling Generators](https://adventofcode.com/2017/day/15) | [Source](src/year2017/day15.rs) | 26000 |
316+
| 15 | [Dueling Generators](https://adventofcode.com/2017/day/15) | [Source](src/year2017/day15.rs) | 20000 |
317317
| 16 | [Permutation Promenade](https://adventofcode.com/2017/day/16) | [Source](src/year2017/day16.rs) | 68 |
318318
| 17 | [Spinlock](https://adventofcode.com/2017/day/17) | [Source](src/year2017/day17.rs) | 85 |
319319
| 18 | [Duet](https://adventofcode.com/2017/day/18) | [Source](src/year2017/day18.rs) | 7 |

src/year2017/day15.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
1414
use std::sync::mpsc::{Receiver, Sender, channel};
1515
use std::thread;
1616

17+
const MOD: usize = 0x7fffffff;
1718
const PART_ONE: usize = 40_000_000;
1819
const PART_TWO: usize = 5_000_000;
1920
const BLOCK: usize = 50_000;
@@ -63,8 +64,8 @@ fn sender(shared: &Shared, tx: &Sender<Block>) {
6364
while !shared.done.load(Ordering::Relaxed) {
6465
// Start at any point in the sequence using modular exponentiation.
6566
let start = shared.start.fetch_add(BLOCK, Ordering::Relaxed);
66-
let mut first = shared.first * 16807.mod_pow(start, 0x7fffffff);
67-
let mut second = shared.second * 48271.mod_pow(start, 0x7fffffff);
67+
let mut first = shared.first * 16807.mod_pow(start, MOD);
68+
let mut second = shared.second * 48271.mod_pow(start, MOD);
6869

6970
// Estimate capacity at one quarter or one eight, plus a little extra for variance.
7071
let mut ones = 0;
@@ -73,8 +74,8 @@ fn sender(shared: &Shared, tx: &Sender<Block>) {
7374

7475
// Check part one pairs immediately while queueing part two pairs.
7576
for _ in 0..BLOCK {
76-
first = (first * 16807) % 0x7fffffff;
77-
second = (second * 48271) % 0x7fffffff;
77+
first = fast_mod(first * 16807);
78+
second = fast_mod(second * 48271);
7879

7980
let left = first as u16;
8081
let right = second as u16;
@@ -167,3 +168,11 @@ fn receiver(shared: &Shared, rx: &Receiver<Block>) -> (u32, u32) {
167168
let part_one = blocks.iter().take(PART_ONE / BLOCK).map(|p| p.ones).sum();
168169
(part_one, part_two)
169170
}
171+
172+
#[inline]
173+
fn fast_mod(n: usize) -> usize {
174+
let low = n & MOD;
175+
let high = n >> 31;
176+
let sum = low + high;
177+
if sum < MOD { sum } else { sum - MOD }
178+
}

0 commit comments

Comments
 (0)