use std::cmp::Ordering;
use crate::{DayanError, ExpressionTree};
use std::collections::BTreeMap;
use std::ops::{Add, Mul};
use std::vec;
use num_traits::{One, Zero};
mod arithmetic;
#[derive(Debug, Eq, PartialEq)]
pub enum DayanBeta {
Number(u32),
Beta(u32, Vec<DayanBeta>),
}
impl DayanBeta {
pub fn as_expression(&self) -> Result<ExpressionTree, DayanError> {
match self {
DayanBeta::Number(v) => Ok(ExpressionTree::Number(*v)),
DayanBeta::Beta(rank, p) => {
let group = same_group(p);
match *rank {
0 => {
match p.len() {
0 => Ok(ExpressionTree::Number(0)),
1 => p[0].as_expression(),
_ => Err(DayanError::too_much_argument("DayanBeta::Beta(0, _)", p.len()).with_min_argument(0).with_max_argument(1)),
}
},
1 => self.cast_add(group).map(|s| s.as_simplify()),
2 => self.cast_mul(group).map(|s| s.as_simplify()),
3 => self.cast_pow(group).map(|s| s.as_simplify()),
_ => panic!("DayanBeta::Beta(3, _) is not a valid expression"),
}
}
}
}
pub fn is_number(&self) -> bool {
matches!(self, DayanBeta::Number(_))
}
}
impl DayanBeta {
fn cast_add(&self, count: BTreeMap<&DayanBeta, u32>) -> Result<ExpressionTree, DayanError> {
let mut terms = vec![];
for (node, count) in count.into_iter().rev() {
terms.push(node.as_rank1()? * ExpressionTree::Number(count))
}
Ok(ExpressionTree::Sum { add: terms })
}
fn as_rank1(&self) -> Result<ExpressionTree, DayanError> {
match self {
DayanBeta::Number(1) => Ok(ExpressionTree::Number(1)),
DayanBeta::Number(_) => {
panic!()
}
DayanBeta::Beta(_, _) => self.as_expression(),
}
}
}
impl DayanBeta {
fn cast_mul(&self, count: BTreeMap<&DayanBeta, u32>) -> Result<ExpressionTree, DayanError> {
let mut terms = vec![];
for (node, count) in count.into_iter().rev() {
terms.push(node.as_rank2(count)?)
}
Ok(ExpressionTree::Product { mul: terms })
}
fn as_rank2(&self, count: u32) -> Result<ExpressionTree, DayanError> {
match self {
DayanBeta::Number(1) => {
Ok(ExpressionTree::Letter('ω') ^ ExpressionTree::Number(count))
},
DayanBeta::Number(2) => {
Ok(ExpressionTree::subscript('ε', count))
},
DayanBeta::Number(_) => {
panic!()
}
DayanBeta::Beta(_, _) => self.as_expression(),
}
}
}
impl DayanBeta {
fn cast_pow(&self, count: BTreeMap<&DayanBeta, u32>) -> Result<ExpressionTree, DayanError> {
let mut terms = vec![];
for (node, count) in count.into_iter().rev() {
terms.push(node.as_rank3(count, 1)?)
}
Ok(ExpressionTree::subscript('φ', ExpressionTree::Product { mul: terms }))
}
fn as_rank3(&self, count: u32, depth: u32) -> Result<ExpressionTree, DayanError> {
match self {
DayanBeta::Number(1) => {
todo!()
},
DayanBeta::Number(2) => {
todo!()
},
DayanBeta::Number(_) => {
panic!()
}
DayanBeta::Beta(_, _) => self.as_expression(),
}
}
}
fn same_group(list: &[DayanBeta]) -> BTreeMap<&DayanBeta, u32> {
let mut groups: BTreeMap<&DayanBeta, u32> = Default::default();
let mut current = None;
for item in list {
if item.is_zero() {
continue;
}
match current {
None => {
current = Some(item);
groups.insert(item, 1);
}
Some(current_item) => {
if current_item == item {
*groups.get_mut(current_item).unwrap() += 1;
}
else {
current = Some(item);
groups.insert(item, 1);
}
}
}
}
groups
}