Browse Source

added cycle finder

master
Thomas Johnson 6 months ago
parent
commit
be7de13a8b
  1. 30
      src/grid.rs
  2. 69
      src/main.rs

30
src/grid.rs

@ -11,6 +11,7 @@ pub const TILESIZE: usize = 1 << TILEBITS;
pub const TILEMASK: usize = TILESIZE - 1;
pub const TILEMASKI: isize = TILEMASK as isize;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Grid
{
tiles: HashMap<(isize, isize), RefCell<Tile>>,
@ -18,13 +19,14 @@ pub struct Grid
wrapy: Option<NonZeroUsize>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Tile
{
which: bool,
cells: [[Cell; TILESIZE]; TILESIZE],
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Cell
{
// Switch between which of the states we use.
@ -32,7 +34,7 @@ pub struct Cell
second: State,
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum State
{
Dead(),
@ -213,22 +215,22 @@ impl Grid
if highidx
{
fn idx_c_f(cells: &mut[[Cell; TILESIZE]; TILESIZE], i: usize) -> &mut Cell
{ &mut cells[TILESIZE - 1][i] };
{ &mut cells[TILESIZE - 1][i] }
fn idx_n_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[TILESIZE - 2][i] };
{ &cells[TILESIZE - 2][i] }
fn idx_f_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[0][i] };
{ &cells[0][i] }
idx_c = idx_c_f as fn(&mut[[Cell; TILESIZE]; TILESIZE], usize) -> &mut Cell;
idx_n = idx_n_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;
idx_f = idx_f_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;
} else
{
fn idx_c_f(cells: &mut[[Cell; TILESIZE]; TILESIZE], i: usize) -> &mut Cell
{ &mut cells[0][i] };
{ &mut cells[0][i] }
fn idx_n_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[1][i] };
{ &cells[1][i] }
fn idx_f_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[TILESIZE - 1][i] };
{ &cells[TILESIZE - 1][i] }
idx_c = idx_c_f as fn(&mut[[Cell; TILESIZE]; TILESIZE], usize) -> &mut Cell;
idx_n = idx_n_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;
idx_f = idx_f_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;
@ -238,22 +240,22 @@ impl Grid
if highidx
{
fn idx_c_f(cells: &mut[[Cell; TILESIZE]; TILESIZE], i: usize) -> &mut Cell
{ &mut cells[i][TILESIZE - 1] };
{ &mut cells[i][TILESIZE - 1] }
fn idx_n_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[i][TILESIZE - 2] };
{ &cells[i][TILESIZE - 2] }
fn idx_f_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[i][0] };
{ &cells[i][0] }
idx_c = idx_c_f as fn(&mut[[Cell; TILESIZE]; TILESIZE], usize) -> &mut Cell;
idx_n = idx_n_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;
idx_f = idx_f_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;
} else
{
fn idx_c_f(cells: &mut[[Cell; TILESIZE]; TILESIZE], i: usize) -> &mut Cell
{ &mut cells[i][0] };
{ &mut cells[i][0] }
fn idx_n_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[i][1] };
{ &cells[i][1] }
fn idx_f_f(cells: &[[Cell; TILESIZE]; TILESIZE], i: usize) -> &Cell
{ &cells[i][TILESIZE - 1] };
{ &cells[i][TILESIZE - 1] }
idx_c = idx_c_f as fn(&mut[[Cell; TILESIZE]; TILESIZE], usize) -> &mut Cell;
idx_n = idx_n_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;
idx_f = idx_f_f as fn(&[[Cell; TILESIZE]; TILESIZE], usize) -> &Cell;

69
src/main.rs

@ -1,5 +1,3 @@
#![feature(const_in_array_repeat_expressions)]
mod grid;
use crate::grid::{Grid, State, TILESIZE, TILEMASKI, TILEBITS};
@ -33,10 +31,11 @@ impl<'a> std::fmt::Display for Disp<'a>
fn main()
{
for _ii in 0 .. 1
for _ in 0 .. 1
{
//let mut grid = Grid::new_blank_wrapped(2, 2);
let mut grid = Grid::new_random(NonZeroUsize::new(2).unwrap(), NonZeroUsize::new(2).unwrap(), 0.5);
let (stability_steps, period) = find_first_oscillation(&mut grid, &[false, false, false, true, false, false, false, false, false], &[true, true, false, false, true, true, true, true, true]);
//grid.set(15, 50, State::Alive());
//grid.set(50, 50, State::Alive());
@ -106,15 +105,15 @@ fn main()
//grid.set(5, 0, State::Alive());
//grid.set(6, 0, State::Alive());
let mut disp = format!("{}", Disp(&grid, (0, 1), (0, 1)));
for steps in 0..3000
{
println!("{}", steps);
print!("{}", disp);
let extents = grid.step(&[false, false, false, true, false, false, false, false, false], &[true, true, false, false, true, true, true, true, true], steps % TILESIZE == 0);
disp = format!("{}", Disp(&grid, extents.0, extents.1));
sleep(Duration::from_millis(1000 / 60));
}
// let mut disp = format!("{}", Disp(&grid, (0, 1), (0, 1)));
// for steps in 0..3000
// {
// println!("{}", steps);
// print!("{}", disp);
// let extents = grid.step(&[false, false, false, true, false, false, false, false, false], &[true, true, false, false, true, true, true, true, true], steps % TILESIZE == 0);
// disp = format!("{}", Disp(&grid, extents.0, extents.1));
// sleep(Duration::from_millis(1000 / 60));
// }
let mut count_off = 0;
let mut count_on = 0;
grid.per_tile(|_, t|
@ -131,8 +130,50 @@ fn main()
}
}
});
println!("cells off : {}", count_off);
println!("cells on : {}", count_on);
println!("took {stability_steps} steps to converge to a period of {period}");
println!("cells off : {count_off}");
println!("cells on : {count_on}");
println!("ratio on : {}", (count_on as f64) / (count_off + count_on) as f64);
}
}
fn find_first_oscillation(g: &mut Grid, on: &[bool; 9], off: &[bool; 9]) -> (usize, usize) {
let mut tortoise = g.clone();
let mut hare = g.clone();
let mut i = 0;
tortoise.step(on, off, i % TILESIZE == 0);
hare.step(on, off, false);
hare.step(on, off, i % TILESIZE == 0);
while hare != tortoise {
tortoise.step(on, off, i % TILESIZE == 0);
hare.step(on, off, false);
hare.step(on, off, i % TILESIZE == 0);
i += 1;
}
let mut next_occurrence = tortoise.clone();
let mut period = 1;
next_occurrence.step(on, off, (i + period) % TILESIZE == 0);
while tortoise != next_occurrence {
next_occurrence.step(on, off, (i + period) % TILESIZE == 0);
period += 1;
}
let mut leading = g.clone();
for i in 0..period {
leading.step(on, off, i % TILESIZE == 0);
}
let mut first_index = 0;
while *g != leading {
g.step(on, off, first_index % TILESIZE == 0);
leading.step(on, off, first_index % TILESIZE == 0);
first_index += 1;
}
(first_index, period)
}
Loading…
Cancel
Save