summaryrefslogtreecommitdiff
path: root/test/pending/shootout/revcomp.scala-3.scala
blob: 39a04091273852dbaac2ef4b51a1870d08389f0c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* The Computer Language Shootout
   http://shootout.alioth.debian.org/
   contributed by Isaac Gouy
*/

import java.io._
import scala.collection.mutable.Stack

object revcomp {
   def main(args: Array[String]) = {
      val out = new FastaOutputStream(System.out)
      val in = new FastaInputStream(System.in)

      out.writeReverseComplement( in.readSequenceStack )
      out.writeReverseComplement( in.readSequenceStack )
      out.writeReverseComplement( in.readSequenceStack )

      in.close
      out.close
   }
}


trait FastaByteStream {
   val nl = '\n'.toByte

   type Line = Array[Byte]
   type LineStack = Stack[Line]
}


// extend the Java BufferedInputStream class

final class FastaInputStream(in: InputStream)
      extends BufferedInputStream(in) with FastaByteStream {

   val gt = '>'.toByte
   val sc = ';'.toByte

   def readSequenceStack(): Tuple2[Line,LineStack] = {
      var header: Line = null
      val lines: LineStack = new Stack

      var line = readLine()
      while (line != null) {
         val c = line(0)
         if (c == gt){                       // '>'
            if (header == null){
               header = line
            } else {
               pos = pos - line.length - 1   // reposition to start of line
               return (header,lines)
            }
         } else {
            if (c != sc) lines push line       // ';'
         }
         line = readLine()
      }
      return (header,lines)
   }

   def readLine() = {
      var bytes: Line = null
      if (in == null) bytes
      else {
         mark(128)                      // mark the start of the line
         if (count == 0) read()         // fill buffer

         var i = markpos
         while (i < count && buf(i) != nl) i = i + 1

         if (i >= count){               // line extends past end of buffer
            pos = i; read(); i = pos;   // fill buffer again
            while (i < count && buf(i) != nl) i = i + 1
         }

         if (i < count){
            bytes = new Array(i - markpos)
            System.arraycopy(buf, markpos, bytes, 0, i - markpos);
            pos = i+1
         }
      }
      bytes
   }
}


// extend the Java BufferedOutputStream class

final class FastaOutputStream(in: OutputStream)
      extends BufferedOutputStream(in) with FastaByteStream {

   private val IUB = IUBCodeComplements

   private def IUBCodeComplements() = {
      val code = "ABCDGHKMNRSTVWYabcdghkmnrstvwy".getBytes
      val comp = "TVGHCDMKNYSABWRTVGHCDMKNYSABWR".getBytes
      val iub: Array[Byte] = new Array( 'z'.toByte )

      for (indexValue <- code zip comp)
         indexValue match { case (i,v) => iub(i) = v }

      iub
   }

   def writeReverseComplement(sequence: Tuple2[Line,LineStack]) = {

      def inplaceComplementReverse(b: Array[Byte]) = {
         var i = 0
         var j = b.length - 1
         while (i < j){
            val swap = b(i)
            b(i) = IUB( b(j) )
            b(j) = IUB( swap )
            i = i + 1
            j = j - 1
         }
         if (i == j) b(i) = IUB( b(i) )
      }

      sequence match {
         case (header,lines) => {

            write(header); write(nl)

            val k = if (lines.isEmpty) 0 else lines.top.length
            val LineLength = 60
            val isSplitLine = k < LineLength
            var isFirstLine = true

            while (!lines.isEmpty) {
               val line = lines.pop
               inplaceComplementReverse(line)

               if (isSplitLine){
                  if (isFirstLine){ write(line); isFirstLine = false }
                  else { write(line,0,LineLength-k); write(nl); write(line,LineLength-k,k) }
               }
               else { write(line); write(nl) }
            }

            if (isSplitLine && !isFirstLine) write(nl)
         }
      }
   }

}