open System; open System.Collections.Generic; type dna = A | C | G | T;; let DNASTR = "ACGT" // translates 0,1,2,3 to printable DNA symbol let STRDNA = Dictionary(); STRDNA.['A'] <- A STRDNA.['C'] <- C STRDNA.['G'] <- G STRDNA.['T'] <- T // convert dna-string to list of type dna values let stringdna (s:string) = let mutable dnalist = [] let mutable i = s.Length-1 // decrement from end to preserve order while i>=0 do dnalist <- STRDNA.[ s.[i] ] :: dnalist i <- i-1 dnalist /// // What's wrong with using strings? // let yourdna = stringdna "I AM A FARM ANIMAL"; // this can't possibly be detected at compile time, because to the // compiler all strings are the same, they're called strings. //let hisdna = [A;C;G;F;R;M]; // compiler type error let CODEDNA = [|A;C;G;T|] // array index translates to type dna let DNACODE x = // convert DNA value to 2-bit binary values match x with | A -> 0 | C -> 1 | G -> 2 | T -> 3;; // convert list of DNA symbols to list of 32 bit integers, each int // can encode 16 DNA symbols. The length of original sequence is stored // via the lref reference, since the length may not be a multiple of 16 let dnaint (ds:dna list) lref = let mutable dsq = ds // lref is a reference, for storing length lref := ds.Length; // record length of original sequence while dsq.Length%16<>0 do dsq <- A::dsq // add dummy A's to front so %8=0 let mutable intlist = [] let mutable i = (dsq.Length-1) let mutable k,ax = 0,0 while i>0 do ax <- 0; k <- i while k>= i-15 do ax <- ax+DNACODE(dsq.[k]) if k>i-15 then ax <- ax*4 // shift left 2 bits k <- k-1 // inner while intlist <- ax::intlist i <- i-16 // outer while intlist;; let intdna (intl:int list) len = // convert integer list to dna sequence of len let mutable dnalist = [] let mutable i = intl.Length-1 while i>=0 do let mutable ai = intl.[i] for k in 0..15 do dnalist <- (CODEDNA.[ai%4]) :: dnalist ai <- ai/4 // right-shift 4 bits i <- i-1 // while let dl = dnalist.Length dnalist <- dnalist.[(dl-len)..(dl-1)] // trim dnalist;; let rec reverse ax m = match m with | [] -> ax | car::cdr -> reverse (car::ax) cdr let len = ref 0 let x = dnaint [A;C;G;T;G;C;A;C;C;T;G;G;A;T;G;C] len Console.WriteLine(string(x)) let y = reverse [] (intdna x !len) for c in y do printf "%A" c printfn ""