Skip to main content

inspect_grids/
inspect_grids.rs

1use brdb::{Brz, IntoReader};
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let path = PathBuf::from(
7        std::env::args()
8            .nth(1)
9            .unwrap_or_else(|| "world.brz".to_string()),
10    );
11    let db = Brz::open(path)?.into_reader();
12
13    let mut grid_ids = vec![1];
14    for index in db.entity_chunk_index()? {
15        for e in db.entity_chunk(index)? {
16            if e.is_brick_grid() || e.is_microchip_grid() {
17                if let Some(id) = e.id {
18                    grid_ids.push(id);
19                }
20            }
21        }
22    }
23
24    // For each grid, collect a fingerprint: (num_bricks, num_wires, num_chunks)
25    // to find grids that look identical.
26    let mut fingerprints: HashMap<(u64, u64, usize), Vec<usize>> = HashMap::new();
27    let mut total_bricks = 0u64;
28    let mut total_wires = 0u64;
29    let mut total_components = 0u64;
30
31    for &gid in &grid_ids {
32        let chunks = db.brick_chunk_index(gid)?;
33        let mut grid_bricks = 0u64;
34        let mut grid_wires = 0u64;
35        let mut grid_components = 0u64;
36        for chunk in &chunks {
37            grid_bricks += chunk.num_bricks as u64;
38            grid_wires += chunk.num_wires as u64;
39            grid_components += chunk.num_components as u64;
40        }
41        total_bricks += grid_bricks;
42        total_wires += grid_wires;
43        total_components += grid_components;
44
45        let fp = (grid_bricks, grid_wires, chunks.len());
46        fingerprints.entry(fp).or_default().push(gid);
47    }
48
49    println!("=== Grid Summary ===");
50    println!("total grids: {}", grid_ids.len());
51    println!("total bricks: {total_bricks}");
52    println!("total wires: {total_wires}");
53    println!("total components: {total_components}");
54    println!();
55
56    println!("=== Unique Grid Shapes ===");
57    let mut fps: Vec<_> = fingerprints.iter().collect();
58    fps.sort_by_key(|((b, _w, _), grids)| std::cmp::Reverse(*b * grids.len() as u64));
59
60    for ((bricks, wires, chunks), grids) in &fps {
61        let savings = if grids.len() > 1 {
62            format!(
63                " → {} could be deduplicated (save {} bricks, {} wires)",
64                grids.len() - 1,
65                bricks * (grids.len() as u64 - 1),
66                wires * (grids.len() as u64 - 1)
67            )
68        } else {
69            String::new()
70        };
71        println!(
72            "  {}×  ({} bricks, {} wires, {} chunks){}",
73            grids.len(),
74            bricks,
75            wires,
76            chunks,
77            savings
78        );
79    }
80
81    // Top 10 largest grids
82    println!();
83    println!("=== Top 10 Largest Grids ===");
84    let mut grid_sizes: Vec<(usize, u64, u64)> = Vec::new();
85    for &gid in &grid_ids {
86        let chunks = db.brick_chunk_index(gid)?;
87        let b: u64 = chunks.iter().map(|c| c.num_bricks as u64).sum();
88        let w: u64 = chunks.iter().map(|c| c.num_wires as u64).sum();
89        grid_sizes.push((gid, b, w));
90    }
91    grid_sizes.sort_by_key(|(_, b, _)| std::cmp::Reverse(*b));
92    for (gid, b, w) in grid_sizes.iter().take(10) {
93        println!("  grid {gid}: {b} bricks, {w} wires");
94    }
95
96    Ok(())
97}