/* The Computer Language Shootout
http://shootout.alioth.debian.org/
contributed by Isaac Gouy
*/
import java.io._
object fasta {
def main(args: Array[String]) = {
val ALU =
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"
val _IUB = Array(
('a', 0.27),
('c', 0.12),
('g', 0.12),
('t', 0.27),
('B', 0.02),
('D', 0.02),
('H', 0.02),
('K', 0.02),
('M', 0.02),
('N', 0.02),
('R', 0.02),
('S', 0.02),
('V', 0.02),
('W', 0.02),
('Y', 0.02)
)
val IUB = makeCumulative(_IUB)
val _HomoSapiens = Array(
('a', 0.3029549426680),
('c', 0.1979883004921),
('g', 0.1975473066391),
('t', 0.3015094502008)
)
val HomoSapiens = makeCumulative(_HomoSapiens)
val n = Integer parseInt(args(0))
val s = new FastaOutputStream(System.out)
s.writeDescription("ONE Homo sapiens alu")
s.writeRepeatingSequence(ALU,n*2)
s.writeDescription("TWO IUB ambiguity codes")
s.writeRandomSequence(IUB,n*3)
s.writeDescription("THREE Homo sapiens frequency")
s.writeRandomSequence(HomoSapiens,n*5)
s.close
}
def makeCumulative(a: Array[Tuple2[Char,Double]]) = {
var cp = 0.0
a map (frequency =>
frequency match {
case (code,percent) =>
cp = cp + percent; new Frequency(code.toByte,cp)
}
)
}
}
// We could use instances of Pair or Tuple2 but specific labels
// make the code more readable than index numbers
class Frequency(_code: Byte, _percent: Double){
var code = _code; var percent = _percent;
}
// extend the Java BufferedOutputStream class
class FastaOutputStream(out: OutputStream) extends BufferedOutputStream(out) {
private val LineLength = 60
private val nl = '\n'.toByte
def writeDescription(desc: String) = { write( (">" + desc + "\n").getBytes ) }
def writeRepeatingSequence(_alu: String, length: Int) = {
val alu = _alu.getBytes
var n = length; var k = 0; val kn = alu.length;
while (n > 0) {
val m = if (n < LineLength) n else LineLength
var i = 0
while (i < m){
if (k == kn) k = 0
val b = alu(k)
if (count < buf.length){ buf(count) = b; count = count + 1 }
else { write(b) } // flush buffer
k = k+1
i = i+1
}
write(nl)
n = n - LineLength
}
}
def writeRandomSequence(distribution: Array[Frequency], length: Int) = {
var n = length
while (n > 0) {
val m = if (n < LineLength) n else LineLength
var i = 0
while (i < m){
val b = selectRandom(distribution)
if (count < buf.length){ buf(count) = b; count = count + 1 }
else { write(b) } // flush buffer
i = i+1
}
if (count < buf.length){ buf(count) = nl; count = count + 1 }
else { write(nl) } // flush buffer
n = n - LineLength
}
}
private def selectRandom(distribution: Array[Frequency]): Byte = {
val n = distribution.length
val r = RandomNumber scaledTo(1.0)
var i = 0
while (i < n) {
if (r < distribution(i).percent) return distribution(i).code
i = i+1
}
return distribution(n-1).code
}
}
object RandomNumber {
private val IM = 139968
private val IA = 3877
private val IC = 29573
private var seed = 42
def scaledTo(max: Double) = {
seed = (seed * IA + IC) % IM
max * seed / IM
}
}