Xeroxer/tag2xeroxer.rs
Jump to navigation
Jump to search
Run with rustc tag2xeroxer.rs && ./tag2xeroxer
fn main() {
// collatz conjecture on input 9
let prod: &[&[usize]] = &[&[1, 2], &[0], &[0, 0, 0]];
let input = &[0; 9][..];
let m = 2;
let prog = trans(prod, input, m);
println!("{:?}", prog);
}
/*
* overview: each symbol copies itself until it is "activated" or destroyed by the production table being near it.
* an activated symbol first copies its corresponding production, and arranges for the production
* table to be recreated, with it being set such that it destroys the next m - 1 symbols. each
* act (destroying each symbol, and recreating the table) takes 1 full cycle of the whole "queue"
* rotating. so, an m-tag system taking O(t) time would be emulated in O(t^2) time.
*
* |x| = length of x
* (x) = quote x = (_, |x|) x (|x|, _)
* prod = (0, 0) * (|sym| + 1) <jump to @y> (0, |rules| + |sym| + 2) rules (0, 0) * (|sym| + 1) <jump to @y> (|sym| + 2, 0) <copy till (0, |rules| + |sym| + 2)> @y: (0, 2)
* rules = [(rule)]
* rule = [sym]
* sym = <copy symbol> <jump to next copier> <copy rule> <copy prod> (( <copy till (0, |rules| + |sym| + 2)> <set m> )) (0, 1)
* set 1 = (0, 2)
* set m = (|prod| - 1, |set m - 1|) set m - 1 (|set m - 1|, |sym| + 1)
*/
fn trans(prod: &[&[usize]], input: &[usize], m: usize) -> Vec<(usize, usize)> {
let map = construct(m, prod);
let sym_len = get_sym_len(m);
let footer_len = get_footer_len(sym_len);
let mut res = vec![(0, 0); sym_len + 1];
let rules_len = get_rules_len(&map, m);
let y = rules_len + footer_len + 1 - 1;
res.extend_from_slice(&[(0, y), (0, rules_len + sym_len + 2)]);
for (i, &rule) in prod.iter().enumerate() {
let rule_len = sym_len * rule.len();
let to_end = map.get(i + 1).map(|&i| i).unwrap_or(0) + footer_len + 2;
res.push((0, rule_len));
for &sym in rule {
sym_convert(&map, &mut res, m, sym);
}
res.push((rule_len, to_end));
}
for _ in 0..sym_len + 1 {
res.push((0, 0));
}
res.extend_from_slice(&[
(0, y),
(sym_len + 2, 0),
(rules_len + sym_len + 4, 4),
(0, 2),
]);
for &sym in input {
sym_convert(&map, &mut res, m, sym);
}
res
}
fn sym_convert(map: &[usize], v: &mut Vec<(usize, usize)>, m: usize, sym: usize) {
let sym_len = get_sym_len(m);
let rules_len = get_rules_len(map, m);
let prod_len = get_prod_len(rules_len, sym_len, m);
v.extend_from_slice(&[
(sym_len, 0),
(0, sym_len - 2),
(map[sym] + get_footer_len(sym_len) + 2, 0),
(get_footer_len(sym_len) + rules_len + 4, 0),
]);
convert_m(v, m, sym_len, rules_len, prod_len);
v.push((0, 1))
}
fn convert_m(
v: &mut Vec<(usize, usize)>,
m: usize,
sym_len: usize,
rules_len: usize,
prod_len: usize,
) {
let m_len = get_m_len(m);
v.extend_from_slice(&[(0, m_len + 3), (0, m_len + 1), (rules_len + sym_len + 4, 4)]);
for m in (2..=m).rev() {
let m_len = get_m_len(m - 1);
v.push((prod_len - 1, m_len));
}
v.push((0, 2));
for m in 2..=m {
let m_len = get_m_len(m - 1);
v.push((m_len, sym_len + 1));
}
v.extend_from_slice(&[(m_len + 1, 1), (m_len + 3, 0)]);
}
fn construct(m: usize, prod: &[&[usize]]) -> Vec<usize> {
let mut res = Vec::new();
let sym_len = get_sym_len(m);
for i in prod {
res.push(i.len() * sym_len + 2);
}
let mut acc = 0;
for i in res.iter_mut().rev() {
acc += *i;
*i = acc;
}
res
}
fn get_m_len(m: usize) -> usize {
m * 2 - 1
}
fn get_sym_len(m: usize) -> usize {
get_m_len(m) + 10
}
fn get_rules_len(map: &[usize], m: usize) -> usize {
map[0]
}
fn get_footer_len(sym_len: usize) -> usize {
sym_len + 5
}
fn get_prod_len(rules_len: usize, sym_len: usize, m: usize) -> usize {
2 * (sym_len + 2) + rules_len + 4
}