5 use std::cast::transmute;
7 use std::libc::{STDIN_FILENO, c_int, fdopen, fgets, fileno, fopen, fstat};
8 use std::libc::{stat, strlen};
10 use std::unstable::intrinsics::init;
11 use std::vec::{reverse};
12 use extra::sort::quick_sort3;
14 static LINE_LEN: uint = 80;
15 static TABLE: [u8, ..4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ];
16 static TABLE_SIZE: uint = 2 << 16;
18 static OCCURRENCES: [&'static str, ..5] = [
26 // Code implementation
32 fn hash(&self) -> u64 {
37 fn push_char(&self, c: u8) -> Code {
38 Code((**self << 2) + (pack_symbol(c) as u64))
41 fn rotate(&self, c: u8, frame: i32) -> Code {
42 Code(*self.push_char(c) & ((1u64 << (2 * (frame as u64))) - 1))
45 fn pack(string: &str) -> Code {
46 let mut code = Code(0u64);
47 for i in range(0u, string.len()) {
48 code = code.push_char(string[i]);
54 fn unpack(&self, frame: i32) -> ~str {
57 do (frame as uint).times {
58 result.push(unpack_symbol((key as u8) & 3));
63 str::from_bytes(result)
67 // Hash table implementation
70 fn f(&self, entry: &mut Entry);
75 impl TableCallback for BumpCallback {
76 fn f(&self, entry: &mut Entry) {
81 struct PrintCallback(&'static str);
83 impl TableCallback for PrintCallback {
84 fn f(&self, entry: &mut Entry) {
85 printfln!("%d\t%s", entry.count as int, **self);
97 items: [Option<~Entry>, ..TABLE_SIZE]
104 items: [ None, ..TABLE_SIZE ],
108 fn search_remainder<C:TableCallback>(item: &mut Entry, key: Code, c: C) {
111 let mut entry = ~Entry {
117 item.next = Some(entry);
119 Some(ref mut entry) => {
120 if entry.code == key {
125 Table::search_remainder(*entry, key, c)
130 fn lookup<C:TableCallback>(&mut self, key: Code, c: C) {
131 let index = *key % (TABLE_SIZE as u64);
134 if self.items[index].is_none() {
135 let mut entry = ~Entry {
141 self.items[index] = Some(entry);
147 let mut entry = &mut *self.items[index].get_mut_ref();
148 if entry.code == key {
153 Table::search_remainder(*entry, key, c)
157 fn each(&self, f: &fn(entry: &Entry) -> bool) {
158 for self.items.each |item| {
162 let mut item: &Entry = *item;
170 Some(ref next_item) => item = &**next_item,
181 fn pack_symbol(c: u8) -> u8 {
183 'a' as u8 | 'A' as u8 => 0,
184 'c' as u8 | 'C' as u8 => 1,
185 'g' as u8 | 'G' as u8 => 2,
186 't' as u8 | 'T' as u8 => 3,
187 _ => fail!(c.to_str())
191 fn unpack_symbol(c: u8) -> u8 {
195 fn next_char<'a>(mut buf: &'a [u8]) -> &'a [u8] {
197 buf = buf.slice(1, buf.len());
201 if buf[0] != (' ' as u8) && buf[0] != ('\t' as u8) &&
202 buf[0] != ('\n' as u8) && buf[0] != 0 {
210 fn read_stdin() -> ~[u8] {
213 //let stdin = fdopen(STDIN_FILENO as c_int, transmute(&mode[0]));
214 let path = "knucleotide-input.txt";
215 let stdin = fopen(transmute(&path[0]), transmute(&mode[0]));
217 let mut st: stat = init();
218 fstat(fileno(stdin), &mut st);
219 let mut buf = vec::from_elem(st.st_size as uint, 0);
221 let header = ">THREE".as_bytes();
224 let mut window: &mut [u8] = buf;
226 fgets(transmute(&mut window[0]), LINE_LEN as c_int, stdin);
229 if window.slice(0, 6) == header {
235 while fgets(transmute(&mut window[0]),
238 window = window.mut_slice(strlen(transmute(&window[0])) as uint, window.len());
247 #[fixed_stack_segment]
248 fn generate_frequencies(frequencies: &mut Table,
251 let mut code = Code(0);
254 do (frame as uint).times {
255 code = code.push_char(input[0]);
256 input = next_char(input);
258 frequencies.lookup(code, BumpCallback);
260 while input.len() != 0 && input[0] != ('>' as u8) {
261 code = code.rotate(input[0], frame);
262 frequencies.lookup(code, BumpCallback);
263 input = next_char(input);
268 #[fixed_stack_segment]
269 fn print_frequencies(frequencies: &Table, frame: i32) {
270 let mut vector = ~[];
271 for frequencies.each |entry| {
272 vector.push((entry.code, entry.count));
276 let mut total_count = 0;
277 for vector.each |&(_, count)| {
278 total_count += count;
281 for vector.each |&(key, count)| {
284 (count as float * 100.0) / (total_count as float));
288 fn print_occurrences(frequencies: &mut Table, occurrence: &'static str) {
289 frequencies.lookup(Code::pack(occurrence), PrintCallback(occurrence))
292 #[fixed_stack_segment]
294 let input = read_stdin();
296 let mut frequencies = ~Table::new();
297 generate_frequencies(frequencies, input, 1);
298 print_frequencies(frequencies, 1);
300 *frequencies = Table::new();
301 generate_frequencies(frequencies, input, 2);
302 print_frequencies(frequencies, 2);
304 for range(0, 5) |i| {
305 let occurrence = OCCURRENCES[i];
306 *frequencies = Table::new();
307 generate_frequencies(frequencies,
309 occurrence.len() as i32);
310 print_occurrences(frequencies, occurrence);