Skip to content

Instantly share code, notes, and snippets.

@amcoder
Last active June 21, 2016 19:23
Show Gist options
  • Save amcoder/c78f997bcf17018dabab7d7cc1dae754 to your computer and use it in GitHub Desktop.
Save amcoder/c78f997bcf17018dabab7d7cc1dae754 to your computer and use it in GitHub Desktop.
Life
mod life {
use std::usize;
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Copy)]
#[derive(Clone)]
pub enum Cell {
Alive,
Dead,
}
#[derive(Debug)]
#[derive(PartialEq)]
pub enum Error {
ParseError,
}
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub struct World {
size: usize,
data: Vec<Cell>,
}
impl World {
pub fn new(size: usize) -> World {
World{size: size, data: vec![Cell::Dead; size * size]}
}
pub fn tick(&self) -> World {
let mut data = vec![Cell::Dead; self.size * self.size];
for i in 0..self.size {
for j in 0..self.size {
data[i * self.size + j] = self.tick_cell(i, j);
}
}
World{size: self.size, data: data}
}
fn tick_cell(&self, i: usize, j: usize) -> Cell {
match self.population_at(i, j) {
3 => Cell::Alive,
4 => self.data[i * self.size + j],
_ => Cell::Dead,
}
}
pub fn get(&self, i: usize, j: usize) -> Cell {
if i >= self.size || j >= self.size {
Cell::Dead
} else {
self.data[i * self.size + j]
}
}
fn population_at(&self, i: usize, j: usize) -> i32 {
let mut result = 0;
let min_i = i.checked_sub(1).unwrap_or(0);
let min_j = j.checked_sub(1).unwrap_or(0);
for i in min_i..i+2 {
for j in min_j..j+2 {
if self.get(i, j) == Cell::Alive {
result += 1;
}
}
}
result
}
}
impl ::std::str::FromStr for World {
type Err = Error;
fn from_str(s: &str) -> Result<World, Error> {
let size = s.lines().count();
if size == 0 || s.lines().nth(0).unwrap().len() != size {
return Err(Error::ParseError);
}
let mut data = vec![];
for line in s.lines() {
if line.len() != size {
return Err(Error::ParseError);
}
for c in line.chars() {
let state = match c {
'.' => Cell::Dead,
'*' => Cell::Alive,
_ => return Err(Error::ParseError),
};
data.push(state);
}
}
Ok(World{size: size, data: data})
}
}
impl ::std::fmt::Display for World {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
for i in 0..self.size {
let row = i * self.size;
let line: String = self.data[row..row + self.size].into_iter().
map(|c| {
match *c {
Cell::Dead => " ",
Cell::Alive => "()",
}
}).collect();
try!(write!(f, "{}\n", line));
}
Ok(())
}
}
pub struct WorldIterator {
world: World
}
impl<'a> IntoIterator for &'a World {
type Item = &'a World;
type IntoIter = WorldIterator;
fn into_iter(self) -> Self::IntoIter {
WorldIterator{world: self.clone()}
}
}
impl<'a> Iterator for WorldIterator {
type Item = &'a World;
fn next<'b>(&'b mut self) -> Option<Self::Item> {
// I realize this is wrong, but I don't know where to go from here.
let old = self.world;
self world = old.tick();
Some(old)
}
}
}
@amcoder
Copy link
Author

amcoder commented Jun 21, 2016

I'm trying to implement an iterator for the world, but I'm getting lifetime errors. I've been playing with lifetimes for a while and I get different variations on lifetime issues.

   Compiling conway v0.1.0 (file:///Users/amcoder/Projects/conway)
src/main.rs:133:10: 133:12 error: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates [E0207]
src/main.rs:133     impl<'a> Iterator for WorldIterator {
                         ^~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment