2024-10-20 00:40:01 +03:00
|
|
|
use std::{
|
|
|
|
collections::{HashMap, VecDeque},
|
2024-10-20 13:36:51 +03:00
|
|
|
env, fs,
|
2024-10-20 00:40:01 +03:00
|
|
|
io::{self, Write},
|
|
|
|
path::PathBuf,
|
|
|
|
};
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let program: Vec<u8> = load_program();
|
|
|
|
|
|
|
|
let mut tape: Vec<u8> = vec![0];
|
|
|
|
let mut cell_index: usize = 0;
|
|
|
|
|
|
|
|
let mut ip: usize = 0;
|
2024-10-20 13:36:51 +03:00
|
|
|
let mut icount: usize = 0;
|
2024-10-20 00:40:01 +03:00
|
|
|
let mut user_input: Vec<u8> = vec![];
|
|
|
|
|
|
|
|
let mut table: HashMap<usize, usize> = HashMap::new();
|
|
|
|
let mut stack: VecDeque<usize> = VecDeque::new();
|
|
|
|
for (ip, instruction) in program.iter().enumerate() {
|
|
|
|
if *instruction == b'[' {
|
|
|
|
stack.push_back(ip);
|
|
|
|
} else if *instruction == b']' {
|
2024-10-20 13:36:51 +03:00
|
|
|
let begin_index = stack.pop_back().unwrap();
|
2024-10-20 00:40:01 +03:00
|
|
|
table.insert(begin_index, ip);
|
|
|
|
table.insert(ip, begin_index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while ip < program.len() {
|
|
|
|
let Some(instruction) = program.get(ip) else {
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
match instruction {
|
2024-10-20 13:56:40 +03:00
|
|
|
b'+' => {
|
|
|
|
tape[cell_index] = tape[cell_index].wrapping_add(1);
|
|
|
|
icount += 1;
|
|
|
|
}
|
|
|
|
b'-' => {
|
|
|
|
tape[cell_index] = tape[cell_index].wrapping_sub(1);
|
|
|
|
icount += 1;
|
|
|
|
}
|
2024-10-20 00:40:01 +03:00
|
|
|
b'>' => {
|
|
|
|
cell_index = cell_index.wrapping_add(1);
|
|
|
|
if tape.len() <= cell_index {
|
|
|
|
tape.push(0);
|
|
|
|
}
|
2024-10-20 13:56:40 +03:00
|
|
|
icount += 1;
|
|
|
|
}
|
|
|
|
b'<' => {
|
|
|
|
cell_index = cell_index.wrapping_sub(1);
|
|
|
|
icount += 1;
|
|
|
|
}
|
|
|
|
b'.' => {
|
|
|
|
print!("{}", tape[cell_index] as char);
|
|
|
|
icount += 1;
|
2024-10-20 00:40:01 +03:00
|
|
|
}
|
|
|
|
b',' => {
|
|
|
|
if user_input.is_empty() {
|
|
|
|
user_input = input();
|
|
|
|
}
|
|
|
|
tape[cell_index] = user_input.remove(0);
|
2024-10-20 13:56:40 +03:00
|
|
|
icount += 1;
|
2024-10-20 00:40:01 +03:00
|
|
|
}
|
|
|
|
b'[' => {
|
|
|
|
if tape[cell_index] == 0 {
|
|
|
|
ip = *table.get(&ip).unwrap();
|
|
|
|
}
|
2024-10-20 13:56:40 +03:00
|
|
|
icount += 1;
|
2024-10-20 00:40:01 +03:00
|
|
|
}
|
|
|
|
b']' => {
|
|
|
|
if tape[cell_index] != 0 {
|
|
|
|
ip = *table.get(&ip).unwrap();
|
|
|
|
}
|
2024-10-20 13:56:40 +03:00
|
|
|
icount += 1;
|
2024-10-20 00:40:01 +03:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
ip += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
println!();
|
2024-10-20 13:36:51 +03:00
|
|
|
println!("Instructions ran: {icount}");
|
|
|
|
// println!("{tape:?}");
|
2024-10-20 00:40:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn input() -> Vec<u8> {
|
|
|
|
let mut input = String::new();
|
|
|
|
|
|
|
|
print!("Input: ");
|
|
|
|
let _ = io::stdout().flush();
|
|
|
|
let _ = io::stdin().read_line(&mut input);
|
|
|
|
|
|
|
|
input.as_bytes().to_vec()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn load_program() -> Vec<u8> {
|
2024-10-20 13:36:51 +03:00
|
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
let input = args[1].clone();
|
|
|
|
|
|
|
|
let path: PathBuf = input.into();
|
2024-10-20 00:40:01 +03:00
|
|
|
let input = fs::read_to_string(path).unwrap();
|
|
|
|
input.as_bytes().to_vec()
|
|
|
|
}
|