ICFP 2007 Contest: https://web.archive.org/web/20090301164728/https://save-endo.cs.uu.nl/
1use crate::dna::Base;
2use crate::dna::DnaRef;
3use crate::pattern::Pattern;
4use crate::pattern::PatternItem;
5use crate::rna::Rna;
6use crate::template::Template;
7use crate::template::TemplateItem;
8
9pub struct Parser<'a> {
10 buf: &'a DnaRef,
11 index: usize,
12}
13
14impl<'a> Parser<'a> {
15 pub fn new(buf: &'a DnaRef) -> Parser<'a> {
16 Parser { buf: buf, index: 0 }
17 }
18
19 pub fn index(&self) -> usize {
20 self.index
21 }
22
23 pub fn next_is(&mut self, next: &[Base]) -> bool {
24 if self.index + next.len() > self.buf.len() {
25 return false;
26 }
27
28 for i in 0..next.len() {
29 if self.buf[self.index + i] != next[i] {
30 return false;
31 }
32 }
33
34 return true;
35 }
36
37 pub fn nat(&mut self) -> Option<usize> {
38 let mut ret = 0;
39 let mut bit = 1;
40 loop {
41 if self.next_is(&[Base::P]) {
42 self.index += 1;
43 return Some(ret);
44 } else if self.next_is(&[Base::I]) || self.next_is(&[Base::F]) {
45 self.index += 1;
46 } else if self.next_is(&[Base::C]) {
47 ret += bit;
48 self.index += 1;
49 } else {
50 return None;
51 }
52
53 bit *= 2;
54 }
55 }
56
57 pub fn consts(&mut self) -> Vec<Base> {
58 let mut ret = Vec::new();
59 loop {
60 if self.next_is(&[Base::C]) {
61 self.index += 1;
62 ret.push(Base::I);
63 } else if self.next_is(&[Base::F]) {
64 self.index += 1;
65 ret.push(Base::C);
66 } else if self.next_is(&[Base::P]) {
67 self.index += 1;
68 ret.push(Base::F);
69 } else if self.next_is(&[Base::I, Base::C]) {
70 self.index += 2;
71 ret.push(Base::P);
72 } else {
73 return ret;
74 }
75 }
76 }
77
78 pub fn pattern(&mut self, rna: &mut Vec<Rna>) -> Option<Pattern> {
79 let mut ret = Vec::new();
80 let mut level = 0;
81 loop {
82 if self.next_is(&[Base::C]) {
83 self.index += 1;
84 ret.push(PatternItem::Base(Base::I));
85 } else if self.next_is(&[Base::F]) {
86 self.index += 1;
87 ret.push(PatternItem::Base(Base::C));
88 } else if self.next_is(&[Base::P]) {
89 self.index += 1;
90 ret.push(PatternItem::Base(Base::F));
91 } else if self.next_is(&[Base::I, Base::C]) {
92 self.index += 2;
93 ret.push(PatternItem::Base(Base::P));
94 } else if self.next_is(&[Base::I, Base::P]) {
95 self.index += 2;
96 let n = self.nat()?;
97 ret.push(PatternItem::Skip(n));
98 } else if self.next_is(&[Base::I, Base::F]) {
99 self.index += 3;
100 let s = self.consts();
101 ret.push(PatternItem::Search(s));
102 } else if self.next_is(&[Base::I, Base::I, Base::P]) {
103 self.index += 3;
104 level += 1;
105 ret.push(PatternItem::Open);
106 } else if self.next_is(&[Base::I, Base::I, Base::C])
107 || self.next_is(&[Base::I, Base::I, Base::F])
108 {
109 self.index += 3;
110 if level == 0 {
111 return Some(ret);
112 }
113 level -= 1;
114 ret.push(PatternItem::Close);
115 } else if self.next_is(&[Base::I, Base::I, Base::I]) {
116 self.index += 3;
117 let mut new_rna = Vec::new();
118 for i in 0..7 {
119 new_rna.push(self.buf[self.index + i]);
120 }
121 self.index += 7;
122 rna.push(new_rna.try_into().unwrap());
123 } else {
124 return None;
125 }
126 }
127 }
128
129 pub fn template(&mut self, rna: &mut Vec<Rna>) -> Option<Template> {
130 let mut ret = Vec::new();
131 loop {
132 if self.next_is(&[Base::C]) {
133 self.index += 1;
134 ret.push(TemplateItem::Base(Base::I));
135 } else if self.next_is(&[Base::F]) {
136 self.index += 1;
137 ret.push(TemplateItem::Base(Base::C));
138 } else if self.next_is(&[Base::P]) {
139 self.index += 1;
140 ret.push(TemplateItem::Base(Base::F));
141 } else if self.next_is(&[Base::I, Base::C]) {
142 self.index += 2;
143 ret.push(TemplateItem::Base(Base::P));
144 } else if self.next_is(&[Base::I, Base::P]) || self.next_is(&[Base::I, Base::F]) {
145 self.index += 2;
146 let l = self.nat()?;
147 let n = self.nat()?;
148 ret.push(TemplateItem::Ref(n, l));
149 } else if self.next_is(&[Base::I, Base::I, Base::C])
150 || self.next_is(&[Base::I, Base::I, Base::F])
151 {
152 self.index += 3;
153 return Some(ret);
154 } else if self.next_is(&[Base::I, Base::I, Base::P]) {
155 self.index += 3;
156 let n = self.nat()?;
157 ret.push(TemplateItem::Len(n));
158 } else if self.next_is(&[Base::I, Base::I, Base::I]) {
159 self.index += 3;
160 let mut new_rna = Vec::new();
161 for i in 0..7 {
162 new_rna.push(self.buf[self.index + i]);
163 }
164 self.index += 7;
165 rna.push(new_rna.try_into().unwrap());
166 } else {
167 return None;
168 }
169 }
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_base() {
179 let dna = DnaRef::from_string("ICFP");
180 let mut parser = Parser::new(&dna);
181 assert!(parser.next_is(&[Base::I]));
182 assert!(parser.next_is(&[Base::I, Base::C]));
183 assert!(parser.next_is(&[Base::I, Base::C, Base::F]));
184 assert!(parser.next_is(&[Base::I, Base::C, Base::F, Base::P]));
185 }
186
187 #[test]
188 fn test_nat() {
189 let dna = DnaRef::from_string("CP");
190 let mut parser = Parser::new(&dna);
191 assert_eq!(parser.nat(), Some(1));
192 assert_eq!(parser.index, 2);
193
194 let dna = DnaRef::from_string("ICICP");
195 let mut parser = Parser::new(&dna);
196 assert_eq!(parser.nat(), Some(10));
197 assert_eq!(parser.index, 5);
198
199 let dna = DnaRef::from_string("III");
200 let mut parser = Parser::new(&dna);
201 assert_eq!(parser.nat(), None);
202 assert_eq!(parser.index, 3);
203 }
204
205 #[test]
206 fn test_consts() {
207 let dna = DnaRef::from_string("CFPICIIC");
208 let mut parser = Parser::new(&dna);
209 assert_eq!(parser.consts(), &[Base::I, Base::C, Base::F, Base::P]);
210 assert_eq!(parser.index, 5);
211 }
212
213 #[test]
214 fn test_pattern() {
215 let mut rna = Vec::new();
216
217 let dna = DnaRef::from_string("CIIC");
218 let mut parser = Parser::new(&dna);
219 assert_eq!(
220 parser.pattern(&mut rna),
221 Some(vec![PatternItem::Base(Base::I)])
222 );
223 assert_eq!(parser.index, 4);
224
225 let dna = DnaRef::from_string("IIPIPICPIICICIIF");
226 let mut parser = Parser::new(&dna);
227 assert_eq!(
228 parser.pattern(&mut rna),
229 Some(vec![
230 PatternItem::Open,
231 PatternItem::Skip(2),
232 PatternItem::Close,
233 PatternItem::Base(Base::P)
234 ])
235 );
236 assert_eq!(parser.index, 16);
237
238 let dna = DnaRef::from_string("IIIPFCICFPIIC");
239 let mut parser = Parser::new(&dna);
240 assert_eq!(parser.pattern(&mut rna), Some(vec![]));
241 assert_eq!(parser.index, 13);
242 assert_eq!(
243 rna,
244 vec![[
245 Base::P,
246 Base::F,
247 Base::C,
248 Base::I,
249 Base::C,
250 Base::F,
251 Base::P
252 ]]
253 );
254 }
255
256 #[test]
257 fn test_template() {
258 let mut rna = Vec::new();
259
260 let dna = DnaRef::from_string("CFPICIFCPICPIIPIICPIIC");
261 let mut parser = Parser::new(&dna);
262 assert_eq!(
263 parser.template(&mut rna),
264 Some(vec![
265 TemplateItem::Base(Base::I),
266 TemplateItem::Base(Base::C),
267 TemplateItem::Base(Base::F),
268 TemplateItem::Base(Base::P),
269 TemplateItem::Ref(2, 1),
270 TemplateItem::Len(4)
271 ])
272 );
273 assert_eq!(parser.index, 22);
274
275 let dna = DnaRef::from_string("IIIPFCICFPIIC");
276 let mut parser = Parser::new(&dna);
277 assert_eq!(parser.template(&mut rna), Some(vec![]));
278 assert_eq!(parser.index, 13);
279 assert_eq!(
280 rna,
281 vec![[
282 Base::P,
283 Base::F,
284 Base::C,
285 Base::I,
286 Base::C,
287 Base::F,
288 Base::P
289 ]]
290 );
291 }
292}