research-arrays.rs

2.5 kB · rust · 88 lines

1use figures::board::Frame;2use figures::{ink, save, Board, Grid};3use mrlyrs::core::error::Result;4use std::collections::HashSet;56const G: [i64; 4] = [0, 1, 2, 4];7const ORDER: u32 = 4;8const PX: f64 = 20.0;910fn coarray(s: &[i64]) -> HashSet<i64> {11    s.iter()12        .flat_map(|x| s.iter().map(move |y| x - y))13        .collect()14}1516fn paired(g: &[i64]) -> Vec<i64> {17    g.iter()18        .copied()19        .filter(|&x| {20            g.iter().any(|&y| {21                y != x22                    && g.iter()23                        .flat_map(|p| g.iter().map(move |q| p - q))24                        .filter(|&d| d == x - y)25                        .count()26                        == 127            })28        })29        .collect()30}3132fn main() -> Result<()> {33    let a = *G.iter().max().unwrap();34    let base = 2 * a + 1;35    assert_eq!(coarray(&G).len() as i64, base);36    let digits: Vec<Vec<i64>> = (0..G.len().pow(ORDER))37        .map(|mut k| {38            (0..ORDER)39                .map(|_| {40                    let d = G[k % G.len()];41                    k /= G.len();42                    d43                })44                .collect()45        })46        .collect();47    let sensors: Vec<i64> = digits48        .iter()49        .map(|d| d.iter().rev().fold(0, |acc, &x| acc * base + x))50        .collect();51    let full = coarray(&sensors);52    assert_eq!(full.len() as i64, base.pow(ORDER));53    let essential: Vec<bool> = sensors54        .iter()55        .map(|&s| {56            let rest: Vec<i64> = sensors.iter().copied().filter(|&x| x != s).collect();57            coarray(&rest) != full58        })59        .collect();60    let u = paired(&G);61    assert_eq!(u, vec![0, 1, 4]);62    for (d, &e) in digits.iter().zip(&essential) {63        assert_eq!(e, d.iter().all(|x| u.contains(x)));64    }65    assert_eq!(essential.iter().filter(|&&e| e).count(), u.len().pow(ORDER));66    let side = (a + base * a + 1) as usize;67    let mut board = Board::square();68    let edge = side as f64 * PX;69    let area = Frame::new(70        ((board.width as f64 - edge) / 2.0).round(),71        ((board.height as f64 - edge) / 2.0).round(),72        edge,73        edge,74    );75    let grid = Grid::new(area, side, side, 0.16);76    for (d, &e) in digits.iter().zip(&essential) {77        let col = (d[0] + base * d[2]) as usize;78        let row = side - 1 - (d[1] + base * d[3]) as usize;79        grid.fill(80            &mut board,81            col,82            row,83            if e { ink::orange() } else { ink::blue() },84        );85    }86    save("research-arrays", &board)?;87    Ok(())88}