ICFP 2007 Contest: https://web.archive.org/web/20090301164728/https://save-endo.cs.uu.nl/

Compare changes

Choose any two refs to compare.

+1 -1
.gitignore
···
task/endo.dna
.tup/
-
out/
···
task/endo.dna
.tup/
+
/out/
-13
Tupfile
···
-
RUSTC_FLAGS= --edition=2024 --crate-type bin --emit=link -C opt-level=3 -C embed-bitcode=no --check-cfg 'cfg (docsrs,test)' --check-cfg 'cfg(feature, values())' --out-dir out/bin -C strip=debuginfo -L dependency=out/bin
-
-
: dna2rna/src/*.rs |> rustc --crate-name dna2rna dna2rna/src/main.rs $(RUSTC_FLAGS) |> out/bin/dna2rna
-
: rna2bmp/src/*.rs |> rustc --crate-name rna2bmp rna2bmp/src/main.rs $(RUSTC_FLAGS) |> out/bin/rna2bmp
-
: asm2dna/src/*.rs |> rustc --crate-name asm2dna asm2dna/src/main.rs $(RUSTC_FLAGS) |> out/bin/asm2dna
-
-
: foreach asm/*.asm | out/bin/asm2dna |> ./out/bin/asm2dna %f out/dna/%B.dna |> out/dna/%B.dna
-
-
: foreach out/dna/*.dna | out/bin/dna2rna |> ./out/bin/dna2rna %f task/endo.dna out/rna/%B.rna |> out/rna/%B.rna
-
-
: foreach out/rna/*.rna | out/bin/rna2bmp |> ./out/bin/rna2bmp %f out/bmp/%B.bmp |> out/bmp/%B.bmp
-
-
: foreach out/bmp/*.bmp |> convert %f out/png/%B.png |> out/png/%B.png
···
+64
Tupfile.lua
···
···
+
function define_rust_rule(name, type, deps)
+
local inputs = {}
+
for _, input in ipairs(tup.glob(name .. "/src/*.rs")) do
+
table.insert(inputs, input)
+
end
+
+
local input_rs
+
local output
+
if type == "bin" then
+
input_rs = name .. "/src/main.rs"
+
output = "out/bin/" .. name
+
else
+
input_rs = name .. "/src/lib.rs"
+
output = "out/lib/lib" .. name .. ".rlib"
+
end
+
+
local externs = {}
+
for _, dep in ipairs(deps) do
+
local rlib = "out/lib/lib" .. dep .. ".rlib"
+
table.insert(inputs, rlib)
+
table.insert(externs, "--extern " .. dep .. "=" .. rlib)
+
end
+
+
local flags = "--edition=2024 -C opt-level=3 -C embed-bitcode=no -C strip=debuginfo --emit=link"
+
local command = "rustc --crate-name " .. name .. " --crate-type=" .. type .. " " .. input_rs .. " -o %o " .. table.concat(externs, " ") .. " " .. flags
+
tup.definerule{inputs = inputs, command = command, outputs = {output}}
+
end
+
+
define_rust_rule("dna_parsing", "lib", {})
+
define_rust_rule("dna2rna", "bin", {"dna_parsing"})
+
define_rust_rule("disassembler", "bin", {"dna_parsing"})
+
define_rust_rule("rna2bmp", "bin", {})
+
define_rust_rule("asm2dna", "bin", {})
+
+
local asm = tup.glob("asm/*.asm")
+
asm.extra_inputs = {"out/bin/asm2dna"}
+
tup.foreach_rule(
+
asm,
+
"./out/bin/asm2dna %f %o",
+
{"out/dna/%B.dna"}
+
)
+
+
local dna = tup.glob("out/dna/*.dna")
+
dna.extra_inputs = {"out/bin/dna2rna"}
+
tup.foreach_rule(
+
dna,
+
"./out/bin/dna2rna %f task/endo.dna %o",
+
{"out/rna/%B.rna"}
+
)
+
+
local rna = tup.glob("out/rna/*.rna")
+
rna.extra_inputs = {"out/bin/rna2bmp"}
+
tup.foreach_rule(
+
rna,
+
"./out/bin/rna2bmp %f %o",
+
{"out/bmp/%B.bmp"}
+
)
+
+
local bmp = tup.glob("out/bmp/*.bmp")
+
tup.foreach_rule(
+
bmp,
+
"convert %f %o",
+
{"out/png/%B.png"}
+
)
+1 -1
asm/gene_list_1.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+2 -2
asm/gene_list_10.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{9,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{9,24} ;
+2 -2
asm/gene_list_11.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{10,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{10,24} ;
+2 -2
asm/gene_list_12.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{11,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{11,24} ;
+2 -2
asm/gene_list_13.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{12,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{12,24} ;
+2 -2
asm/gene_list_14.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{13,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{13,24} ;
+2 -2
asm/gene_list_2.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{1,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{1,24} ;
+2 -2
asm/gene_list_3.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{2,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{2,24} ;
+2 -2
asm/gene_list_4.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{3,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{3,24} ;
+2 -2
asm/gene_list_5.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{4,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{4,24} ;
+2 -2
asm/gene_list_6.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{5,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{5,24} ;
+2 -2
asm/gene_list_7.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{6,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{6,24} ;
+2 -2
asm/gene_list_8.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{7,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{7,24} ;
+2 -2
asm/gene_list_9.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{42,24} ;
-
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; "0"n{8,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{42,24} ;
+
(?{IFPICFPPCFFPP}!{0x503})n{0,24} ; {0}n{8,24} ;
+1 -1
asm/repair_guide.asm
···
-
(?{IFPCFFP})II ; "0"IC ;
···
+
(?{IFPCFFP})II ; {0}IC ;
+1 -1
asm/repair_guide_catalog.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{1337,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{1337,24} ;
+1 -1
asm/repair_guide_charset.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{10646,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{10646,24} ;
+1 -1
asm/repair_guide_field_repair.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{85,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{85,24} ;
+1 -1
asm/repair_guide_genome_structure.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{1729,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{1729,24} ;
+1 -1
asm/repair_guide_l_systems.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{5,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{5,24} ;
+1 -1
asm/repair_guide_more_genome_structure.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{8,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{8,24} ;
+1 -1
asm/repair_guide_rna_compression.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{123456,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{123456,24} ;
+1 -1
asm/repair_guide_security.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{4405829,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{4405829,24} ;
+1 -1
asm/repair_guide_wanted.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{112,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{112,24} ;
+1 -1
asm/repair_guide_weird_rna.asm
···
-
(?{IFPCFFP})n{0,24} ; "0"n{2181889,24} ;
···
+
(?{IFPCFFP})n{0,24} ; {0}n{2181889,24} ;
+1 -1
asm/startup.asm
···
-
(?{IFPCFFP})I ; "0"C ;
···
+
(?{IFPCFFP})I ; {0}C ;
+1 -1
asm/sun.asm
···
-
(?{IFPFI})P ; "0"F ;
···
+
(?{IFPFI})P ; {0}F ;
+1 -1
asm/task.asm
···
-
(?{IFPP})F ; "0"P ;
···
+
(?{IFPP})F ; {0}P ;
+7 -7
asm2dna/src/assembler.rs
···
Some('(') => self.emit("IIP"),
Some(')') => self.emit("IIC"),
Some(';') => self.emit("IIC"),
-
Some('"') => {
-
let n = self.read_to("\",").ok_or("Reference failed terminate")?;
let n = Self::parse_int(&n).ok_or("Reference group index invalid")?;
let l = match self.iter.next() {
-
Some('"') => String::from("0"),
Some(',') => {
-
let l = self.read_to("\"").ok_or("Reference failed to terminate")?;
-
self.expect('"');
l
}
_ => return Err("Reference failed to terminate"),
···
#[test]
fn test_assemble_pattern_quote() {
-
let asm = assemble(&"\"2\"").unwrap();
assert_eq!(b"IPPICP", &asm[..]);
-
let asm = assemble(&"\"2,3\"").unwrap();
assert_eq!(b"IPCCPICP", &asm[..]);
}
···
Some('(') => self.emit("IIP"),
Some(')') => self.emit("IIC"),
Some(';') => self.emit("IIC"),
+
Some('{') => {
+
let n = self.read_to("},").ok_or("Reference failed terminate")?;
let n = Self::parse_int(&n).ok_or("Reference group index invalid")?;
let l = match self.iter.next() {
+
Some('}') => String::from("0"),
Some(',') => {
+
let l = self.read_to("}").ok_or("Reference failed to terminate")?;
+
self.expect('}');
l
}
_ => return Err("Reference failed to terminate"),
···
#[test]
fn test_assemble_pattern_quote() {
+
let asm = assemble(&"{2}").unwrap();
assert_eq!(b"IPPICP", &asm[..]);
+
let asm = assemble(&"{2,3}").unwrap();
assert_eq!(b"IPCCPICP", &asm[..]);
}
+1
disassembler/.dir-locals.el
···
···
+
((nil . ((default-directory . "~/repos/endo/disassembler/"))))
+14
disassembler/Cargo.lock
···
···
+
# This file is automatically @generated by Cargo.
+
# It is not intended for manual editing.
+
version = 4
+
+
[[package]]
+
name = "disassembler"
+
version = "0.1.0"
+
dependencies = [
+
"dna_parsing",
+
]
+
+
[[package]]
+
name = "dna_parsing"
+
version = "0.1.0"
+7
disassembler/Cargo.toml
···
···
+
[package]
+
name = "disassembler"
+
version = "0.1.0"
+
edition = "2024"
+
+
[dependencies]
+
dna_parsing = { path = "../dna_parsing" }
+69
disassembler/src/main.rs
···
···
+
use dna_parsing::base::Base;
+
use dna_parsing::parser::Parser;
+
use std::env;
+
use std::fs;
+
use std::io;
+
use std::io::Write;
+
+
fn main() {
+
let args: Vec<String> = env::args().collect();
+
if args.len() < 3 {
+
println!("Usage: {} <dna file> <offset>", args[0]);
+
return;
+
}
+
+
let Ok(dna) = fs::read_to_string(&args[1]) else {
+
println!("Failed to read dna file at {}", &args[1]);
+
return;
+
};
+
let Ok(offset): Result<usize, _> = args[2].parse() else {
+
println!("Failed to parse offset {}", &args[2]);
+
return;
+
};
+
+
let mut index = 0;
+
loop {
+
print!("> ");
+
let _ = io::stdout().flush();
+
let mut line = String::new();
+
if !io::stdin().read_line(&mut line).is_ok() {
+
println!("Failed to read response line");
+
return;
+
}
+
line = line.trim().to_string();
+
if !line.is_empty() {
+
let Ok(new_index): Result<usize, _> = line.parse() else {
+
println!("Failed to parse {}", line);
+
continue;
+
};
+
index = new_index;
+
}
+
+
let mut parser = Parser::new(
+
dna[index + offset..]
+
.chars()
+
.filter_map(|c| Base::from_char(c)),
+
);
+
let mut rna = Vec::new();
+
let Some(pattern) = parser.pattern(&mut rna) else {
+
println!("Failed to parse pattern");
+
continue;
+
};
+
let Some(template) = parser.template(&mut rna) else {
+
println!("Failed to parse template");
+
continue;
+
};
+
+
if !rna.is_empty() {
+
println!("RNA output:");
+
for r in rna.iter() {
+
let rna_str: String = r.iter().map(|b| b.to_char()).collect();
+
println!(" {}", rna_str);
+
}
+
println!();
+
}
+
println!("{} ; {} ;", pattern, template);
+
index += parser.index();
+
println!("Now at: {}", index);
+
}
+
}
+7
dna2rna/Cargo.lock
···
[[package]]
name = "dna2rna"
version = "0.1.0"
···
[[package]]
name = "dna2rna"
version = "0.1.0"
+
dependencies = [
+
"dna_parsing",
+
]
+
+
[[package]]
+
name = "dna_parsing"
+
version = "0.1.0"
+1
dna2rna/Cargo.toml
···
edition = "2024"
[dependencies]
···
edition = "2024"
[dependencies]
+
dna_parsing = { path = "../dna_parsing" }
+1 -29
dna2rna/src/dna.rs
···
use std::collections::VecDeque;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Deref;
use std::ops::Index;
use std::rc::Rc;
-
-
#[derive(Copy, Clone, PartialEq, Debug)]
-
pub enum Base {
-
I,
-
C,
-
F,
-
P,
-
}
#[derive(Clone, Debug)]
pub enum Dna {
···
len: usize,
depth: usize,
children: (DnaRef, DnaRef, DnaRef),
-
}
-
-
impl Base {
-
pub fn from_char(c: char) -> Option<Base> {
-
match c {
-
'I' => Some(Base::I),
-
'C' => Some(Base::C),
-
'F' => Some(Base::F),
-
'P' => Some(Base::P),
-
_ => None,
-
}
-
}
-
-
pub fn to_char(&self) -> char {
-
match self {
-
Base::I => 'I',
-
Base::C => 'C',
-
Base::F => 'F',
-
Base::P => 'P',
-
}
-
}
}
impl DnaRef {
···
+
use dna_parsing::base::Base;
use std::collections::VecDeque;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Deref;
use std::ops::Index;
use std::rc::Rc;
#[derive(Clone, Debug)]
pub enum Dna {
···
len: usize,
depth: usize,
children: (DnaRef, DnaRef, DnaRef),
}
impl DnaRef {
-4
dna2rna/src/main.rs
···
mod dna;
mod match_replace;
-
mod parser;
-
mod pattern;
-
mod rna;
-
mod template;
use std::env;
use std::fs;
···
mod dna;
mod match_replace;
use std::env;
use std::fs;
+6 -6
dna2rna/src/match_replace.rs
···
-
use crate::dna::Base;
use crate::dna::DnaRef;
-
use crate::parser::Parser;
-
use crate::pattern::Pattern;
-
use crate::pattern::PatternItem;
-
use crate::rna::Rna;
-
use crate::template::TemplateItem;
struct MatchResult {
end: usize,
···
use crate::dna::DnaRef;
+
use dna_parsing::base::Base;
+
use dna_parsing::parser::Parser;
+
use dna_parsing::pattern::Pattern;
+
use dna_parsing::pattern::PatternItem;
+
use dna_parsing::rna::Rna;
+
use dna_parsing::template::TemplateItem;
struct MatchResult {
end: usize,
-315
dna2rna/src/parser.rs
···
-
use crate::dna::Base;
-
use crate::pattern::Pattern;
-
use crate::pattern::PatternItem;
-
use crate::rna::Rna;
-
use crate::template::Template;
-
use crate::template::TemplateItem;
-
use std::mem;
-
-
pub struct Parser<I>
-
where
-
I: Iterator<Item = Base>,
-
{
-
iter: I,
-
peeked: Vec<Base>,
-
index: usize,
-
}
-
-
impl<I> Parser<I>
-
where
-
I: Iterator<Item = Base>,
-
{
-
pub fn new(iter: I) -> Parser<I> {
-
Parser {
-
iter: iter,
-
peeked: Vec::new(),
-
index: 0,
-
}
-
}
-
-
pub fn index(&self) -> usize {
-
self.index
-
}
-
-
fn peek_to(&mut self, n: usize) {
-
while self.peeked.len() < n {
-
if let Some(b) = self.iter.next() {
-
self.peeked.push(b);
-
} else {
-
return;
-
}
-
}
-
}
-
-
pub fn next_is(&mut self, next: &[Base]) -> bool {
-
self.peek_to(next.len());
-
if self.peeked.len() < next.len() {
-
return false;
-
}
-
return &self.peeked[..next.len()] == next;
-
}
-
-
pub fn advance(&mut self, n: usize) {
-
self.peek_to(n);
-
self.index += n;
-
self.peeked.drain(..n);
-
}
-
-
pub fn nat(&mut self) -> Option<usize> {
-
let mut ret = 0;
-
let mut bit = 1;
-
loop {
-
if self.next_is(&[Base::P]) {
-
self.advance(1);
-
return Some(ret);
-
} else if self.next_is(&[Base::I]) || self.next_is(&[Base::F]) {
-
self.advance(1);
-
} else if self.next_is(&[Base::C]) {
-
ret += bit;
-
self.advance(1);
-
} else {
-
return None;
-
}
-
-
bit *= 2;
-
}
-
}
-
-
pub fn consts(&mut self) -> Vec<Base> {
-
let mut ret = Vec::new();
-
loop {
-
if self.next_is(&[Base::C]) {
-
self.advance(1);
-
ret.push(Base::I);
-
} else if self.next_is(&[Base::F]) {
-
self.advance(1);
-
ret.push(Base::C);
-
} else if self.next_is(&[Base::P]) {
-
self.advance(1);
-
ret.push(Base::F);
-
} else if self.next_is(&[Base::I, Base::C]) {
-
self.advance(2);
-
ret.push(Base::P);
-
} else {
-
return ret;
-
}
-
}
-
}
-
-
pub fn pattern(&mut self, rna: &mut Vec<Rna>) -> Option<Pattern> {
-
let mut ret = Vec::new();
-
let mut level = 0;
-
loop {
-
if self.next_is(&[Base::C]) {
-
self.advance(1);
-
ret.push(PatternItem::Base(Base::I));
-
} else if self.next_is(&[Base::F]) {
-
self.advance(1);
-
ret.push(PatternItem::Base(Base::C));
-
} else if self.next_is(&[Base::P]) {
-
self.advance(1);
-
ret.push(PatternItem::Base(Base::F));
-
} else if self.next_is(&[Base::I, Base::C]) {
-
self.advance(2);
-
ret.push(PatternItem::Base(Base::P));
-
} else if self.next_is(&[Base::I, Base::P]) {
-
self.advance(2);
-
let n = self.nat()?;
-
ret.push(PatternItem::Skip(n));
-
} else if self.next_is(&[Base::I, Base::F]) {
-
self.advance(3);
-
let s = self.consts();
-
ret.push(PatternItem::Search(s));
-
} else if self.next_is(&[Base::I, Base::I, Base::P]) {
-
self.advance(3);
-
level += 1;
-
ret.push(PatternItem::Open);
-
} else if self.next_is(&[Base::I, Base::I, Base::C])
-
|| self.next_is(&[Base::I, Base::I, Base::F])
-
{
-
self.advance(3);
-
if level == 0 {
-
return Some(Pattern::new(ret));
-
}
-
level -= 1;
-
ret.push(PatternItem::Close);
-
} else if self.next_is(&[Base::I, Base::I, Base::I]) {
-
self.advance(3);
-
self.peek_to(7);
-
let mut r = Vec::new();
-
mem::swap(&mut r, &mut self.peeked);
-
rna.push(r.try_into().unwrap());
-
self.index += 7;
-
} else {
-
return None;
-
}
-
}
-
}
-
-
pub fn template(&mut self, rna: &mut Vec<Rna>) -> Option<Template> {
-
let mut ret = Vec::new();
-
loop {
-
if self.next_is(&[Base::C]) {
-
self.advance(1);
-
ret.push(TemplateItem::Base(Base::I));
-
} else if self.next_is(&[Base::F]) {
-
self.advance(1);
-
ret.push(TemplateItem::Base(Base::C));
-
} else if self.next_is(&[Base::P]) {
-
self.advance(1);
-
ret.push(TemplateItem::Base(Base::F));
-
} else if self.next_is(&[Base::I, Base::C]) {
-
self.advance(2);
-
ret.push(TemplateItem::Base(Base::P));
-
} else if self.next_is(&[Base::I, Base::P]) || self.next_is(&[Base::I, Base::F]) {
-
self.advance(2);
-
let l = self.nat()?;
-
let n = self.nat()?;
-
ret.push(TemplateItem::Ref(n, l));
-
} else if self.next_is(&[Base::I, Base::I, Base::C])
-
|| self.next_is(&[Base::I, Base::I, Base::F])
-
{
-
self.advance(3);
-
return Some(Template::new(ret));
-
} else if self.next_is(&[Base::I, Base::I, Base::P]) {
-
self.advance(3);
-
let n = self.nat()?;
-
ret.push(TemplateItem::Len(n));
-
} else if self.next_is(&[Base::I, Base::I, Base::I]) {
-
self.advance(3);
-
self.peek_to(7);
-
let mut r = Vec::new();
-
mem::swap(&mut r, &mut self.peeked);
-
rna.push(r.try_into().unwrap());
-
self.index += 7;
-
} else {
-
return None;
-
}
-
}
-
}
-
}
-
-
#[cfg(test)]
-
mod tests {
-
use super::*;
-
-
fn dna_from_str(s: &str) -> Vec<Base> {
-
s.chars().filter_map(|c| Base::from_char(c)).collect()
-
}
-
-
#[test]
-
fn test_base() {
-
let dna = dna_from_str("ICFP").into_iter();
-
let mut parser = Parser::new(dna);
-
assert!(parser.next_is(&[Base::I]));
-
assert!(parser.next_is(&[Base::I, Base::C]));
-
assert!(parser.next_is(&[Base::I, Base::C, Base::F]));
-
assert!(parser.next_is(&[Base::I, Base::C, Base::F, Base::P]));
-
}
-
-
#[test]
-
fn test_nat() {
-
let dna = dna_from_str("CP").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(parser.nat(), Some(1));
-
assert_eq!(parser.index, 2);
-
-
let dna = dna_from_str("ICICP").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(parser.nat(), Some(10));
-
assert_eq!(parser.index, 5);
-
-
let dna = dna_from_str("III").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(parser.nat(), None);
-
assert_eq!(parser.index, 3);
-
}
-
-
#[test]
-
fn test_consts() {
-
let dna = dna_from_str("CFPICIIC").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(parser.consts(), &[Base::I, Base::C, Base::F, Base::P]);
-
assert_eq!(parser.index, 5);
-
}
-
-
#[test]
-
fn test_pattern() {
-
let mut rna = Vec::new();
-
-
let dna = dna_from_str("CIIC").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(
-
parser.pattern(&mut rna),
-
Some(Pattern::new(vec![PatternItem::Base(Base::I)]))
-
);
-
assert_eq!(parser.index, 4);
-
-
let dna = dna_from_str("IIPIPICPIICICIIF").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(
-
parser.pattern(&mut rna),
-
Some(Pattern::new(vec![
-
PatternItem::Open,
-
PatternItem::Skip(2),
-
PatternItem::Close,
-
PatternItem::Base(Base::P)
-
]))
-
);
-
assert_eq!(parser.index, 16);
-
-
let dna = dna_from_str("IIIPFCICFPIIC").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(parser.pattern(&mut rna), Some(Pattern::new(vec![])));
-
assert_eq!(parser.index, 13);
-
assert_eq!(
-
rna,
-
vec![[
-
Base::P,
-
Base::F,
-
Base::C,
-
Base::I,
-
Base::C,
-
Base::F,
-
Base::P
-
]]
-
);
-
}
-
-
#[test]
-
fn test_template() {
-
let mut rna = Vec::new();
-
-
let dna = dna_from_str("CFPICIFCPICPIIPIICPIIC").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(
-
parser.template(&mut rna),
-
Some(Template::new(vec![
-
TemplateItem::Base(Base::I),
-
TemplateItem::Base(Base::C),
-
TemplateItem::Base(Base::F),
-
TemplateItem::Base(Base::P),
-
TemplateItem::Ref(2, 1),
-
TemplateItem::Len(4)
-
]))
-
);
-
assert_eq!(parser.index, 22);
-
-
let dna = dna_from_str("IIIPFCICFPIIC").into_iter();
-
let mut parser = Parser::new(dna);
-
assert_eq!(parser.template(&mut rna), Some(Template::new(vec![])));
-
assert_eq!(parser.index, 13);
-
assert_eq!(
-
rna,
-
vec![[
-
Base::P,
-
Base::F,
-
Base::C,
-
Base::I,
-
Base::C,
-
Base::F,
-
Base::P
-
]]
-
);
-
}
-
}
···
-114
dna2rna/src/pattern.rs
···
-
use crate::dna::Base;
-
use std::fmt;
-
use std::slice;
-
use std::vec;
-
-
#[derive(Debug, PartialEq)]
-
pub enum PatternItem {
-
Base(Base),
-
Skip(usize),
-
Search(Vec<Base>),
-
Open,
-
Close,
-
}
-
-
impl fmt::Display for PatternItem {
-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-
match &self {
-
PatternItem::Base(b) => write!(f, "{}", b.to_char()),
-
PatternItem::Skip(n) => write!(f, "!{{{}}}", n),
-
PatternItem::Search(s) => {
-
write!(f, "?{{")?;
-
for b in s {
-
write!(f, "{}", b.to_char())?;
-
}
-
write!(f, "}}")?;
-
Ok(())
-
}
-
PatternItem::Open => write!(f, "("),
-
PatternItem::Close => write!(f, ")"),
-
}
-
}
-
}
-
-
#[derive(PartialEq, Debug)]
-
pub struct Pattern {
-
pattern: Vec<PatternItem>,
-
}
-
-
impl Pattern {
-
pub fn new(pattern: Vec<PatternItem>) -> Pattern {
-
Pattern { pattern: pattern }
-
}
-
-
pub fn iter<'a>(&'a self) -> slice::Iter<'a, PatternItem> {
-
self.pattern.iter()
-
}
-
-
pub fn into_iter<'a>(self) -> vec::IntoIter<PatternItem> {
-
self.pattern.into_iter()
-
}
-
}
-
-
impl fmt::Display for Pattern {
-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-
for p in self.iter() {
-
write!(f, "{}", p)?;
-
}
-
Ok(())
-
}
-
}
-
-
#[cfg(test)]
-
mod tests {
-
use super::*;
-
-
#[test]
-
fn test_display_base() {
-
assert_eq!(
-
Pattern::new(vec![
-
PatternItem::Base(Base::I),
-
PatternItem::Base(Base::C),
-
PatternItem::Base(Base::F),
-
PatternItem::Base(Base::P)
-
])
-
.to_string(),
-
"ICFP"
-
);
-
}
-
-
#[test]
-
fn test_display_skip() {
-
assert_eq!(Pattern::new(vec![PatternItem::Skip(5)]).to_string(), "!{5}");
-
}
-
-
#[test]
-
fn test_display_search() {
-
assert_eq!(
-
Pattern::new(vec![PatternItem::Search(vec![
-
Base::I,
-
Base::C,
-
Base::F,
-
Base::P
-
])])
-
.to_string(),
-
"?{ICFP}"
-
);
-
}
-
-
#[test]
-
fn test_display_group() {
-
assert_eq!(
-
Pattern::new(vec![
-
PatternItem::Open,
-
PatternItem::Base(Base::I),
-
PatternItem::Base(Base::C),
-
PatternItem::Base(Base::F),
-
PatternItem::Base(Base::P),
-
PatternItem::Close,
-
])
-
.to_string(),
-
"(ICFP)"
-
)
-
}
-
}
···
-3
dna2rna/src/rna.rs
···
-
use crate::dna::Base;
-
-
pub type Rna = [Base; 7];
···
-89
dna2rna/src/template.rs
···
-
use crate::dna::Base;
-
use std::fmt;
-
use std::slice;
-
use std::vec;
-
-
#[derive(Debug, PartialEq)]
-
pub enum TemplateItem {
-
Base(Base),
-
Ref(usize, usize),
-
Len(usize),
-
}
-
-
impl fmt::Display for TemplateItem {
-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-
match &self {
-
TemplateItem::Base(b) => write!(f, "{}", b.to_char()),
-
TemplateItem::Ref(n, l) => {
-
if *l == 0 {
-
write!(f, "{{{}}}", n)
-
} else {
-
write!(f, "{{{},{}}}", n, l)
-
}
-
}
-
TemplateItem::Len(n) => {
-
write!(f, "|{}|", n)
-
}
-
}
-
}
-
}
-
-
#[derive(Debug, PartialEq)]
-
pub struct Template {
-
template: Vec<TemplateItem>,
-
}
-
-
impl Template {
-
pub fn new(template: Vec<TemplateItem>) -> Template {
-
Template { template: template }
-
}
-
-
pub fn iter<'a>(&'a self) -> slice::Iter<'a, TemplateItem> {
-
self.template.iter()
-
}
-
-
pub fn into_iter<'a>(self) -> vec::IntoIter<TemplateItem> {
-
self.template.into_iter()
-
}
-
}
-
-
impl fmt::Display for Template {
-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-
for p in self.iter() {
-
write!(f, "{}", p)?;
-
}
-
Ok(())
-
}
-
}
-
-
#[cfg(test)]
-
mod tests {
-
use super::*;
-
-
#[test]
-
fn test_display_base() {
-
assert_eq!(
-
Template::new(vec![
-
TemplateItem::Base(Base::I),
-
TemplateItem::Base(Base::C),
-
TemplateItem::Base(Base::F),
-
TemplateItem::Base(Base::P)
-
])
-
.to_string(),
-
"ICFP"
-
);
-
}
-
-
#[test]
-
fn test_display_ref() {
-
assert_eq!(
-
Template::new(vec![TemplateItem::Ref(3, 2), TemplateItem::Ref(4, 0),]).to_string(),
-
"{3,2}{4}"
-
);
-
}
-
-
#[test]
-
fn test_display_lenf() {
-
assert_eq!(Template::new(vec![TemplateItem::Len(3)]).to_string(), "|3|");
-
}
-
}
···
+1
dna_parsing/.dir-locals.el
···
···
+
((nil . ((default-directory . "~/repos/endo/dna_parsing/"))))
+7
dna_parsing/Cargo.lock
···
···
+
# This file is automatically @generated by Cargo.
+
# It is not intended for manual editing.
+
version = 4
+
+
[[package]]
+
name = "dna_parsing"
+
version = "0.1.0"
+6
dna_parsing/Cargo.toml
···
···
+
[package]
+
name = "dna_parsing"
+
version = "0.1.0"
+
edition = "2024"
+
+
[dependencies]
+28
dna_parsing/src/base.rs
···
···
+
#[derive(Copy, Clone, PartialEq, Debug)]
+
pub enum Base {
+
I,
+
C,
+
F,
+
P,
+
}
+
+
impl Base {
+
pub fn from_char(c: char) -> Option<Base> {
+
match c {
+
'I' => Some(Base::I),
+
'C' => Some(Base::C),
+
'F' => Some(Base::F),
+
'P' => Some(Base::P),
+
_ => None,
+
}
+
}
+
+
pub fn to_char(&self) -> char {
+
match self {
+
Base::I => 'I',
+
Base::C => 'C',
+
Base::F => 'F',
+
Base::P => 'P',
+
}
+
}
+
}
+5
dna_parsing/src/lib.rs
···
···
+
pub mod base;
+
pub mod parser;
+
pub mod pattern;
+
pub mod rna;
+
pub mod template;
+315
dna_parsing/src/parser.rs
···
···
+
use crate::base::Base;
+
use crate::pattern::Pattern;
+
use crate::pattern::PatternItem;
+
use crate::rna::Rna;
+
use crate::template::Template;
+
use crate::template::TemplateItem;
+
use std::mem;
+
+
pub struct Parser<I>
+
where
+
I: Iterator<Item = Base>,
+
{
+
iter: I,
+
peeked: Vec<Base>,
+
index: usize,
+
}
+
+
impl<I> Parser<I>
+
where
+
I: Iterator<Item = Base>,
+
{
+
pub fn new(iter: I) -> Parser<I> {
+
Parser {
+
iter: iter,
+
peeked: Vec::new(),
+
index: 0,
+
}
+
}
+
+
pub fn index(&self) -> usize {
+
self.index
+
}
+
+
fn peek_to(&mut self, n: usize) {
+
while self.peeked.len() < n {
+
if let Some(b) = self.iter.next() {
+
self.peeked.push(b);
+
} else {
+
return;
+
}
+
}
+
}
+
+
pub fn next_is(&mut self, next: &[Base]) -> bool {
+
self.peek_to(next.len());
+
if self.peeked.len() < next.len() {
+
return false;
+
}
+
return &self.peeked[..next.len()] == next;
+
}
+
+
pub fn advance(&mut self, n: usize) {
+
self.peek_to(n);
+
self.index += n;
+
self.peeked.drain(..n);
+
}
+
+
pub fn nat(&mut self) -> Option<usize> {
+
let mut ret = 0;
+
let mut bit = 1;
+
loop {
+
if self.next_is(&[Base::P]) {
+
self.advance(1);
+
return Some(ret);
+
} else if self.next_is(&[Base::I]) || self.next_is(&[Base::F]) {
+
self.advance(1);
+
} else if self.next_is(&[Base::C]) {
+
ret += bit;
+
self.advance(1);
+
} else {
+
return None;
+
}
+
+
bit *= 2;
+
}
+
}
+
+
pub fn consts(&mut self) -> Vec<Base> {
+
let mut ret = Vec::new();
+
loop {
+
if self.next_is(&[Base::C]) {
+
self.advance(1);
+
ret.push(Base::I);
+
} else if self.next_is(&[Base::F]) {
+
self.advance(1);
+
ret.push(Base::C);
+
} else if self.next_is(&[Base::P]) {
+
self.advance(1);
+
ret.push(Base::F);
+
} else if self.next_is(&[Base::I, Base::C]) {
+
self.advance(2);
+
ret.push(Base::P);
+
} else {
+
return ret;
+
}
+
}
+
}
+
+
pub fn pattern(&mut self, rna: &mut Vec<Rna>) -> Option<Pattern> {
+
let mut ret = Vec::new();
+
let mut level = 0;
+
loop {
+
if self.next_is(&[Base::C]) {
+
self.advance(1);
+
ret.push(PatternItem::Base(Base::I));
+
} else if self.next_is(&[Base::F]) {
+
self.advance(1);
+
ret.push(PatternItem::Base(Base::C));
+
} else if self.next_is(&[Base::P]) {
+
self.advance(1);
+
ret.push(PatternItem::Base(Base::F));
+
} else if self.next_is(&[Base::I, Base::C]) {
+
self.advance(2);
+
ret.push(PatternItem::Base(Base::P));
+
} else if self.next_is(&[Base::I, Base::P]) {
+
self.advance(2);
+
let n = self.nat()?;
+
ret.push(PatternItem::Skip(n));
+
} else if self.next_is(&[Base::I, Base::F]) {
+
self.advance(3);
+
let s = self.consts();
+
ret.push(PatternItem::Search(s));
+
} else if self.next_is(&[Base::I, Base::I, Base::P]) {
+
self.advance(3);
+
level += 1;
+
ret.push(PatternItem::Open);
+
} else if self.next_is(&[Base::I, Base::I, Base::C])
+
|| self.next_is(&[Base::I, Base::I, Base::F])
+
{
+
self.advance(3);
+
if level == 0 {
+
return Some(Pattern::new(ret));
+
}
+
level -= 1;
+
ret.push(PatternItem::Close);
+
} else if self.next_is(&[Base::I, Base::I, Base::I]) {
+
self.advance(3);
+
self.peek_to(7);
+
let mut r = Vec::new();
+
mem::swap(&mut r, &mut self.peeked);
+
rna.push(r.try_into().unwrap());
+
self.index += 7;
+
} else {
+
return None;
+
}
+
}
+
}
+
+
pub fn template(&mut self, rna: &mut Vec<Rna>) -> Option<Template> {
+
let mut ret = Vec::new();
+
loop {
+
if self.next_is(&[Base::C]) {
+
self.advance(1);
+
ret.push(TemplateItem::Base(Base::I));
+
} else if self.next_is(&[Base::F]) {
+
self.advance(1);
+
ret.push(TemplateItem::Base(Base::C));
+
} else if self.next_is(&[Base::P]) {
+
self.advance(1);
+
ret.push(TemplateItem::Base(Base::F));
+
} else if self.next_is(&[Base::I, Base::C]) {
+
self.advance(2);
+
ret.push(TemplateItem::Base(Base::P));
+
} else if self.next_is(&[Base::I, Base::P]) || self.next_is(&[Base::I, Base::F]) {
+
self.advance(2);
+
let l = self.nat()?;
+
let n = self.nat()?;
+
ret.push(TemplateItem::Ref(n, l));
+
} else if self.next_is(&[Base::I, Base::I, Base::C])
+
|| self.next_is(&[Base::I, Base::I, Base::F])
+
{
+
self.advance(3);
+
return Some(Template::new(ret));
+
} else if self.next_is(&[Base::I, Base::I, Base::P]) {
+
self.advance(3);
+
let n = self.nat()?;
+
ret.push(TemplateItem::Len(n));
+
} else if self.next_is(&[Base::I, Base::I, Base::I]) {
+
self.advance(3);
+
self.peek_to(7);
+
let mut r = Vec::new();
+
mem::swap(&mut r, &mut self.peeked);
+
rna.push(r.try_into().unwrap());
+
self.index += 7;
+
} else {
+
return None;
+
}
+
}
+
}
+
}
+
+
#[cfg(test)]
+
mod tests {
+
use super::*;
+
+
fn dna_from_str(s: &str) -> Vec<Base> {
+
s.chars().filter_map(|c| Base::from_char(c)).collect()
+
}
+
+
#[test]
+
fn test_base() {
+
let dna = dna_from_str("ICFP").into_iter();
+
let mut parser = Parser::new(dna);
+
assert!(parser.next_is(&[Base::I]));
+
assert!(parser.next_is(&[Base::I, Base::C]));
+
assert!(parser.next_is(&[Base::I, Base::C, Base::F]));
+
assert!(parser.next_is(&[Base::I, Base::C, Base::F, Base::P]));
+
}
+
+
#[test]
+
fn test_nat() {
+
let dna = dna_from_str("CP").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(parser.nat(), Some(1));
+
assert_eq!(parser.index, 2);
+
+
let dna = dna_from_str("ICICP").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(parser.nat(), Some(10));
+
assert_eq!(parser.index, 5);
+
+
let dna = dna_from_str("III").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(parser.nat(), None);
+
assert_eq!(parser.index, 3);
+
}
+
+
#[test]
+
fn test_consts() {
+
let dna = dna_from_str("CFPICIIC").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(parser.consts(), &[Base::I, Base::C, Base::F, Base::P]);
+
assert_eq!(parser.index, 5);
+
}
+
+
#[test]
+
fn test_pattern() {
+
let mut rna = Vec::new();
+
+
let dna = dna_from_str("CIIC").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(
+
parser.pattern(&mut rna),
+
Some(Pattern::new(vec![PatternItem::Base(Base::I)]))
+
);
+
assert_eq!(parser.index, 4);
+
+
let dna = dna_from_str("IIPIPICPIICICIIF").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(
+
parser.pattern(&mut rna),
+
Some(Pattern::new(vec![
+
PatternItem::Open,
+
PatternItem::Skip(2),
+
PatternItem::Close,
+
PatternItem::Base(Base::P)
+
]))
+
);
+
assert_eq!(parser.index, 16);
+
+
let dna = dna_from_str("IIIPFCICFPIIC").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(parser.pattern(&mut rna), Some(Pattern::new(vec![])));
+
assert_eq!(parser.index, 13);
+
assert_eq!(
+
rna,
+
vec![[
+
Base::P,
+
Base::F,
+
Base::C,
+
Base::I,
+
Base::C,
+
Base::F,
+
Base::P
+
]]
+
);
+
}
+
+
#[test]
+
fn test_template() {
+
let mut rna = Vec::new();
+
+
let dna = dna_from_str("CFPICIFCPICPIIPIICPIIC").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(
+
parser.template(&mut rna),
+
Some(Template::new(vec![
+
TemplateItem::Base(Base::I),
+
TemplateItem::Base(Base::C),
+
TemplateItem::Base(Base::F),
+
TemplateItem::Base(Base::P),
+
TemplateItem::Ref(2, 1),
+
TemplateItem::Len(4)
+
]))
+
);
+
assert_eq!(parser.index, 22);
+
+
let dna = dna_from_str("IIIPFCICFPIIC").into_iter();
+
let mut parser = Parser::new(dna);
+
assert_eq!(parser.template(&mut rna), Some(Template::new(vec![])));
+
assert_eq!(parser.index, 13);
+
assert_eq!(
+
rna,
+
vec![[
+
Base::P,
+
Base::F,
+
Base::C,
+
Base::I,
+
Base::C,
+
Base::F,
+
Base::P
+
]]
+
);
+
}
+
}
+114
dna_parsing/src/pattern.rs
···
···
+
use crate::base::Base;
+
use std::fmt;
+
use std::slice;
+
use std::vec;
+
+
#[derive(Debug, PartialEq)]
+
pub enum PatternItem {
+
Base(Base),
+
Skip(usize),
+
Search(Vec<Base>),
+
Open,
+
Close,
+
}
+
+
impl fmt::Display for PatternItem {
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+
match &self {
+
PatternItem::Base(b) => write!(f, "{}", b.to_char()),
+
PatternItem::Skip(n) => write!(f, "!{{{}}}", n),
+
PatternItem::Search(s) => {
+
write!(f, "?{{")?;
+
for b in s {
+
write!(f, "{}", b.to_char())?;
+
}
+
write!(f, "}}")?;
+
Ok(())
+
}
+
PatternItem::Open => write!(f, "("),
+
PatternItem::Close => write!(f, ")"),
+
}
+
}
+
}
+
+
#[derive(PartialEq, Debug)]
+
pub struct Pattern {
+
pattern: Vec<PatternItem>,
+
}
+
+
impl Pattern {
+
pub fn new(pattern: Vec<PatternItem>) -> Pattern {
+
Pattern { pattern: pattern }
+
}
+
+
pub fn iter<'a>(&'a self) -> slice::Iter<'a, PatternItem> {
+
self.pattern.iter()
+
}
+
+
pub fn into_iter<'a>(self) -> vec::IntoIter<PatternItem> {
+
self.pattern.into_iter()
+
}
+
}
+
+
impl fmt::Display for Pattern {
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+
for p in self.iter() {
+
write!(f, "{}", p)?;
+
}
+
Ok(())
+
}
+
}
+
+
#[cfg(test)]
+
mod tests {
+
use super::*;
+
+
#[test]
+
fn test_display_base() {
+
assert_eq!(
+
Pattern::new(vec![
+
PatternItem::Base(Base::I),
+
PatternItem::Base(Base::C),
+
PatternItem::Base(Base::F),
+
PatternItem::Base(Base::P)
+
])
+
.to_string(),
+
"ICFP"
+
);
+
}
+
+
#[test]
+
fn test_display_skip() {
+
assert_eq!(Pattern::new(vec![PatternItem::Skip(5)]).to_string(), "!{5}");
+
}
+
+
#[test]
+
fn test_display_search() {
+
assert_eq!(
+
Pattern::new(vec![PatternItem::Search(vec![
+
Base::I,
+
Base::C,
+
Base::F,
+
Base::P
+
])])
+
.to_string(),
+
"?{ICFP}"
+
);
+
}
+
+
#[test]
+
fn test_display_group() {
+
assert_eq!(
+
Pattern::new(vec![
+
PatternItem::Open,
+
PatternItem::Base(Base::I),
+
PatternItem::Base(Base::C),
+
PatternItem::Base(Base::F),
+
PatternItem::Base(Base::P),
+
PatternItem::Close,
+
])
+
.to_string(),
+
"(ICFP)"
+
)
+
}
+
}
+3
dna_parsing/src/rna.rs
···
···
+
use crate::base::Base;
+
+
pub type Rna = [Base; 7];
+89
dna_parsing/src/template.rs
···
···
+
use crate::base::Base;
+
use std::fmt;
+
use std::slice;
+
use std::vec;
+
+
#[derive(Debug, PartialEq)]
+
pub enum TemplateItem {
+
Base(Base),
+
Ref(usize, usize),
+
Len(usize),
+
}
+
+
impl fmt::Display for TemplateItem {
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+
match &self {
+
TemplateItem::Base(b) => write!(f, "{}", b.to_char()),
+
TemplateItem::Ref(n, l) => {
+
if *l == 0 {
+
write!(f, "{{{}}}", n)
+
} else {
+
write!(f, "{{{},{}}}", n, l)
+
}
+
}
+
TemplateItem::Len(n) => {
+
write!(f, "|{}|", n)
+
}
+
}
+
}
+
}
+
+
#[derive(Debug, PartialEq)]
+
pub struct Template {
+
template: Vec<TemplateItem>,
+
}
+
+
impl Template {
+
pub fn new(template: Vec<TemplateItem>) -> Template {
+
Template { template: template }
+
}
+
+
pub fn iter<'a>(&'a self) -> slice::Iter<'a, TemplateItem> {
+
self.template.iter()
+
}
+
+
pub fn into_iter<'a>(self) -> vec::IntoIter<TemplateItem> {
+
self.template.into_iter()
+
}
+
}
+
+
impl fmt::Display for Template {
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+
for p in self.iter() {
+
write!(f, "{}", p)?;
+
}
+
Ok(())
+
}
+
}
+
+
#[cfg(test)]
+
mod tests {
+
use super::*;
+
+
#[test]
+
fn test_display_base() {
+
assert_eq!(
+
Template::new(vec![
+
TemplateItem::Base(Base::I),
+
TemplateItem::Base(Base::C),
+
TemplateItem::Base(Base::F),
+
TemplateItem::Base(Base::P)
+
])
+
.to_string(),
+
"ICFP"
+
);
+
}
+
+
#[test]
+
fn test_display_ref() {
+
assert_eq!(
+
Template::new(vec![TemplateItem::Ref(3, 2), TemplateItem::Ref(4, 0),]).to_string(),
+
"{3,2}{4}"
+
);
+
}
+
+
#[test]
+
fn test_display_lenf() {
+
assert_eq!(Template::new(vec![TemplateItem::Len(3)]).to_string(), "|3|");
+
}
+
}
+20
generate_crate_rule.py
···
···
+
import sys
+
+
# 'lib' or 'bin'
+
crate_type = sys.argv[1]
+
crate_name = sys.argv[2]
+
if crate_type == "bin":
+
input_rs = f"{crate_name}/src/main.rs"
+
outfile = f"out/bin/{crate_name}"
+
else:
+
input_rs = f"{crate_name}/src/lib.rs"
+
outfile = f"out/lib/lib{crate_name}.rlib"
+
+
dep_crates = sys.argv[3:]
+
dep_inputs = " ".join([f"out/lib/lib{dep}.rlib" for dep in dep_crates])
+
externs = " ".join([f"--extern {dep}=out/lib/lib{dep}.rlib" for dep in dep_crates])
+
+
flags = "--edition=2024 -C opt-level=3 -C embed-bitcode=no -C strip=debuginfo --emit=link"
+
+
inputs = f"{crate_name}/src/*.rs"
+
print(f": {crate_name}/src/*.rs {dep_inputs} |> rustc --crate-name {crate_name} --crate-type={crate_type} {input_rs} -o %o {externs} {flags} |> {outfile}")