From 174aaab0cdc3f64a374d0fed5d777b9619b0b76a Mon Sep 17 00:00:00 2001 From: Daniel Mita Date: Sun, 17 Mar 2024 15:11:52 +0000 Subject: [PATCH 1/2] Implement protein-translation --- config.json | 9 + .../protein-translation/.docs/instructions.md | 45 ++++ .../protein-translation/.meta/config.json | 18 ++ .../solutions/lib/ProteinTranslation.rakumod | 4 + .../solutions/t/protein-translation.rakutest | 1 + .../.meta/template-data.yaml | 29 +++ .../protein-translation/.meta/tests.toml | 100 +++++++++ .../lib/ProteinTranslation.rakumod | 4 + .../t/protein-translation.rakutest | 210 ++++++++++++++++++ 9 files changed, 420 insertions(+) create mode 100644 exercises/practice/protein-translation/.docs/instructions.md create mode 100644 exercises/practice/protein-translation/.meta/config.json create mode 100644 exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod create mode 120000 exercises/practice/protein-translation/.meta/solutions/t/protein-translation.rakutest create mode 100644 exercises/practice/protein-translation/.meta/template-data.yaml create mode 100644 exercises/practice/protein-translation/.meta/tests.toml create mode 100644 exercises/practice/protein-translation/lib/ProteinTranslation.rakumod create mode 100755 exercises/practice/protein-translation/t/protein-translation.rakutest diff --git a/config.json b/config.json index 925cdb99..c371b11a 100644 --- a/config.json +++ b/config.json @@ -760,6 +760,15 @@ "prerequisites": [], "difficulty": 1, "topics": [] + }, + { + "slug": "protein-translation", + "name": "Protein Translation", + "uuid": "c446a757-3dad-4455-a633-a3a7873e4405", + "practices": [], + "prerequisites": [], + "difficulty": 1, + "topics": [] } ] }, diff --git a/exercises/practice/protein-translation/.docs/instructions.md b/exercises/practice/protein-translation/.docs/instructions.md new file mode 100644 index 00000000..7dc34d2e --- /dev/null +++ b/exercises/practice/protein-translation/.docs/instructions.md @@ -0,0 +1,45 @@ +# Instructions + +Translate RNA sequences into proteins. + +RNA can be broken into three nucleotide sequences called codons, and then translated to a polypeptide like so: + +RNA: `"AUGUUUUCU"` => translates to + +Codons: `"AUG", "UUU", "UCU"` +=> which become a polypeptide with the following sequence => + +Protein: `"Methionine", "Phenylalanine", "Serine"` + +There are 64 codons which in turn correspond to 20 amino acids; however, all of the codon sequences and resulting amino acids are not important in this exercise. +If it works for one codon, the program should work for all of them. +However, feel free to expand the list in the test suite to include them all. + +There are also three terminating codons (also known as 'STOP' codons); if any of these codons are encountered (by the ribosome), all translation ends and the protein is terminated. + +All subsequent codons after are ignored, like this: + +RNA: `"AUGUUUUCUUAAAUG"` => + +Codons: `"AUG", "UUU", "UCU", "UAA", "AUG"` => + +Protein: `"Methionine", "Phenylalanine", "Serine"` + +Note the stop codon `"UAA"` terminates the translation and the final methionine is not translated into the protein sequence. + +Below are the codons and resulting Amino Acids needed for the exercise. + +| Codon | Protein | +| :----------------- | :------------ | +| AUG | Methionine | +| UUU, UUC | Phenylalanine | +| UUA, UUG | Leucine | +| UCU, UCC, UCA, UCG | Serine | +| UAU, UAC | Tyrosine | +| UGU, UGC | Cysteine | +| UGG | Tryptophan | +| UAA, UAG, UGA | STOP | + +Learn more about [protein translation on Wikipedia][protein-translation]. + +[protein-translation]: https://en.wikipedia.org/wiki/Translation_(biology) diff --git a/exercises/practice/protein-translation/.meta/config.json b/exercises/practice/protein-translation/.meta/config.json new file mode 100644 index 00000000..b7428ce6 --- /dev/null +++ b/exercises/practice/protein-translation/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "m-dango" + ], + "files": { + "solution": [ + "lib/ProteinTranslation.rakumod" + ], + "test": [ + "t/protein-translation.rakutest" + ], + "example": [ + ".meta/solutions/lib/ProteinTranslation.rakumod" + ] + }, + "blurb": "Translate RNA sequences into proteins.", + "source": "Tyler Long" +} diff --git a/exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod b/exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod new file mode 100644 index 00000000..488cd390 --- /dev/null +++ b/exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod @@ -0,0 +1,4 @@ +unit module ProteinTranslation; + +sub protein-translation ($strand) { +} diff --git a/exercises/practice/protein-translation/.meta/solutions/t/protein-translation.rakutest b/exercises/practice/protein-translation/.meta/solutions/t/protein-translation.rakutest new file mode 120000 index 00000000..6da8c5ea --- /dev/null +++ b/exercises/practice/protein-translation/.meta/solutions/t/protein-translation.rakutest @@ -0,0 +1 @@ +../../../t/protein-translation.rakutest \ No newline at end of file diff --git a/exercises/practice/protein-translation/.meta/template-data.yaml b/exercises/practice/protein-translation/.meta/template-data.yaml new file mode 100644 index 00000000..835a5e4f --- /dev/null +++ b/exercises/practice/protein-translation/.meta/template-data.yaml @@ -0,0 +1,29 @@ +properties: + proteins: + test: |- + if %case:exists { + sprintf(q:to/END/, (%case, %case).map(*.raku)); + dies-ok( + { protein-translation %s }, + %s, + ); + END + } + else { + sprintf(q:to/END/, (%case, %case.List<>, %case).map(*.raku)); + cmp-ok( + protein-translation(%s), + "~~", + %s, + %s, + ); + END + } + +example: |- + sub protein-translation ($strand) { + } + +stub: |- + sub protein-translation ($strand) { + } diff --git a/exercises/practice/protein-translation/.meta/tests.toml b/exercises/practice/protein-translation/.meta/tests.toml new file mode 100644 index 00000000..5fb18907 --- /dev/null +++ b/exercises/practice/protein-translation/.meta/tests.toml @@ -0,0 +1,100 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[2c44f7bf-ba20-43f7-a3bf-f2219c0c3f98] +description = "Empty RNA sequence results in no proteins" + +[96d3d44f-34a2-4db4-84cd-fff523e069be] +description = "Methionine RNA sequence" + +[1b4c56d8-d69f-44eb-be0e-7b17546143d9] +description = "Phenylalanine RNA sequence 1" + +[81b53646-bd57-4732-b2cb-6b1880e36d11] +description = "Phenylalanine RNA sequence 2" + +[42f69d4f-19d2-4d2c-a8b0-f0ae9ee1b6b4] +description = "Leucine RNA sequence 1" + +[ac5edadd-08ed-40a3-b2b9-d82bb50424c4] +description = "Leucine RNA sequence 2" + +[8bc36e22-f984-44c3-9f6b-ee5d4e73f120] +description = "Serine RNA sequence 1" + +[5c3fa5da-4268-44e5-9f4b-f016ccf90131] +description = "Serine RNA sequence 2" + +[00579891-b594-42b4-96dc-7ff8bf519606] +description = "Serine RNA sequence 3" + +[08c61c3b-fa34-4950-8c4a-133945570ef6] +description = "Serine RNA sequence 4" + +[54e1e7d8-63c0-456d-91d2-062c72f8eef5] +description = "Tyrosine RNA sequence 1" + +[47bcfba2-9d72-46ad-bbce-22f7666b7eb1] +description = "Tyrosine RNA sequence 2" + +[3a691829-fe72-43a7-8c8e-1bd083163f72] +description = "Cysteine RNA sequence 1" + +[1b6f8a26-ca2f-43b8-8262-3ee446021767] +description = "Cysteine RNA sequence 2" + +[1e91c1eb-02c0-48a0-9e35-168ad0cb5f39] +description = "Tryptophan RNA sequence" + +[e547af0b-aeab-49c7-9f13-801773a73557] +description = "STOP codon RNA sequence 1" + +[67640947-ff02-4f23-a2ef-816f8a2ba72e] +description = "STOP codon RNA sequence 2" + +[9c2ad527-ebc9-4ace-808b-2b6447cb54cb] +description = "STOP codon RNA sequence 3" + +[f4d9d8ee-00a8-47bf-a1e3-1641d4428e54] +description = "Sequence of two protein codons translates into proteins" + +[dd22eef3-b4f1-4ad6-bb0b-27093c090a9d] +description = "Sequence of two different protein codons translates into proteins" + +[d0f295df-fb70-425c-946c-ec2ec185388e] +description = "Translate RNA strand into correct protein list" + +[e30e8505-97ec-4e5f-a73e-5726a1faa1f4] +description = "Translation stops if STOP codon at beginning of sequence" + +[5358a20b-6f4c-4893-bce4-f929001710f3] +description = "Translation stops if STOP codon at end of two-codon sequence" + +[ba16703a-1a55-482f-bb07-b21eef5093a3] +description = "Translation stops if STOP codon at end of three-codon sequence" + +[4089bb5a-d5b4-4e71-b79e-b8d1f14a2911] +description = "Translation stops if STOP codon in middle of three-codon sequence" + +[2c2a2a60-401f-4a80-b977-e0715b23b93d] +description = "Translation stops if STOP codon in middle of six-codon sequence" + +[1e75ea2a-f907-4994-ae5c-118632a1cb0f] +description = "Non-existing codon can't translate" + +[9eac93f3-627a-4c90-8653-6d0a0595bc6f] +description = "Unknown amino acids, not part of a codon, can't translate" + +[9d73899f-e68e-4291-b1e2-7bf87c00f024] +description = "Incomplete RNA sequence can't translate" + +[43945cf7-9968-402d-ab9f-b8a28750b050] +description = "Incomplete RNA sequence can translate if valid until a STOP codon" diff --git a/exercises/practice/protein-translation/lib/ProteinTranslation.rakumod b/exercises/practice/protein-translation/lib/ProteinTranslation.rakumod new file mode 100644 index 00000000..488cd390 --- /dev/null +++ b/exercises/practice/protein-translation/lib/ProteinTranslation.rakumod @@ -0,0 +1,4 @@ +unit module ProteinTranslation; + +sub protein-translation ($strand) { +} diff --git a/exercises/practice/protein-translation/t/protein-translation.rakutest b/exercises/practice/protein-translation/t/protein-translation.rakutest new file mode 100755 index 00000000..794120a6 --- /dev/null +++ b/exercises/practice/protein-translation/t/protein-translation.rakutest @@ -0,0 +1,210 @@ +#!/usr/bin/env raku +use Test; +use lib $?FILE.IO.parent(2).add('lib'); +use ProteinTranslation; + +cmp-ok( # begin: 2c44f7bf-ba20-43f7-a3bf-f2219c0c3f98 + protein-translation(""), + "~~", + (), + "Empty RNA sequence results in no proteins", +); # end: 2c44f7bf-ba20-43f7-a3bf-f2219c0c3f98 + +cmp-ok( # begin: 96d3d44f-34a2-4db4-84cd-fff523e069be + protein-translation("AUG"), + "~~", + ("Methionine",), + "Methionine RNA sequence", +); # end: 96d3d44f-34a2-4db4-84cd-fff523e069be + +cmp-ok( # begin: 1b4c56d8-d69f-44eb-be0e-7b17546143d9 + protein-translation("UUU"), + "~~", + ("Phenylalanine",), + "Phenylalanine RNA sequence 1", +); # end: 1b4c56d8-d69f-44eb-be0e-7b17546143d9 + +cmp-ok( # begin: 81b53646-bd57-4732-b2cb-6b1880e36d11 + protein-translation("UUC"), + "~~", + ("Phenylalanine",), + "Phenylalanine RNA sequence 2", +); # end: 81b53646-bd57-4732-b2cb-6b1880e36d11 + +cmp-ok( # begin: 42f69d4f-19d2-4d2c-a8b0-f0ae9ee1b6b4 + protein-translation("UUA"), + "~~", + ("Leucine",), + "Leucine RNA sequence 1", +); # end: 42f69d4f-19d2-4d2c-a8b0-f0ae9ee1b6b4 + +cmp-ok( # begin: ac5edadd-08ed-40a3-b2b9-d82bb50424c4 + protein-translation("UUG"), + "~~", + ("Leucine",), + "Leucine RNA sequence 2", +); # end: ac5edadd-08ed-40a3-b2b9-d82bb50424c4 + +cmp-ok( # begin: 8bc36e22-f984-44c3-9f6b-ee5d4e73f120 + protein-translation("UCU"), + "~~", + ("Serine",), + "Serine RNA sequence 1", +); # end: 8bc36e22-f984-44c3-9f6b-ee5d4e73f120 + +cmp-ok( # begin: 5c3fa5da-4268-44e5-9f4b-f016ccf90131 + protein-translation("UCC"), + "~~", + ("Serine",), + "Serine RNA sequence 2", +); # end: 5c3fa5da-4268-44e5-9f4b-f016ccf90131 + +cmp-ok( # begin: 00579891-b594-42b4-96dc-7ff8bf519606 + protein-translation("UCA"), + "~~", + ("Serine",), + "Serine RNA sequence 3", +); # end: 00579891-b594-42b4-96dc-7ff8bf519606 + +cmp-ok( # begin: 08c61c3b-fa34-4950-8c4a-133945570ef6 + protein-translation("UCG"), + "~~", + ("Serine",), + "Serine RNA sequence 4", +); # end: 08c61c3b-fa34-4950-8c4a-133945570ef6 + +cmp-ok( # begin: 54e1e7d8-63c0-456d-91d2-062c72f8eef5 + protein-translation("UAU"), + "~~", + ("Tyrosine",), + "Tyrosine RNA sequence 1", +); # end: 54e1e7d8-63c0-456d-91d2-062c72f8eef5 + +cmp-ok( # begin: 47bcfba2-9d72-46ad-bbce-22f7666b7eb1 + protein-translation("UAC"), + "~~", + ("Tyrosine",), + "Tyrosine RNA sequence 2", +); # end: 47bcfba2-9d72-46ad-bbce-22f7666b7eb1 + +cmp-ok( # begin: 3a691829-fe72-43a7-8c8e-1bd083163f72 + protein-translation("UGU"), + "~~", + ("Cysteine",), + "Cysteine RNA sequence 1", +); # end: 3a691829-fe72-43a7-8c8e-1bd083163f72 + +cmp-ok( # begin: 1b6f8a26-ca2f-43b8-8262-3ee446021767 + protein-translation("UGC"), + "~~", + ("Cysteine",), + "Cysteine RNA sequence 2", +); # end: 1b6f8a26-ca2f-43b8-8262-3ee446021767 + +cmp-ok( # begin: 1e91c1eb-02c0-48a0-9e35-168ad0cb5f39 + protein-translation("UGG"), + "~~", + ("Tryptophan",), + "Tryptophan RNA sequence", +); # end: 1e91c1eb-02c0-48a0-9e35-168ad0cb5f39 + +cmp-ok( # begin: e547af0b-aeab-49c7-9f13-801773a73557 + protein-translation("UAA"), + "~~", + (), + "STOP codon RNA sequence 1", +); # end: e547af0b-aeab-49c7-9f13-801773a73557 + +cmp-ok( # begin: 67640947-ff02-4f23-a2ef-816f8a2ba72e + protein-translation("UAG"), + "~~", + (), + "STOP codon RNA sequence 2", +); # end: 67640947-ff02-4f23-a2ef-816f8a2ba72e + +cmp-ok( # begin: 9c2ad527-ebc9-4ace-808b-2b6447cb54cb + protein-translation("UGA"), + "~~", + (), + "STOP codon RNA sequence 3", +); # end: 9c2ad527-ebc9-4ace-808b-2b6447cb54cb + +cmp-ok( # begin: f4d9d8ee-00a8-47bf-a1e3-1641d4428e54 + protein-translation("UUUUUU"), + "~~", + ("Phenylalanine", "Phenylalanine"), + "Sequence of two protein codons translates into proteins", +); # end: f4d9d8ee-00a8-47bf-a1e3-1641d4428e54 + +cmp-ok( # begin: dd22eef3-b4f1-4ad6-bb0b-27093c090a9d + protein-translation("UUAUUG"), + "~~", + ("Leucine", "Leucine"), + "Sequence of two different protein codons translates into proteins", +); # end: dd22eef3-b4f1-4ad6-bb0b-27093c090a9d + +cmp-ok( # begin: d0f295df-fb70-425c-946c-ec2ec185388e + protein-translation("AUGUUUUGG"), + "~~", + ("Methionine", "Phenylalanine", "Tryptophan"), + "Translate RNA strand into correct protein list", +); # end: d0f295df-fb70-425c-946c-ec2ec185388e + +cmp-ok( # begin: e30e8505-97ec-4e5f-a73e-5726a1faa1f4 + protein-translation("UAGUGG"), + "~~", + (), + "Translation stops if STOP codon at beginning of sequence", +); # end: e30e8505-97ec-4e5f-a73e-5726a1faa1f4 + +cmp-ok( # begin: 5358a20b-6f4c-4893-bce4-f929001710f3 + protein-translation("UGGUAG"), + "~~", + ("Tryptophan",), + "Translation stops if STOP codon at end of two-codon sequence", +); # end: 5358a20b-6f4c-4893-bce4-f929001710f3 + +cmp-ok( # begin: ba16703a-1a55-482f-bb07-b21eef5093a3 + protein-translation("AUGUUUUAA"), + "~~", + ("Methionine", "Phenylalanine"), + "Translation stops if STOP codon at end of three-codon sequence", +); # end: ba16703a-1a55-482f-bb07-b21eef5093a3 + +cmp-ok( # begin: 4089bb5a-d5b4-4e71-b79e-b8d1f14a2911 + protein-translation("UGGUAGUGG"), + "~~", + ("Tryptophan",), + "Translation stops if STOP codon in middle of three-codon sequence", +); # end: 4089bb5a-d5b4-4e71-b79e-b8d1f14a2911 + +cmp-ok( # begin: 2c2a2a60-401f-4a80-b977-e0715b23b93d + protein-translation("UGGUGUUAUUAAUGGUUU"), + "~~", + ("Tryptophan", "Cysteine", "Tyrosine"), + "Translation stops if STOP codon in middle of six-codon sequence", +); # end: 2c2a2a60-401f-4a80-b977-e0715b23b93d + +dies-ok( # begin: 1e75ea2a-f907-4994-ae5c-118632a1cb0f + { protein-translation "AAA" }, + "Non-existing codon can't translate", +); # end: 1e75ea2a-f907-4994-ae5c-118632a1cb0f + +dies-ok( # begin: 9eac93f3-627a-4c90-8653-6d0a0595bc6f + { protein-translation "XYZ" }, + "Unknown amino acids, not part of a codon, can't translate", +); # end: 9eac93f3-627a-4c90-8653-6d0a0595bc6f + +dies-ok( # begin: 9d73899f-e68e-4291-b1e2-7bf87c00f024 + { protein-translation "AUGU" }, + "Incomplete RNA sequence can't translate", +); # end: 9d73899f-e68e-4291-b1e2-7bf87c00f024 + +cmp-ok( # begin: 43945cf7-9968-402d-ab9f-b8a28750b050 + protein-translation("UUCUUCUAAUGGU"), + "~~", + ("Phenylalanine", "Phenylalanine"), + "Incomplete RNA sequence can translate if valid until a STOP codon", +); # end: 43945cf7-9968-402d-ab9f-b8a28750b050 + +done-testing; From f51e7e2525773ad9eb52b92e9727ab409ec2a42e Mon Sep 17 00:00:00 2001 From: Daniel Mita Date: Sun, 17 Mar 2024 15:33:24 +0000 Subject: [PATCH 2/2] Add solution and contributor --- .../protein-translation/.meta/config.json | 3 +++ .../solutions/lib/ProteinTranslation.rakumod | 23 ++++++++++++++++- .../.meta/template-data.yaml | 25 +++++++++++++++++-- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/exercises/practice/protein-translation/.meta/config.json b/exercises/practice/protein-translation/.meta/config.json index b7428ce6..6f2d9210 100644 --- a/exercises/practice/protein-translation/.meta/config.json +++ b/exercises/practice/protein-translation/.meta/config.json @@ -2,6 +2,9 @@ "authors": [ "m-dango" ], + "contributors": [ + "rcmlz" + ], "files": { "solution": [ "lib/ProteinTranslation.rakumod" diff --git a/exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod b/exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod index 488cd390..3ac6e526 100644 --- a/exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod +++ b/exercises/practice/protein-translation/.meta/solutions/lib/ProteinTranslation.rakumod @@ -1,4 +1,25 @@ unit module ProteinTranslation; -sub protein-translation ($strand) { +my class X::InvalidCodon is Exception { + method message { + 'Invalid codon' + } +} + +our %PROTEIN is default(X::InvalidCodon) = { + Methionine => , + Phenylalanine => , + Leucine => , + Serine => , + Tyrosine => , + Cysteine => , + Tryptophan => , + STOP => }.invert; + +sub protein-translation (Str $rna --> Seq) is export { + $rna.comb(3).map: { given %PROTEIN{$_} { + when 'STOP' { last } + when X::InvalidCodon { $_.new.throw } + default { $_ or [] } + }} } diff --git a/exercises/practice/protein-translation/.meta/template-data.yaml b/exercises/practice/protein-translation/.meta/template-data.yaml index 835a5e4f..64303325 100644 --- a/exercises/practice/protein-translation/.meta/template-data.yaml +++ b/exercises/practice/protein-translation/.meta/template-data.yaml @@ -21,8 +21,29 @@ properties: } example: |- - sub protein-translation ($strand) { - } + my class X::InvalidCodon is Exception { + method message { + 'Invalid codon' + } + } + + our %PROTEIN is default(X::InvalidCodon) = { + Methionine => , + Phenylalanine => , + Leucine => , + Serine => , + Tyrosine => , + Cysteine => , + Tryptophan => , + STOP => }.invert; + + sub protein-translation (Str $rna --> Seq) is export { + $rna.comb(3).map: { given %PROTEIN{$_} { + when 'STOP' { last } + when X::InvalidCodon { $_.new.throw } + default { $_ or [] } + }} + } stub: |- sub protein-translation ($strand) {