A => .gitignore +1 -0
A => Cargo.lock +83 -0
@@ 1,83 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "conway"
+version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
A => Cargo.toml +10 -0
@@ 1,10 @@
+[package]
+name = "conway"
+version = "0.1.0"
+authors = ["Andrew Thorp <andrew.thorp.dev@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+rand = "0.8.3"
A => src/conway/board.rs +103 -0
@@ 1,103 @@
+use rand::prelude::*;
+use std::fmt;
+
+use crate::conway::conway::{Cell, CellState, Coordinate, SimpleCell};
+
+pub struct Board {
+ width: usize,
+ height: usize,
+ cells: Vec<Vec<SimpleCell>>,
+}
+
+impl Board {
+ pub fn new(width: usize, height: usize) -> Self {
+ let mut cells: Vec<Vec<SimpleCell>> = Vec::with_capacity(height);
+
+ // Initialize vectors
+ for i in 0..height {
+ let mut row = Vec::with_capacity(width);
+ for j in 0..width {
+ row.push(SimpleCell::new(Coordinate::new(i as i32, j as i32)));
+ }
+ cells.push(row);
+ }
+
+ Board {
+ width,
+ height,
+ cells: cells,
+ }
+ }
+
+ pub fn get(&self, x: usize, y: usize) -> Option<SimpleCell> {
+ if x < self.width && x >= 0 && y < self.height && y >= 0 {
+ Some(self.cells[x][y].clone())
+ } else {
+ None
+ }
+ }
+
+ pub fn set(&mut self, x: usize, y: usize, state: CellState) {
+ self.cells[x][y].set_state(state);
+ }
+
+ pub fn step(&mut self) {
+ let mut cells = self.cells.clone();
+ let mut display = String::new();
+ for i in 0..cells.len() {
+ for j in 0..cells[i].len() {
+ let cell = cells[i][j].clone();
+ cells[i][j].set_state(self.next_cell_step(cell));
+ }
+ }
+ self.cells = cells;
+ }
+
+ fn next_cell_step(&self, cell: SimpleCell) -> CellState {
+ let adj = cell.get_adjecent();
+ let neighbors = self.get_cells(adj);
+ let live_neighbors = neighbors.iter().filter(|c| c.is_alive()).count();
+
+ // birth
+ if !cell.is_alive() && live_neighbors == 3 {
+ CellState::Alive
+ // Starvation
+ } else if cell.is_alive() && live_neighbors > 3 {
+ CellState::Dead
+ // Isolation
+ } else if cell.is_alive() && live_neighbors <= 1 {
+ CellState::Dead
+ // Survival
+ } else {
+ cell.state
+ }
+ }
+
+ fn get_cells(&self, coordinates: Vec<Coordinate>) -> Vec<SimpleCell> {
+ let mut cells = Vec::new();
+ for c in coordinates {
+ if let Some(cell) = self.get(c.x as usize, c.y as usize) {
+ cells.push(cell);
+ }
+ }
+ cells
+ }
+}
+
+impl fmt::Display for Board {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let cells = self.cells.clone();
+ let mut display = String::new();
+ for row in cells {
+ for cell in row {
+ if cell.is_alive() {
+ display.push_str("()");
+ } else {
+ display.push_str("__");
+ }
+ }
+ display.push('\n');
+ }
+ write!(f, "{}", display)
+ }
+}
A => src/conway/conway.rs +78 -0
@@ 1,78 @@
+use std::fmt;
+
+#[derive(Clone, Debug)]
+pub struct Coordinate {
+ pub x: i32,
+ pub y: i32,
+}
+
+impl Coordinate {
+ pub fn new(x: i32, y: i32) -> Self {
+ Coordinate { x: x, y: y }
+ }
+ pub fn calculate_adjecents(&self) -> Vec<Coordinate> {
+ let x_sub1 = self.x - 1;
+ let y_sub1 = self.y - 1;
+ let mut adj: Vec<Coordinate> = Vec::new();
+ for i in x_sub1..=x_sub1 + 2 {
+ for j in y_sub1..=y_sub1 + 2 {
+ if !(i == self.x && j == self.y) && i >= 0 && j >= 0 {
+ adj.push(Coordinate { x: i, y: j });
+ }
+ }
+ }
+ adj
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum CellState {
+ Dead,
+ Alive,
+}
+
+pub trait Cell {
+ fn new(location: Coordinate) -> Self;
+ fn is_alive(&self) -> bool;
+ fn set_state(&mut self, state: CellState);
+ fn get_adjecent(&self) -> Vec<Coordinate>;
+}
+
+#[derive(Clone, Debug)]
+pub struct SimpleCell {
+ pub state: CellState,
+ pub location: Coordinate,
+ adjecent: Vec<Coordinate>,
+}
+
+impl SimpleCell {}
+
+impl Cell for SimpleCell {
+ fn new(location: Coordinate) -> Self {
+ let adjecent = location.calculate_adjecents();
+ Self {
+ state: CellState::Dead,
+ location: location,
+ adjecent: adjecent,
+ }
+ }
+ fn is_alive(&self) -> bool {
+ self.state == CellState::Alive
+ }
+ fn set_state(&mut self, state: CellState) {
+ self.state = state;
+ }
+ fn get_adjecent(&self) -> Vec<Coordinate> {
+ self.adjecent.clone()
+ }
+}
+
+impl fmt::Display for SimpleCell {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "Cell ({}, {}): {:?}",
+ self.location.x, self.location.y, self.state
+ )
+ }
+}
A => src/conway/mod.rs +2 -0
@@ 1,2 @@
+pub mod board;
+pub mod conway;
A => src/main.rs +27 -0
@@ 1,27 @@
+use std::{thread, time};
+
+mod conway;
+
+use conway::board::Board;
+use conway::conway::CellState;
+
+fn sleep(time_ms: usize) {
+ let sleep_time = time::Duration::from_millis(time_ms as u64);
+ thread::sleep(sleep_time);
+}
+
+fn main() {
+ let mut b = Board::new(10, 10);
+
+ b.set(0, 0, CellState::Alive);
+ b.set(1, 1, CellState::Alive);
+ b.set(1, 2, CellState::Alive);
+ b.set(2, 0, CellState::Alive);
+ b.set(2, 1, CellState::Alive);
+
+ for i in 0..50 {
+ println!("Board:\n{}", b);
+ b.step();
+ sleep(100);
+ }
+}