brute.rs

2.2 kB · rust · 74 lines

1use std::sync::atomic::{AtomicUsize, Ordering};23use crate::design::Design;45// GCD67fn gcd(mut a: u64, mut b: u64) -> u64 {8    while b != 0 {9        let rest = a % b;10        a = b;11        b = rest;12    }13    a14}1516fn walk(depth: u32, coords: &mut Vec<u64>, corners: &[Vec<u64>], found: &mut u64) {17    if depth == 0 {18        let mut common = coords[0];19        for value in coords.iter().skip(1) {20            common = gcd(common, *value);21        }22        if common == 1 {23            *found += 1;24        }25        return;26    }27    for corner in corners.iter() {28        for (slot, digit) in coords.iter_mut().zip(corner.iter()) {29            *slot = *slot * 3 + digit;30        }31        walk(depth - 1, coords, corners, found);32        for (slot, digit) in coords.iter_mut().zip(corner.iter()) {33            *slot = (*slot - digit) / 3;34        }35    }36}3738pub fn count(design: &Design, level: u32, threads: usize) -> u64 {39    let corners = design.corners();40    if level < 2 {41        let mut coords = vec![0u64; design.dimension];42        let mut found = 0u64;43        walk(level, &mut coords, &corners, &mut found);44        return found;45    }46    let fill = corners.len();47    let cursor = AtomicUsize::new(0);48    std::thread::scope(|scope| {49        let mut handles = Vec::new();50        for _ in 0..threads {51            let cursor = &cursor;52            let corners = &corners;53            handles.push(scope.spawn(move || {54                let mut found = 0u64;55                loop {56                    let task = cursor.fetch_add(1, Ordering::Relaxed);57                    if task >= fill * fill {58                        break;59                    }60                    let first = &corners[task / fill];61                    let second = &corners[task % fill];62                    let mut coords: Vec<u64> = first63                        .iter()64                        .zip(second.iter())65                        .map(|(a, b)| a * 3 + b)66                        .collect();67                    walk(level - 2, &mut coords, corners, &mut found);68                }69                found70            }));71        }72        handles.into_iter().map(|h| h.join().unwrap()).sum()73    })74}