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: PRTMIn 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:SKADYEKSample Output:821.392My solution solves the sample dataset and the actual dataset given.Dataset:FQLCECNPKWNEEKRQYGACNQRNEYQDMKMVLRLNTRALAFLVEKFCTQATANSHGWQYRIENPLQLNHLPLTICRHGFDEDRIQRYQDDHNGVHIHVAMQITHSEWVLETWASSHQHANISPLSGNSQRYYPANHEGRRIQCCQFDCESHLMEDLWREATRSHESKVTRFKHDHNTPLHFTVFWPSDMEHDNGKTEYKSGWQLMFKIEGSVGKECELHTSYFSMKVKYTTVEIQTNPIERMCYAELVYWLRAEMEGVAKDRDHKWAMEHEQYIYSPMEGLINSVEYHMVYPQMARSIAKDRYWTPATLRRIHVWYCREIVQIMWIDHPKGLVCVMPDSNVGALIKWYTHYTDVKLETHQTCRKNNAGMVRDGRKKVAAEVFIIYEMGMPEYKPHEDANRDYRIPIDHPWRPHNNMCFGISGEWRRSCMKHQIQLSRWWANITKIMPMRWSIESGTTLRFVQGMVYRVNRFDDRYPRMNDCYWDAIWVCGAWTMHLTVPDLLMQMHHCMGAIHDVVFSEMGVKIAYQAVWFASVRIPASFQDWFCHEDHFQRGLRKCKLEHNDVLYETWIAMEPASYHTVHHCWHWREVFCHPCVFIHQMYSYPEFHIPDVELSLHYSQIWMNRETGWSPIRMELMCTSAPPNPDGGTPLLSFWYFGFIIQRHCGCETIMIGQWDTCFNSHHDVWAVWVHPENSQFTKERICCASFTDNSDTRECKQTVQHSSPGPTELWADSKTQVQWWYISQWLGKGLMYSEFQVSISGLSTPMLVYWLPNSMIEMNDVMEILNSPAGAQITTCIAGVNFRMIFETSWRTWYINRHOutput:97283.202PRTM.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 }  endenduser_input = gets.chompputs '%.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.
Calculating protein mass
strings;ruby;programming challenge;hash table;bioinformatics
About your code:I am glad you liked the idea of building the inverse structure programmatically, but here I don't think it's necessary :) Only two aminoacids have the same weight, I'd write the reversed hash. Why residue instead of aminoacid?I don't see why you need take_while here.xs.reduce(0) { |acc, x| acc.method(x) } -> xs.reduce(0, :method).Minor detail: personally I prefer explicit uses of $stdin.readline instead of gets.I'd write:module Rosalind  MONOISOTOPIC_MASS_BY_AMINOACID = {    A => 71.03711,    C => 103.00919,    D => 115.02694,    E => 129.04259,    F => 147.06841,    G => 57.02146,    H => 137.05891,    I => 113.08406,    L => 113.08406,    K => 128.09496,    M => 131.04049,    N => 114.04293,    P => 97.05276,    Q => 128.05858,    R => 156.10111,    S => 87.03203,    T => 101.04768,    V => 99.06841,    W => 186.07931,    Y => 163.06333,  }  def self.problem_prtm(aminoacids_string)    aminoacids_string.      chars.      map { |aminoacid| MONOISOTOPIC_MASS_BY_AMINOACID[aminoacid] }.      reduce(0, :+)  end  end protein = $stdin.readline.rstripweight = '%.3f' % Rosalind.problem_prtm(protein)puts(weight)Same idea, slightly different approach:module Rosalind  ...  def self.problem_prtm(aminoacids_string)    aminoacids = aminoacids_string.chars    masses = MONOISOTOPIC_MASS_BY_AMINOACID.values_at(*aminoacids)    masses.reduce(0, :+)  endend  