revcomp.lua 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. -- Reverse Complement benchmark from benchmarks game
  2. -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/revcomp.html
  3. --
  4. -- Original LUa code:
  5. -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/revcomp-lua-4.html
  6. --
  7. -- Adapted by Hugo Gualandi
  8. -- * Removed the eval-based metaprogramming
  9. -- * Don't do complicated logic with buffers
  10. -- * Use string.gsub
  11. --
  12. -- DNA complement table
  13. --
  14. local R = {}
  15. do
  16. local codes = "ACGTUMRWSYKVHDBN"
  17. local cmpls = "TGCAAKYWSRMBDHVN"
  18. for i = 1, #codes do
  19. local s = string.sub(codes, i, i)
  20. local t = string.sub(cmpls, i, i)
  21. R[s] = t
  22. R[string.lower(s)] = t
  23. end
  24. end
  25. --
  26. -- Print a long DNA sequence in multiple lines,
  27. -- with 60 columns per line
  28. --
  29. local function wrap(str)
  30. local n = #str
  31. local r = n
  32. local i = 1
  33. while r >= 60 do
  34. io.write(string.sub(str, i, i+59), "\n")
  35. i = i + 60
  36. r = r - 60
  37. end
  38. if r > 0 then
  39. io.write(string.sub(str, i, n), "\n")
  40. end
  41. end
  42. --
  43. -- Print the reverse-complement of the input sequences
  44. --
  45. local function revcomp(infile)
  46. local n = 0
  47. local names = {}
  48. local liness = {}
  49. local lines
  50. for line in infile:lines() do
  51. if string.sub(line, 1, 1) == ">" then
  52. n = n + 1
  53. lines = {}
  54. names[n] = line
  55. liness[n] = lines
  56. else
  57. lines[#lines+1] = line
  58. end
  59. end
  60. for i = 1, n do
  61. local seq = table.concat(liness[i])
  62. local rev = string.reverse(seq)
  63. local cpl = string.gsub(rev, '.', R)
  64. io.write(names[i], "\n")
  65. wrap(cpl)
  66. end
  67. end
  68. return function()
  69. revcomp(io.stdin)
  70. end