use colored::*;
use core::fmt::Display;
#[derive(Debug, Clone)]
pub struct Tape {
left: Vec<char>,
right: Vec<char>,
}
impl Default for Tape {
fn default() -> Self {
Self {
left: Vec::new(),
right: Vec::new(),
}
}
}
impl Display for Tape {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"..@{}|{}|@..",
self.left
.iter()
.flat_map(|sym| ['|', *sym])
.collect::<String>(),
self.right
.iter()
.rev()
.flat_map(|sym| ['|', *sym])
.skip(1)
.collect::<String>()
)
}
}
impl Tape {
pub fn read(&self) -> char {
*self.right.last().unwrap_or(&'@')
}
pub fn write(&mut self, symbol: char) {
self.right.pop();
self.right.push(symbol);
}
pub fn move_left(&mut self) {
let character = match self.left.pop() {
Some(x) => x,
None => '@',
};
self.right.push(character);
}
pub fn move_right(&mut self) {
let character = match self.right.pop() {
Some(x) => x,
None => '@',
};
self.left.push(character);
}
pub fn shift_left(&mut self) {
self.left.pop();
}
pub fn shift_right(&mut self) {
let character = match self.right.last() {
Some(x) => *x,
None => '@',
};
self.left.push(character);
}
pub fn initialize(&mut self, input: String) {
input
.chars()
.rev()
.for_each(|character| self.right.push(character));
}
pub fn memory(&self) -> usize {
self.left.len() + self.right.len()
}
pub fn show_output(&self) {
println!("{}", "Output:".bright_blue());
let output = self
.right
.iter()
.rev()
.filter(|sym| **sym != '@')
.collect::<String>();
println!(
"{}",
if output == "" {
"@".to_string()
} else {
output
}
);
}
pub fn show_tape(&self) {
println!("{}", "Tape:".bright_blue());
let header = self.left.len();
println!(
"..@{}|{}|@..",
self.left
.iter()
.flat_map(|sym| ['|', *sym])
.collect::<String>(),
if self.right.is_empty() {
"@".to_owned()
} else {
self.right
.iter()
.rev()
.flat_map(|sym| ['|', *sym])
.skip(1)
.collect::<String>()
}
);
println!("{}^", " ".repeat(header * 2 + 4));
}
}