Skip to content

Instantly share code, notes, and snippets.

@TomBebbington
Created June 20, 2014 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TomBebbington/bebbf6f8b9a283b96910 to your computer and use it in GitHub Desktop.
Save TomBebbington/bebbf6f8b9a283b96910 to your computer and use it in GitHub Desktop.
Optimised Rust magic forest
extern crate test;
use std::vec::Vec;
use std::cmp::Ord;
use std::os;
use std::from_str::from_str;
use std::fmt::{Show, Formatter, Result};
use test::Bencher;
#[deriving(Clone, Eq, PartialEq, PartialOrd, Ord)]
struct Forest {
goats: i32,
wolves: i32,
lions: i32
}
impl Forest {
pub fn is_stable(&self) -> bool {
if self.goats == 0 {
(self.wolves == 0) || (self.lions == 0)
} else {
(self.wolves == 0) && (self.lions == 0)
}
}
#[inline]
pub fn is_invalid(&self) -> bool {
self.goats < 0 || self.wolves < 0 || self.lions < 0
}
pub fn find_stable(&self) -> Vec<Forest> {
let mut forests = vec!(*self);
while forests.is_devouring_possible() {
forests.meal();
}
forests.get_stable()
}
}
impl Show for Forest {
fn fmt(&self, f:&mut Formatter) -> Result {
write!(f, "Forest [goats= {}, wolves= {}, lions= {}]", self.goats, self.lions, self.wolves)
}
}
trait Forests {
fn is_devouring_possible(&self) -> bool;
fn meal(&mut self) -> ();
fn get_stable(&self) -> Vec<Forest>;
}
impl Forests for Vec<Forest> {
#[inline]
fn is_devouring_possible(&self) -> bool {
!(self.len() < 1) && !(self.iter().any(|x| x.is_stable()))
}
fn meal(&mut self) -> () {
let mut mealed_forests = Vec::with_capacity(self.len() * 3);
for x in self.iter() {
mealed_forests.push(Forest {
goats : x.goats - 1,
wolves : x.wolves - 1,
lions: x.lions + 1
});
mealed_forests.push(Forest {
goats : x.goats - 1,
wolves : x.wolves + 1,
lions: x.lions - 1
});
mealed_forests.push(Forest {
goats : x.goats + 1,
wolves : x.wolves - 1,
lions: x.lions - 1
});
}
let (_, mut mealed_forests) = mealed_forests.partition(|a| a.is_invalid() );
mealed_forests.sort_by(|a, b| a.cmp(b));
mealed_forests.dedup();
*self = mealed_forests;
}
fn get_stable(&self) -> Vec<Forest> {
self.iter().filter_map(|forest|
if forest.is_stable() {
Some(*forest)
} else {
None
}
).collect()
}
}
fn main() {
let args = os::args();
let args:Vec<i32> = args.tail().iter().map(|s| {
from_str(s.as_slice()).expect("arguments should be int")
}).collect();
if args.len() != 3 {
fail!("input should be in the form of <goats> <wolves> <lions>");
}
let inital_forest = Forest {
goats: *args.get(0),
wolves: *args.get(1),
lions: *args.get(2)
};
let stable_forests = inital_forest.find_stable();
if stable_forests.len() < 1 {
fail!("no stable forests found");
}
println!("{}", stable_forests);
}
#[bench]
fn bench_20_forests(b: &mut Bencher) {
let forests = Vec::from_fn(20, |n| Forest {
goats: n as i32,
wolves: n as i32,
lions: n as i32
});
b.iter(|| {
for forest in forests.iter() {
let stable_forests = forest.find_stable();
if stable_forests.len() < 1 {
fail!("no stable forests found");
}
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment