#![allow(dead_code)]
use std::boxed::Box;
use std::cell::RefCell;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::rc::Rc;
use std::rc::Weak;
pub mod cellular_process;
#[macro_use]
pub mod util;
pub type Printer = Fn(&str) -> ();
pub type Reader = Fn() -> String;
pub trait CellularAutomata<
'a,
CellDataType: Clone + 'static + util::Newable + util::Parseable + util::Encodeable + Debug,
MetaDataType: Clone + 'static + util::Newable + util::Parseable + cellular_process::GridMeta,
>
{
fn run(&self, _: &'a str) -> ();
fn input_handler(
_: &mut cellular_process::Grid<CellDataType, MetaDataType>,
_: &Reader,
_: &Printer,
) -> ();
fn output_handler(_: &cellular_process::Grid<CellDataType, MetaDataType>, _: &Printer) -> ();
}
#[derive(Clone)]
pub struct DummyMetaData {}
#[derive(Clone, Debug, PartialEq)]
pub enum AdaptiveTransitionFunctionMapNode {
TempLink(Vec<Option<Rc<RefCell<AdaptiveTransitionFunctionMapNode>>>>), End(util::UsizeWrapper), Link(Vec<Option<Box<AdaptiveTransitionFunctionMapNode>>>), }
#[derive(Clone, Debug)]
pub struct AdaptiveTransitionFunction {
matrix: AdaptiveTransitionFunctionMatrix,
}
#[derive(Clone, Debug, PartialEq)]
pub enum AdaptiveNeighborParserNode {
Relative(Vec<isize>),
Absolute(Vec<usize>),
}
#[derive(Clone, Debug)]
pub struct AdaptiveTransitionFunctionMatrix {
matrix: Vec<Option<util::UsizeWrapper>>,
dimensions: Vec<usize>,
}
#[derive(Clone, Debug)]
pub struct AdaptiveNeighborParser {
addr_matrix: Vec<AdaptiveNeighborParserNode>,
edge_val: util::UsizeWrapper,
}
#[derive(Clone, Debug)]
pub struct AdaptiveMetaData {
dimensions: Vec<usize>,
transition: AdaptiveTransitionFunction,
neighbor_parser: AdaptiveNeighborParser,
}
#[derive(Clone)]
pub struct AdaptiveCellularAutomata<'a> {
meta: AdaptiveMetaData,
initial: Vec<util::UsizeWrapper>,
phantom: PhantomData<&'a str>,
}
impl util::Parseable for AdaptiveTransitionFunctionMapNode {
fn parse(input: &str) -> Self {
let to_return = Self::temp_link();
let input_as_string = input.to_string();
let split_input: Vec<&str> = input_as_string.split(',').collect();
let tokens: Vec<Vec<util::UsizeWrapper>> = {
let mut to_return: Vec<Vec<util::UsizeWrapper>> = Vec::new();
let dimension_count = split_input[0].split(' ').count() - 1;
to_return.resize(dimension_count + 1, Vec::new());
for (indx1, j) in split_input.iter().enumerate() {
let tmp: Vec<&str> = j.split(' ').collect();
for item in tmp {
to_return[indx1].push(util::Parseable::parse(item));
}
}
to_return
};
if split_input.is_empty() {
panic!("ERROR - error reading transition function symbol table - table is empty");
}
let num_dimensions = split_input[0].split(' ').count() - 1;
for j in split_input {
let tokens: Vec<&str> = j.split(' ').collect();
if (tokens.len() - 1) != num_dimensions {
panic!("ERROR - missing or extra dimension");
}
}
let to_return_rc = Rc::new(RefCell::new(to_return));
let mut old_cell_weak_ptr: Weak<RefCell<Self>> = Rc::downgrade(&to_return_rc);
for val_1 in tokens {
for (addr, val_2) in val_1.iter().enumerate() {
let current_ref_cell = {
if addr == num_dimensions {
RefCell::new(AdaptiveTransitionFunctionMapNode::End(val_2.clone()))
} else {
RefCell::new(Self::temp_link())
}
};
let node: Rc<RefCell<Self>> = Rc::new(current_ref_cell);
let tmp = {
if addr == 0 {
Rc::new(RefCell::new(Self::temp_link())) } else if let Some(a) = old_cell_weak_ptr.upgrade() {
a
} else {
panic!("Cannot borrow last processed node as mutable");
}
};
let mut data = {
if addr == 0 {
if let Ok(d) = to_return_rc.try_borrow_mut() {
d
} else {
panic!("Cannot borrow last processed node as mutable");
}
} else if let Ok(a) = tmp.try_borrow_mut() {
a
} else {
panic!("Cannot borrow last processed node as mutable");
}
};
old_cell_weak_ptr = data.add_link(&Some(val_2.clone()), Some(node));
}
}
Self::solidify(
{
if let Ok(a) = Rc::try_unwrap(to_return_rc) {
a
} else {
panic!("Cannot unwrap to_return_Rc");
}
}
.into_inner(),
)
}
}
impl AdaptiveTransitionFunction {
#[inline]
pub fn apply(
data: &mut util::UsizeWrapper,
neighbor: &cellular_process::NeighborType<util::UsizeWrapper>,
meta: &AdaptiveMetaData,
) {
*data = meta
.get_transition_function()
.get_matrix()
.follow_path(neighbor.get_data().as_slice());
}
#[inline]
pub fn get_matrix(&self) -> &AdaptiveTransitionFunctionMatrix {
&self.matrix
}
}
impl util::Parseable for AdaptiveTransitionFunction {
fn parse(input: &str) -> Self {
Self {
matrix: util::Parseable::parse(input),
}
}
}
impl util::Newable for AdaptiveTransitionFunction {
fn new() -> Self {
Self {
matrix: util::Newable::new(),
}
}
}
impl util::Newable for AdaptiveTransitionFunctionMapNode {
fn new() -> Self {
Self::temp_link()
}
}
impl AdaptiveTransitionFunctionMapNode {
fn solidify(self) -> Self {
match self {
AdaptiveTransitionFunctionMapNode::TempLink(mut the_vec) => {
let mut tmp: Vec<Option<Box<Self>>> = Vec::new();
for dat in &mut the_vec {
tmp.push(if let Some(a) = dat.take() {
let to_solidify: Self = {
if let Ok(d) = Rc::try_unwrap(a) {
d.into_inner()
} else {
panic!("Cannot unwrap Rc");
}
};
Some(Box::new(Self::solidify(to_solidify)))
} else {
None
});
}
AdaptiveTransitionFunctionMapNode::Link(tmp)
}
AdaptiveTransitionFunctionMapNode::End(val) => {
AdaptiveTransitionFunctionMapNode::End(val)
}
AdaptiveTransitionFunctionMapNode::Link(val) => {
AdaptiveTransitionFunctionMapNode::Link(val)
}
}
}
#[inline]
pub fn follow_path(&self, input: Vec<&util::UsizeWrapper>) -> util::UsizeWrapper {
let mut old = self;
for data in input {
old = old.next_node(data);
}
if let AdaptiveTransitionFunctionMapNode::End(dat) = old {
dat.clone()
} else {
panic!("Incorrect number of dimensions");
}
}
#[inline]
pub fn next_node(&self, value: &util::UsizeWrapper) -> &Self {
if let AdaptiveTransitionFunctionMapNode::Link(a) = self {
if let Some(d) = &a[value.get_data()].as_ref() {
d
} else {
panic!("No value associated with given key");
}
} else {
panic!("The type of node is incorrect");
}
}
pub fn get_end_data(&self) -> Result<util::UsizeWrapper, usize> {
if let AdaptiveTransitionFunctionMapNode::End(to_ret) = self {
Ok(to_ret.clone())
} else {
Err(0)
}
}
pub fn temp_link() -> Self {
AdaptiveTransitionFunctionMapNode::TempLink(Vec::new())
}
pub fn end(value: &util::UsizeWrapper) -> Self {
AdaptiveTransitionFunctionMapNode::End(value.clone())
}
pub fn link_links_to(&mut self, pointers: Vec<Option<Rc<RefCell<Self>>>>) {
*self = AdaptiveTransitionFunctionMapNode::TempLink(pointers);
}
pub fn link_link_to(
&mut self,
value: &Option<util::UsizeWrapper>,
pointer: Option<Rc<RefCell<Self>>>,
) -> Weak<RefCell<Self>> {
let mut to_return = Weak::new();
if let AdaptiveTransitionFunctionMapNode::TempLink(input_vector) = self {
let usize_value = {
if let Some(temp) = value.clone() {
temp.get_data()
} else {
panic!("Attempted to make a link with a \"none\" value as the key");
}
};
let mut is_end: bool = false;
let remade_pointer = if let Some(a) = pointer {
if let Ok(b) = Rc::try_unwrap(a) {
let inner = b.into_inner();
if let AdaptiveTransitionFunctionMapNode::End(c) = inner {
is_end = true;
Some(Rc::new(RefCell::new(
AdaptiveTransitionFunctionMapNode::End(c),
)))
} else if let AdaptiveTransitionFunctionMapNode::TempLink(c) = inner {
is_end = false;
Some(Rc::new(RefCell::new(
AdaptiveTransitionFunctionMapNode::TempLink(c),
)))
} else {
panic!("This shouldn't happen");
}
} else {
panic!("Cannot unwrap Rc");
}
} else {
None
};
if is_end {
*self = {
if let Some(a) = remade_pointer {
if let Ok(b) = Rc::try_unwrap(a) {
b.into_inner()
} else {
panic!("This shouldn't happen");
}
} else {
panic!("This shouldn't happen");
}
};
} else {
if input_vector.len() < usize_value {
let diff = usize_value - input_vector.len() + 1;
for _ in 0..diff {
input_vector.push(None);
}
}
if input_vector[usize_value] == None {
input_vector[usize_value] = remade_pointer;
}
if let Some(unwrapped) = &input_vector[usize_value] {
to_return = Rc::downgrade(&unwrapped);
}
*self = AdaptiveTransitionFunctionMapNode::TempLink(input_vector.to_vec());
}
} else {
panic!("Improper use of link_link_to function");
}
to_return
}
pub fn add_link(
&mut self,
value: &Option<util::UsizeWrapper>,
pointer: Option<Rc<RefCell<Self>>>,
) -> Weak<RefCell<Self>> {
let mut to_return;
if let AdaptiveTransitionFunctionMapNode::TempLink(_) = self {
to_return = self.link_link_to(&value, pointer);
} else {
panic!("A link can only be added to a link node");
}
to_return
}
}
impl AdaptiveNeighborParser {
#[inline]
pub fn neighbor_func_parser<'b>(
grid: &'b cellular_process::GridDataType<util::UsizeWrapper>,
meta: &'b AdaptiveMetaData,
address: usize,
) -> cellular_process::NeighborType<'b, util::UsizeWrapper> {
let tmp = meta.get_neighbor_parser();
tmp.apply_neighbors(grid, meta, address)
}
#[inline]
pub fn apply_neighbors<'b>(
&'b self,
grid: &'b cellular_process::GridDataType<util::UsizeWrapper>,
meta: &'b AdaptiveMetaData,
address: usize,
) -> cellular_process::NeighborType<'b, util::UsizeWrapper> {
let dimensions = cellular_process::GridMeta::get_dimensions(meta);
let table = &self.addr_matrix;
let mut to_ret: Vec<&'b util::UsizeWrapper> = Vec::new();
for item in table {
if let AdaptiveNeighborParserNode::Absolute(the_vec) = item {
to_ret.push(util::access_flattened_vec(
grid.get_data_ref(),
&(the_vec.iter().map(|&x| x as isize).collect::<Vec<isize>>()),
&dimensions.to_vec(),
0,
&self.edge_val,
))
} else if let AdaptiveNeighborParserNode::Relative(the_vec) = item {
to_ret.push(util::access_flattened_vec(
grid.get_data_ref(),
&the_vec,
&dimensions.to_vec(),
address,
&self.edge_val,
))
} else {
panic!("This shouldn't happen");
}
}
cellular_process::NeighborType::new(to_ret, dimensions)
}
}
impl util::Newable for AdaptiveNeighborParser {
fn new() -> Self {
Self {
addr_matrix: Vec::new(),
edge_val: util::UsizeWrapper::from(0),
}
}
}
impl util::Parseable for AdaptiveNeighborParser {
fn parse(input: &str) -> Self {
let mut split = input.split(',');
let mut temp_vec: Vec<AdaptiveNeighborParserNode> = Vec::new();
let edge_case: util::UsizeWrapper = {
let cached = split.next().unwrap();
if cached.starts_with('e') {
util::Parseable::parse(&cached[1..cached.len()])
} else {
panic!("Symbol table is invalid");
}
};
for item in split {
temp_vec.push(util::Parseable::parse(item));
}
Self {
addr_matrix: temp_vec,
edge_val: edge_case,
}
}
}
impl util::Parseable for AdaptiveNeighborParserNode {
fn parse(input: &str) -> Self {
let collected: Vec<char> = input.chars().collect::<Vec<char>>();
if collected.len() <= 1 {
panic!("Node is invalid");
}
let discrim: char = {
if let Some(d) = collected[0].to_lowercase().nth(0) {
d
} else {
panic!("Character has no lowercase version");
}
};
let the_string = input[1..input.len()].to_string();
let tokenized = {
let tmp = the_string.split(' ');
let mut to_return: Vec<isize> = Vec::new();
for item in tmp {
to_return.push(if let Ok(a) = item.parse::<isize>() {
a
} else {
panic!("Position index is not an integer");
});
}
to_return
};
if discrim == 'a' {
AdaptiveNeighborParserNode::Absolute(
tokenized
.iter()
.map(|x| *x as usize)
.collect::<Vec<usize>>(),
)
} else if discrim == 'r' {
AdaptiveNeighborParserNode::Relative(
tokenized
.iter()
.map(|&x| x as isize)
.collect::<Vec<isize>>(),
)
} else {
panic!("Discriminator is invalid");
}
}
}
impl util::Newable for DummyMetaData {
fn new() -> Self {
Self {}
}
}
impl util::Parseable for DummyMetaData {
fn parse(_data: &str) -> Self {
util::Newable::new()
}
}
impl util::Encodeable for DummyMetaData {
fn encode(&self) -> String {
String::new()
}
}
impl AdaptiveMetaData {
#[inline(always)]
pub fn get_neighbor_parser(&self) -> &AdaptiveNeighborParser {
&self.neighbor_parser
}
#[inline(always)]
pub fn get_transition_function(&self) -> &AdaptiveTransitionFunction {
&self.transition
}
}
impl cellular_process::GridMeta for AdaptiveMetaData {
fn get_dimensions(&self) -> &[usize] {
self.dimensions.as_slice()
}
}
impl util::Parseable for AdaptiveMetaData {
fn parse(input: &str) -> Self {
let split = util::parse_table_sections(input);
if split.len() != 3 {
panic!("Malformed metadata table");
}
Self {
dimensions: util::parse_csv_list_native(&split[0], ','),
neighbor_parser: util::Parseable::parse(&split[1]),
transition: util::Parseable::parse(&split[2]),
}
}
}
impl util::Newable for AdaptiveMetaData {
fn new() -> Self {
Self {
dimensions: Vec::new(),
neighbor_parser: util::Newable::new(),
transition: util::Newable::new(),
}
}
}
impl<'a> util::Parseable for AdaptiveCellularAutomata<'a> {
fn parse(input: &str) -> Self {
let split = util::parse_table_sections(input);
if split.len() != 2 {
panic!("Malformed metadata table")
}
let parsed = util::parse_csv_list(&split[1], ',');
AdaptiveCellularAutomata {
phantom: PhantomData,
meta: util::Parseable::parse(&split[0]),
initial: parsed,
}
}
}
impl<'a> AdaptiveCellularAutomata<'a> {
pub fn test_1() {
let neighbor_str = "e2,a1 1";
let parser_str = "1 2";
let data_str = "1,1,1";
let dim_str = "3,1";
let meta_str = util::encode_table_sections(&[
String::from(dim_str),
String::from(neighbor_str),
String::from(parser_str),
]);
let final_str = util::encode_table_sections(&[meta_str, String::from(data_str)]);
dbg!(&final_str);
let transition: &cellular_process::TransitionFunc<util::UsizeWrapper, AdaptiveMetaData> =
&AdaptiveTransitionFunction::apply;
let neighbor: &cellular_process::NeighborFuncParser<util::UsizeWrapper, AdaptiveMetaData> =
&AdaptiveNeighborParser::neighbor_func_parser;
let mut grid = cellular_process::Grid::<util::UsizeWrapper, AdaptiveMetaData>::decode(
final_str.as_str(),
);
let meta = grid.get_meta().clone();
grid.apply(transition, neighbor, &meta);
dbg!(grid.get_data_read()); }
fn get_meta_data(&self) -> &AdaptiveMetaData {
&self.meta
}
fn get_initial_state(&self) -> &Vec<util::UsizeWrapper> {
&self.initial
}
}
impl<'a> CellularAutomata<'a, util::UsizeWrapper, AdaptiveMetaData>
for AdaptiveCellularAutomata<'a>
{
fn input_handler(
_: &mut cellular_process::Grid<util::UsizeWrapper, AdaptiveMetaData>,
_: &Reader,
_: &Printer,
) {
}
fn output_handler(
_: &cellular_process::Grid<util::UsizeWrapper, AdaptiveMetaData>,
_: &Printer,
) {
}
fn run(&self, input: &str) {
let transition: &cellular_process::TransitionFunc<util::UsizeWrapper, AdaptiveMetaData> =
&AdaptiveTransitionFunction::apply;
let neighbor: &cellular_process::NeighborFuncParser<util::UsizeWrapper, AdaptiveMetaData> =
&AdaptiveNeighborParser::neighbor_func_parser;
let mut grid =
cellular_process::Grid::<util::UsizeWrapper, AdaptiveMetaData>::decode(input);
let meta = grid.get_meta().clone();
grid.apply(transition, neighbor, &meta);
dbg!(grid);
}
}
impl util::Newable for AdaptiveTransitionFunctionMatrix {
fn new() -> Self {
Self {
matrix: Vec::new(),
dimensions: Vec::new(),
}
}
}
impl util::Parseable for AdaptiveTransitionFunctionMatrix {
#[inline]
fn parse(input: &str) -> Self {
let mut to_return_vec: Vec<Option<util::UsizeWrapper>> = Vec::new();
let input_as_string = input.to_string();
let split_input: Vec<&str> = input_as_string.split(',').collect();
let tokens: Vec<Vec<usize>> = {
let mut to_return: Vec<Vec<usize>> = Vec::new();
let dimension_count = split_input[0].split(' ').count() - 1;
to_return.resize(dimension_count + 1, Vec::new());
for (indx1, j) in split_input.iter().enumerate() {
let tmp: Vec<&str> = j.split(' ').collect();
for item in tmp {
to_return[indx1].push({
if let Ok(a) = item.parse::<usize>() {
a
} else {
panic!("Not an integer");
}
});
}
}
to_return
};
if split_input.is_empty() {
panic!("ERROR - error reading transition function symbol table - table is empty");
}
let num_dimensions = split_input[0].split(' ').count() - 1;
for j in split_input {
let tokens: Vec<&str> = j.split(' ').collect();
if (tokens.len() - 1) != num_dimensions {
panic!("ERROR - missing or extra dimension");
}
}
let dimension_maxima: Vec<usize> = {
let mut to_return: Vec<Option<usize>> = Vec::new();
for _ in 0..num_dimensions {
to_return.push(None);
}
for item in &tokens {
for (dim, value) in item.iter().enumerate() {
if dim == num_dimensions {
} else if let Some(a) = to_return[dim] {
if value > &a {
to_return[dim] = Some(*value);
}
} else {
to_return[dim] = Some(*value);
}
}
}
let mut final_to_return: Vec<usize> = Vec::new();
for item in to_return {
if let Some(a) = item {
final_to_return.push(a);
} else {
panic!("Symbol table is invalid");
}
}
final_to_return
};
for _ in 0..util::addr_normal_to_flattened_usize(
&dimension_maxima,
&(dimension_maxima
.iter()
.map(|x| x + 1)
.collect::<Vec<usize>>()),
) {
to_return_vec.push(None);
}
for item in tokens {
to_return_vec[util::addr_normal_to_flattened_usize(
&item[0..item.len() - 1],
&dimension_maxima,
)] = Some(util::UsizeWrapper::from(item[item.len() - 1]));
}
Self {
matrix: to_return_vec,
dimensions: dimension_maxima,
}
}
}
impl AdaptiveTransitionFunctionMatrix {
#[inline]
pub fn follow_path(&self, path: &[&util::UsizeWrapper]) -> util::UsizeWrapper {
if let Some(a) = &self.matrix[util::addr_normal_to_flattened_usize(
&(path.iter().map(|x| x.get_data()).collect::<Vec<usize>>()),
&self.dimensions,
)] {
a.clone()
} else {
panic!("No value associated with given key");
}
}
}