···
1
+
use crate::dna::Base;
2
+
use crate::dna::DnaRef;
3
+
use crate::parser::Parser;
4
+
use crate::pattern::Pattern;
5
+
use crate::pattern::PatternItem;
7
+
use crate::template::TemplateItem;
11
+
groups: Vec<(usize, usize)>,
14
+
fn do_match(dna: &DnaRef, start: usize, pattern: &Pattern) -> Option<MatchResult> {
15
+
let mut index = start;
16
+
let mut env = Vec::new();
17
+
let mut opens = Vec::new();
18
+
for p in pattern.iter() {
20
+
PatternItem::Base(b) => {
21
+
if index >= dna.len() || dna[index] != *b {
27
+
PatternItem::Skip(n) => {
29
+
if index > dna.len() {
33
+
PatternItem::Search(s) => {
34
+
let mut fallback = Vec::new();
35
+
fallback.reserve(s.len());
38
+
for i in 2..s.len() {
39
+
let mut j = fallback[i - 1];
40
+
while j > 0 && s[j] != s[i - 1] {
43
+
if s[i - 1] == s[j] {
44
+
fallback.push(j + 1);
54
+
} else if index >= dna.len() {
56
+
} else if dna[index] == s[cur] {
59
+
} else if cur == 0 {
62
+
cur = fallback[cur];
66
+
PatternItem::Open => {
69
+
PatternItem::Close => {
70
+
let start = opens.pop()?;
71
+
env.push((start, index));
76
+
return Some(MatchResult {
82
+
pub fn protect(dna: DnaRef, level: usize) -> DnaRef {
87
+
let mut cur = dna.clone();
91
+
.flat_map(|b| match b {
92
+
Base::I => [Base::C].iter(),
93
+
Base::C => [Base::F].iter(),
94
+
Base::F => [Base::P].iter(),
95
+
Base::P => [Base::I, Base::C].iter(),
97
+
.map(|b| DnaRef::from_base(*b))
98
+
.collect::<DnaRef>();
104
+
pub fn asnat(n: usize) -> DnaRef {
105
+
let mut v = Vec::new();
117
+
return v.iter().map(|b| DnaRef::from_base(*b)).collect::<DnaRef>();
120
+
pub fn match_replace(dna: DnaRef, rna: &mut Vec<Rna>) -> Option<DnaRef> {
121
+
let mut parser = Parser::new(&dna);
122
+
let pattern = parser.pattern(rna)?;
123
+
let template = parser.template(rna)?;
124
+
let index = parser.index();
126
+
if let Some(matched) = do_match(&dna, index, &pattern) {
127
+
let mut replace = DnaRef::new();
128
+
for t in template.into_iter() {
130
+
TemplateItem::Base(b) => {
131
+
// TODO: Implement AddAssign
132
+
replace = replace + DnaRef::from_base(b);
134
+
TemplateItem::Ref(n, l) => {
135
+
let (start, end) = matched.groups[n];
136
+
let (_, rhs) = dna.split(start);
137
+
let (group, _) = rhs.split(end - start);
138
+
replace = replace + protect(group, l);
140
+
TemplateItem::Len(n) => {
141
+
let (start, end) = matched.groups[n];
142
+
replace = replace + asnat(end - start);
146
+
let (_, remainder) = dna.split(matched.end);
147
+
return Some(replace + remainder);
149
+
let (_, rhs) = dna.split(index);
159
+
fn test_match_bases() {
160
+
// ICFP -> III on ICFP
161
+
let dna = DnaRef::from_string("CFPICIIC CCCIIC ICFP");
162
+
let mut rna = Vec::new();
163
+
let res = match_replace(dna, &mut rna);
164
+
assert!(res.is_some());
165
+
assert_eq!(res.unwrap().to_string(), "III");
169
+
fn test_match_skip() {
170
+
// !{10} -> III on ICFPICFPICFP
171
+
let dna = DnaRef::from_string("IPICICPIIC CCCIIC ICFPICFPICFP");
172
+
let mut rna = Vec::new();
173
+
let res = match_replace(dna, &mut rna);
174
+
assert!(res.is_some());
175
+
assert_eq!(res.unwrap().to_string(), "IIIFP");
179
+
fn test_match_search() {
180
+
// ?{IIIC} -> <empty> on ICIICIIICICFP
181
+
let dna = DnaRef::from_string("IFFCCCFIIC IIC ICIICIIICICFP");
182
+
let mut rna = Vec::new();
183
+
let res = match_replace(dna, &mut rna);
184
+
assert!(res.is_some());
185
+
assert_eq!(res.unwrap().to_string(), "ICFP");
189
+
fn test_match_groups() {
190
+
// (!{1})(!{1})(!{1})(!{1}) -> {3}{2}{1}{0} on ICFP
191
+
let dna = DnaRef::from_string(
192
+
"IIPIPCPIICIIPIPCPIICIIPIPCPIICIIPIPCPIICIIC IPPCCPIPPICPIPPCPIPPPIIC ICFP",
194
+
let mut rna = Vec::new();
195
+
let res = match_replace(dna, &mut rna);
196
+
assert!(res.is_some());
197
+
assert_eq!(res.unwrap().to_string(), "PFCI");
201
+
fn test_match_protect() {
202
+
// (!{4}) -> {0}{0,1}{0,2}{0,3} on ICFP
203
+
let dna = DnaRef::from_string("IIPIPIICPIICIIC IPPPIPCPPIPICPPIPCCPPIIC ICFP");
204
+
let mut rna = Vec::new();
205
+
let res = match_replace(dna, &mut rna);
206
+
assert!(res.is_some());
207
+
assert_eq!(res.unwrap().to_string(), "ICFPCFPICFPICCFPICCFFP");
211
+
fn test_match_asnat() {
212
+
// (!{10}) -> |0| on ICFPICFPICFP
213
+
let dna = DnaRef::from_string("IIPIPICICPIICIIC IIPPIIC ICFPICFPICFP");
214
+
let mut rna = Vec::new();
215
+
let res = match_replace(dna, &mut rna);
216
+
assert!(res.is_some());
217
+
assert_eq!(res.unwrap().to_string(), "ICICPFP");
221
+
fn test_match_rna() {
222
+
// RIPIPIPI -> RCFCFCFC on ICFP
223
+
let dna = DnaRef::from_string("IIIIPIPIPIIIC IIICFCFCFCIIC ICFP");
224
+
let mut rna = Vec::new();
225
+
let res = match_replace(dna, &mut rna);
226
+
assert!(res.is_some());
227
+
assert_eq!(res.unwrap().to_string(), "ICFP");
254
+
fn test_from_task() {
255
+
let dna = DnaRef::from_string("IIPIPICPIICICIIFICCIFPPIICCFPC");
256
+
let mut rna = Vec::new();
257
+
let res = match_replace(dna, &mut rna);
258
+
assert!(res.is_some());
259
+
assert_eq!(res.unwrap().to_string(), "PICFC");
261
+
let dna = DnaRef::from_string("IIPIPICPIICICIIFICCIFCCCPPIICCFPC");
262
+
let mut rna = Vec::new();
263
+
let res = match_replace(dna, &mut rna);
264
+
assert!(res.is_some());
265
+
assert_eq!(res.unwrap().to_string(), "PIICCFCFFPC");
267
+
let dna = DnaRef::from_string("IIPIPIICPIICIICCIICFCFC");
268
+
let mut rna = Vec::new();
269
+
let res = match_replace(dna, &mut rna);
270
+
assert!(res.is_some());
271
+
assert_eq!(res.unwrap().to_string(), "I");