This question is part of a series solving the Rosalind challenges. For the previous question in this series, see A sequence of mistakes. The repository with all my up-to-date solutions so far can be found here.
Problem: PRTM
In a weighted alphabet, every symbol is assigned a positive real number called a weight. A string formed from a weighted alphabet is called a weighted string, and its weight is equal to the sum of the weights of its symbols.
The standard weight assigned to each member of the 20-symbol amino acid alphabet is the monoisotopic mass of the corresponding amino acid.
Given:
A protein string \$P\$ of length at most 1000 aa.
Return:
The total weight of \$P\$. Consult the monoisotopic mass table.
Sample Dataset:
SKADYEK
Sample Output:
821.392
My solution solves the sample dataset and the actual dataset given.
Dataset:
FQLCECNPKWNEEKRQYGACNQRNEYQDMKMVLRLNTRALAFLVEKFCTQATANSHGWQYRIENPLQLNHLPLTICRHGFDEDRIQRYQDDHNGVHIHVAMQITHSEWVLETWASSHQHANISPLSGNSQRYYPANHEGRRIQCCQFDCESHLMEDLWREATRSHESKVTRFKHDHNTPLHFTVFWPSDMEHDNGKTEYKSGWQLMFKIEGSVGKECELHTSYFSMKVKYTTVEIQTNPIERMCYAELVYWLRAEMEGVAKDRDHKWAMEHEQYIYSPMEGLINSVEYHMVYPQMARSIAKDRYWTPATLRRIHVWYCREIVQIMWIDHPKGLVCVMPDSNVGALIKWYTHYTDVKLETHQTCRKNNAGMVRDGRKKVAAEVFIIYEMGMPEYKPHEDANRDYRIPIDHPWRPHNNMCFGISGEWRRSCMKHQIQLSRWWANITKIMPMRWSIESGTTLRFVQGMVYRVNRFDDRYPRMNDCYWDAIWVCGAWTMHLTVPDLLMQMHHCMGAIHDVVFSEMGVKIAYQAVWFASVRIPASFQDWFCHEDHFQRGLRKCKLEHNDVLYETWIAMEPASYHTVHHCWHWREVFCHPCVFIHQMYSYPEFHIPDVELSLHYSQIWMNRETGWSPIRMELMCTSAPPNPDGGTPLLSFWYFGFIIQRHCGCETIMIGQWDTCFNSHHDVWAVWVHPENSQFTKERICCASFTDNSDTRECKQTVQHSSPGPTELWADSKTQVQWWYISQWLGKGLMYSEFQVSISGLSTPMLVYWLPNSMIEMNDVMEILNSPAGAQITTCIAGVNFRMIFETSWRTWYINRH
Output:
97283.202
PRTM.rb:
module Rosalind
RESIDUE_BY_MONOISOTOPIC_MASS = {
71.03711 => ["A"],
103.00919 => ["C"],
115.02694 => ["D"],
129.04259 => ["E"],
147.06841 => ["F"],
57.02146 => ["G"],
137.05891 => ["H"],
113.08406 => ["I", "L"],
128.09496 => ["K"],
131.04049 => ["M"],
114.04293 => ["N"],
97.05276 => ["P"],
128.05858 => ["Q"],
156.10111 => ["R"],
87.03203 => ["S"],
101.04768 => ["T"],
99.06841 => ["V"],
186.07931 => ["W"],
163.06333 => ["Y"]
}
MONOISOTOPIC_MASS_BY_RESIDUE = RESIDUE_BY_MONOISOTOPIC_MASS.
flat_map { |c, as| as.map { |a| [a, c] } }.to_h
def self.problem_prtm(aminoacids_string)
aminoacids_string.
scan(/./).
map { |residue| MONOISOTOPIC_MASS_BY_RESIDUE[residue] }.
take_while { |aminoacid| aminoacid != "" }.
inject(0){ |sum, x| sum + x }
end
end
user_input = gets.chomp
puts '%.3f' % Rosalind.problem_prtm(user_input)
The problem statement is quite similar to PROT, so the code looks quite similar to the answers given there.
Basically, I declare a bunch of value-key pairs which get inverted. This saves me from having the same value multiple times in the hash (when multiple residue weigh the same amount).
I'm mainly looking for idiomaticness and re-usability. I'm pretty sure my take_while
could be written better and my naming is always open for critique.