1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::utils::{Interpreter, Program, MAX_MEMORY};
use shortest_brainfuck::shortest_map;
#[derive(Debug)]
pub struct MemoryLayout {
head: String,
layout: Vec<u8>,
index: usize,
}
pub fn get_memory_layout(p: &str) -> MemoryLayout {
let pi_program = Program::from_string(p);
let mut data = Vec::new();
let mut vm = Interpreter {
program_counter: 0,
program: &pi_program,
memory_pointer: 10,
memory: [0; MAX_MEMORY],
input: std::io::stdin(),
output: &mut data,
};
vm.interpret();
MemoryLayout { head: p.to_string(), layout: vm.memory[0..(vm.memory_pointer + 10)].to_owned(), index: vm.memory_pointer }
}
impl MemoryLayout {
fn abs(&self, a: usize, b: usize) -> usize {
if a >= b { a - b } else { b - a }
}
fn rem(&self, a: i16, b: i16) -> i16 {
if b - a > 128 { 256 - b + a } else { b - a }
}
fn distance(&self, pos: usize, index: usize, target: u8, value: u8) -> usize {
self.abs(pos, index) + self.rem(value.min(target) as i16, value.max(target) as i16) as usize
}
fn append(&mut self, record: (usize, usize, u8, u8)) {
self.head.push('\n');
let (pos, index, target, value) = record;
if pos < index {
self.head.push_str(&">".repeat(index - pos))
}
else if pos > index {
self.head.push_str(&"<".repeat(pos - index))
};
if value < target {
self.head.push_str(&"+".repeat((target - value) as usize))
}
else if value > target {
self.head.push_str(&"-".repeat((value - target) as usize))
}
self.head.push('.');
}
fn update(&mut self, target: &u8) {
let mut min = self.index + 255;
let mut record = (0, 0, 0, 0);
for (index, value) in self.layout.iter().enumerate() {
let d = self.distance(self.index, index, *target, *value);
if d < min {
record = (self.index, index, *target, *value);
min = d
}
}
self.append(record);
self.index = record.1;
self.layout[self.index] = *target
}
fn encode(&mut self, target: &str) -> String {
for c in target.as_bytes() {
self.update(c)
}
return self.head.clone();
}
}
pub const INITIALIZATIONS: &[&str; 18] = &[
"-[[<+>->+>+<<]>]",
"+[[<+>->+>+<<]>]",
"--[[<+>->+>+<<]>]",
"++[[<+>->+>+<<]>]",
"-[[<+>->+>--->-<<<]>+++]",
"+<-[[<+>->+>--->-<<<]>++]",
"-<++[[<+>->->+++>+<<<]->]",
"+<<+[+[<+>--->->->-<<<]>]",
"-<<+[+[<+>--->->->-<<<]>]",
"+[++[<+++>->+++<]>+++++++]",
"+<-[[<+>->+>--->-<<<]>+++]",
"++<-[[<+>->+>--->-<<<]>+++]",
"-[++[<++>->+++>+++<<]--->+]",
"-<-<<+[+[<+>--->->->-<<<]>]",
"-[++[<++>->+++>+++<<]---->+]",
"--<-<<+[+[<+>--->->->-<<<]>]",
"+[+[<<<+>>>>]",
"+[>>>->-[>->----<<<]>>]",
];
pub fn encode(input: &str) -> String {
if let Some(s) = shortest_map().get(input) { return s.to_string() };
INITIALIZATIONS.iter().map(|&o| get_memory_layout(o).encode(input)).min_by(|x, y| x.len().cmp(&y.len())).unwrap()
}
pub fn decode(input: &str) -> String {
let mut data = Vec::new();
let mut vm = Interpreter {
program_counter: 0,
program: &Program::from_string(input),
memory_pointer: 10,
memory: [0; MAX_MEMORY],
input: std::io::stdin(),
output: &mut data,
};
vm.interpret();
match String::from_utf8(data) {
Ok(o) => o,
Err(e) => e.to_string(),
}
}