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", "") } } }