Skip to content

Commit

Permalink
refactor: abstractions
Browse files Browse the repository at this point in the history
  • Loading branch information
moliva committed Nov 18, 2023
1 parent 44b8c00 commit 1bdf706
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 110 deletions.
123 changes: 123 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
const EMPTY_CHAR: &str = "░";
const FULL_CHAR: &str = "▓";

#[derive(Debug)]
pub enum Stamp {
Point,
Block,
Oscillator,
Glider,
}

pub struct Grid<const N: usize, const M: usize> {
grid: [[bool; N]; M],
}

impl<const N: usize, const M: usize> Grid<N, M> {
pub fn sized() -> Self {
let grid = [[false; N]; M];

Self::new(grid)
}
pub fn new(grid: [[bool; N]; M]) -> Self {
Self { grid }
}

pub fn print(&self) {
for row in self.grid.iter() {
for &cell in row.iter() {
print!("{}", if cell { FULL_CHAR } else { EMPTY_CHAR })
}
println!();
}
}

/**
* 1. Any live cell with fewer than two live neighbours dies, as if by underpopulation.
* 2. Any live cell with two or three live neighbours lives on to the next generation.
* 3. Any live cell with more than three live neighbours dies, as if by overpopulation.
* 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
*/
pub fn tick(&mut self) {
let mut new_grid = [[false; N]; M];

for (i, row) in self.grid.iter().enumerate() {
for (j, &cell) in row.iter().enumerate() {
let n = self.live_neighbors_around(i, j);

// only set to true when conditions met for life to appear/persist
if (cell && n == 2) || n == 3 {
new_grid[i][j] = true;
}
}
}

self.grid = new_grid;
}

pub fn stamp(&mut self, stamp: Stamp, initial_position: (usize, usize)) {
use Stamp::*;

let (xi, yi) = initial_position;
match stamp {
Point => {
self.grid[xi][yi] = true;
}
Block => {
self.grid[xi][yi] = true;
self.grid[xi][yi + 1] = true;
self.grid[xi + 1][yi] = true;
self.grid[xi + 1][yi + 1] = true;
}
Oscillator => {
self.grid[xi][yi] = true;
self.grid[xi][yi + 1] = true;
self.grid[xi][yi + 2] = true;
}
Glider => {
self.grid[xi][yi] = true;
self.grid[xi + 1][yi + 1] = true;
self.grid[xi + 1][yi + 2] = true;
self.grid[xi + 2][yi] = true;
self.grid[xi + 2][yi + 1] = true;
}
}
}

fn live_neighbors_around(&self, i: usize, j: usize) -> usize {
let mut live_neighbors = 0;

if i > 0 {
if j > 0 && self.grid[i - 1][j - 1] {
live_neighbors += 1;
}
if self.grid[i - 1][j] {
live_neighbors += 1;
}
if j < N - 1 && self.grid[i - 1][j + 1] {
live_neighbors += 1;
}
}

if j > 0 && self.grid[i][j - 1] {
live_neighbors += 1;
}
if j < N - 1 && self.grid[i][j + 1] {
live_neighbors += 1;
}

if i < M - 1 {
if j > 0 && self.grid[i + 1][j - 1] {
live_neighbors += 1;
}
if self.grid[i + 1][j] {
live_neighbors += 1;
}
if j < N - 1 && self.grid[i + 1][j + 1] {
live_neighbors += 1;
}
}

live_neighbors
}
}
118 changes: 8 additions & 110 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const COL_SIZE: usize = 20;
const ROW_SIZE: usize = 10;
use conway_rs::{Grid, Stamp};

const EMPTY_CHAR: &str = "░";
const FULL_CHAR: &str = "▓";
const COL_SIZE: usize = 100;
const ROW_SIZE: usize = 18;

/**
* The universe of the Game of Life is an infinite, two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead (or populated and unpopulated, respectively). Every cell interacts with its eight neighbours, which are the cells that are horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:
Expand All @@ -15,33 +14,13 @@ const FULL_CHAR: &str = "▓";
* The initial pattern constitutes the seed of the system. The first generation is created by applying the above rules simultaneously to every cell in the seed, live or dead; births and deaths occur simultaneously, and the discrete moment at which this happens is sometimes called a tick.[nb 1] Each generation is a pure function of the preceding one. The rules continue to be applied repeatedly to create further generations.
*/
fn main() {
println!("Hello, world!");

let mut grid = [[false; COL_SIZE]; ROW_SIZE];
let mut grid = Grid::<COL_SIZE, ROW_SIZE>::sized();

// set live cells
// block
grid[5][5] = true;
grid[4][5] = true;
grid[5][4] = true;
grid[4][4] = true;

// alone
grid[9][0] = true;

// oscillator
grid[8][7] = true;
grid[8][8] = true;
grid[8][9] = true;

// glider
grid[0][7] = true;
grid[1][8] = true;
grid[1][9] = true;
grid[2][7] = true;
grid[2][8] = true;

let mut grid = Grid::new(grid);
grid.stamp(Stamp::Point, (9, 0));
grid.stamp(Stamp::Block, (4, 4));
grid.stamp(Stamp::Oscillator, (8, 7));
grid.stamp(Stamp::Glider, (0, 7));

for i in 0.. {
println!("tick {}", i);
Expand All @@ -52,84 +31,3 @@ fn main() {
let _ = std::io::stdin().read(&mut [0u8]).unwrap();
}
}

pub struct Grid<const N: usize, const M: usize> {
grid: [[bool; N]; M],
}

impl<const N: usize, const M: usize> Grid<N, M> {
pub fn new(grid: [[bool; N]; M]) -> Self {
Self {
grid,
}
}

pub fn print(&self) {
for row in self.grid.iter() {
for &cell in row.iter() {
print!("{}", if cell { FULL_CHAR } else { EMPTY_CHAR })
}
println!();
}
}

/**
* 1. Any live cell with fewer than two live neighbours dies, as if by underpopulation.
* 2. Any live cell with two or three live neighbours lives on to the next generation.
* 3. Any live cell with more than three live neighbours dies, as if by overpopulation.
* 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
*/
pub fn tick(&mut self) {
let mut new_grid = [[false; N]; M];

for (i, row) in self.grid.iter().enumerate() {
for (j, &cell) in row.iter().enumerate() {
let n = self.live_neighbors_around(i, j);

// only set to true when conditions met for life to appear/persist
if (cell && n == 2) || n == 3 {
new_grid[i][j] = true;
}
}
}

self.grid = new_grid;
}

fn live_neighbors_around(&self, i: usize, j: usize) -> usize {
let mut live_neighbors = 0;

if i > 0 {
if j > 0 && self.grid[i - 1][j - 1] {
live_neighbors += 1;
}
if self.grid[i - 1][j] {
live_neighbors += 1;
}
if j < N - 1 && self.grid[i - 1][j + 1] {
live_neighbors += 1;
}
}

if j > 0 && self.grid[i][j - 1] {
live_neighbors += 1;
}
if j < N - 1 && self.grid[i][j + 1] {
live_neighbors += 1;
}

if i < M - 1 {
if j > 0 && self.grid[i + 1][j - 1] {
live_neighbors += 1;
}
if self.grid[i + 1][j] {
live_neighbors += 1;
}
if j < N - 1 && self.grid[i + 1][j + 1] {
live_neighbors += 1;
}
}

live_neighbors
}
}

0 comments on commit 1bdf706

Please sign in to comment.