Skip to content

Instantly share code, notes, and snippets.

@shubhamkumar13
Last active November 5, 2022 12:37
Show Gist options
  • Save shubhamkumar13/a2c145f48094b5505701a97dde8ffbe1 to your computer and use it in GitHub Desktop.
Save shubhamkumar13/a2c145f48094b5505701a97dde8ffbe1 to your computer and use it in GitHub Desktop.
Trying to implement algorithm design in rust
use std::collections::VecDeque;
use std::panic;
trait FP<T> {
fn cons(self, x : T) -> VecDeque<T>;
fn snoc(self, x : T) -> VecDeque<T>;
fn tail(self) -> Option<VecDeque<T>>;
fn init(self) -> Option<VecDeque<T>>;
fn head(self) -> Option<T>;
fn last(self) -> Option<T>;
}
#[derive(Debug, Clone)]
struct SymList<T : Clone> (VecDeque<T>, VecDeque<T>);
impl<T : Clone> FP<T> for VecDeque<T> {
fn cons(self, x : T) -> VecDeque<T> {
let mut v = self;
v.push_front(x);
v
}
fn snoc(self, x : T) -> VecDeque<T> {
let mut v = self;
v.push_back(x);
v
}
fn tail(self) -> Option<VecDeque<T>> {
let mut v = self;
if !v.is_empty() {
Some(v.split_off(0))
} else {
None
}
}
fn init(self) -> Option<VecDeque<T>> {
let mut v = self;
if !v.is_empty() {
let _ = v.split_off(v.len() - 1);
Some(v)
} else {
None
}
}
fn head(self) -> Option<T> {
let mut v = self;
v.pop_front()
}
fn last(self) -> Option<T> {
let mut v = self;
v.pop_back()
}
}
impl<T : Clone> SymList<T> {
fn new(arr : Vec<T>) -> Self {
let mut v = VecDeque::from(arr.clone());
let mut ys = v.split_off(v.len() / 2);
ys.make_contiguous().reverse();
SymList(v, ys)
}
fn from_sl(self) -> VecDeque<T> {
let mut v1 = self.0.clone();
let mut v2 = self.1.clone();
v2.make_contiguous().reverse();
v1.append(&mut v2);
v1
}
fn snoc_sl (self, x : T) -> Self {
let mut v1 = self.0.clone();
let mut v2 = self.1.clone();
if v1.is_empty() {
SymList(v2, VecDeque::from(vec![x]))
} else {
v2.push_front(x);
SymList(v1, v2)
}
}
fn cons_sl (self, x : T) -> Self {
let mut v1 = self.0.clone();
let mut v2 = self.1.clone();
if v2.is_empty() {
SymList(VecDeque::from(vec![x]), v2)
} else {
v1.push_front(x);
SymList(v1, v2)
}
}
fn head_sl (self) -> Option<T> {
let mut v1 = self.0.clone();
let mut v2 = self.1.clone();
match (v1.is_empty(), v2.is_empty()) {
(true, true) => None,
(true, false) => v2.head(),
(false, _) => v1.head()
}
}
fn last_sl(self) -> Option<T> {
let mut v1 = self.0.clone();
let mut v2 = self.1.clone();
match (v2.is_empty(), v1.is_empty()) {
(true, true) => None,
(true, false) => v1.head(),
(false, _) => v2.head()
}
}
fn tail_sl(self) -> Self {
let mut v1 = self.0.clone();
let mut v2 = self.1.clone();
match v1.len() {
0 => {
if v2.is_empty() {
panic!("empty symmetric list")
} else {
SymList(VecDeque::new(), VecDeque::new())
}
},
1 => {
let (vs, us) = {
let vs = v2.split_off(v2.len() / 2);
v2.make_contiguous().reverse();
let us = v2;
(vs, us)
};
SymList(vs, us)
},
_ => {
if let Some(xs) = v1.tail() {
SymList(xs, v2)
} else {
panic!("cannot get a tail value")
}
}
}
}
}
// cons adds elements at the end
// eq1 lst x = cons x $ from_sl lst
// eq2 lst x = from_sl $ cons_sl lst
// eq1 = eq2
// snoc adds element at the end of a list
// eq1 lst x = snoc x $ from_sl lst
// eq2 lst x = from_sl $ snoc_sl lst
// eq1 = eq2
fn main () {
let s = SymList::<i32>::new(vec![1,2,3]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment