rust implement a crate for encode and decode brainfuck and ook

Pub Date: 2023-07-28

#![allow(unused)]
fn main() {
mod utils;
#[allow(warnings)]
pub mod Ook {
use std::collections::HashMap;
pub trait Join {
fn join(&self, by: &str) -> String;
}
impl<T: ToString> Join for [T] {
fn join(&self, by: &str) -> String {
self.iter()
.map(|item| item.to_string())
.collect::<Vec<String>>()
.join(by)
}
}
/// # text to brainfuck
pub fn text_to_brainfuck(text: impl AsRef<str>) -> String {
let mut value: isize = 0;
let mut result = String::new();
for c in text.as_ref().chars() {
let diff = c as isize - value;
value = c as isize;
if diff == 0 {
result.push_str(">.");
continue;
}
if diff.abs() < 10 {
if diff > 0 {
result.push('>');
result.push_str(&"+".repeat(diff as usize));
} else if diff < 0 {
result.push('>');
result.push_str(&"-".repeat(diff.abs() as usize));
}
} else {
let loop_count = (diff.abs() as f64).sqrt() as usize;
result.push_str(&"+".repeat(loop_count));
if diff > 0 {
result.push_str(&"[->".to_owned());
result.push_str(&"+".repeat(loop_count));
result.push_str("<]");
result.push('>');
result.push_str(&"+".repeat(diff as usize - loop_count.pow(2)));
} else if diff < 0 {
result.push_str(&"[->".to_owned());
result.push_str(&"-".repeat(loop_count));
result.push_str("<]");
result.push('>');
result.push_str(&"-".repeat(diff.abs() as usize - loop_count.pow(2)));
}
}
result.push_str(".<");
}
result.replace("<>", "")
}
///# decode brainfuck to text
pub fn brainfuck_to_text(encoded: impl AsRef<str>) -> String {
let mut decoded = String::new();
let mut data = vec![0u8; 30000];
let mut data_index = 0;
let mut loop_stack = Vec::new();
let encoded_chars: Vec<char> = encoded.as_ref().chars().collect();
let mut index = 0;
while index < encoded_chars.len() {
match encoded_chars[index] {
'+' => {
data[data_index] = data[data_index].wrapping_add(1);
}
'-' => {
data[data_index] = data[data_index].wrapping_sub(1);
}
'>' => {
data_index += 1;
}
'<' => {
if data_index > 0 {
data_index -= 1;
}
}
'.' => {
decoded.push(data[data_index] as char);
}
',' => {
// Input operation is not supported in decoding mode.
// You can add your own logic here if needed.
}
'[' => {
if data[data_index] == 0 {
// Skip the loop (jump to corresponding ']')
let mut brackets = 1;
while brackets > 0 && index < encoded_chars.len() {
index += 1;
if encoded_chars[index] == '[' {
brackets += 1;
} else if encoded_chars[index] == ']' {
brackets -= 1;
}
}
} else {
loop_stack.push(index);
}
}
']' => {
if data[data_index] != 0 {
// Jump back to the loop start ('[')
if let Some(&start) = loop_stack.last() {
index = start - 1; // Subtract 1 since 'index' will be incremented again
}
} else {
loop_stack.pop();
}
}
_ => {} // Ignore other characters
}
index += 1;
}
decoded
}
/// # translate brainfuck to ook
pub fn brainfuck_to_ook(output: impl AsRef<str>) -> String {
output.as_ref()
.chars()
.map(|ch| match ch {
'>' => "Ook. Ook? ",
'<' => "Ook? Ook. ",
'+' => "Ook. Ook. ",
'-' => "Ook! Ook! ",
'.' => "Ook! Ook. ",
',' => "Ook. Ook! ",
'[' => "Ook! Ook? ",
']' => "Ook? Ook! ",
_ => "",
})
.collect()
}
/// # translate ook to brainfuck
pub fn ook_to_text(input: impl AsRef<str>) -> String {
let input = input.as_ref().replace("Ook", "").replace(" ", "");
let mut output = "".to_string();
let lookup: HashMap<&str, &str> = [
(".?", ">"),
("?.", "<"),
("..", "+"),
("!!", "-"),
("!.", "."),
(".!", ","),
("!?", "["),
("?!", "]"),
].iter().cloned().collect();
let len = input.len();
for i in (0..len).step_by(2) {
let key = &input[i..i+2];
output.push_str(lookup.get(key).unwrap_or(&""));
}
brainfuck_to_text(&output)
}
/// # text to ook
pub fn text_to_ook(text: impl AsRef<str>) -> String {
brainfuck_to_ook(&text_to_brainfuck(&text.as_ref())).to_string()
}
/// # text to shourt ook
pub fn text_to_short_ook(text:  impl AsRef<str>) -> String {
brainfuck_to_ook(&text_to_brainfuck(&text.as_ref()))
.to_string()
.replace(" ", "")
.replace("Ook", "")
}
}
}