diff --git a/config.json b/config.json index 8b62bc0b4e..36f3c8d8ef 100644 --- a/config.json +++ b/config.json @@ -1160,6 +1160,19 @@ "strings", "text_formatting" ] + }, + { + "uuid": "775ae0ec-8db7-4568-a188-963931cf5ee1", + "slug": "protein-translation", + "core": false, + "unlocked_by": null, + "difficulty": 1, + "topics": [ + "control-flow-(conditionals)", + "control-flow-(loops)", + "strings", + "algorithms" + ] } ], "foregone": [] diff --git a/exercises/protein-translation/README.md b/exercises/protein-translation/README.md new file mode 100644 index 0000000000..744a694cd8 --- /dev/null +++ b/exercises/protein-translation/README.md @@ -0,0 +1,78 @@ +# Protein Translation + +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 four 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", "UAG", "AUG"` => + +Protein: `"Methionine", "Phenylalanine", "Serine"` + +Note the stop codon 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](http://en.wikipedia.org/wiki/Translation_(biology)) + +## Setup + +Go through the setup instructions for ECMAScript to +install the necessary dependencies: + +http://exercism.io/languages/ecmascript + +## Requirements + +Install assignment dependencies: + +```bash +$ npm install +``` + +## Making the Test Suite Pass + +Execute the tests with: + +```bash +$ npm test +``` + +In the test suite, all tests but the first have been skipped. + +Once you get a test passing, you can enable the next one by +changing `xtest` to `test`. + +## Source + +Tyler Long + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/exercises/protein-translation/example.js b/exercises/protein-translation/example.js new file mode 100644 index 0000000000..23514df5a2 --- /dev/null +++ b/exercises/protein-translation/example.js @@ -0,0 +1,45 @@ +const ACID_PROTEIN_MAP = { + AUG: 'Methionine', + UUU: 'Phenylalanine', + UUC: 'Phenylalanine', + UUA: 'Leucine', + UUG: 'Leucine', + UCU: 'Serine', + UCC: 'Serine', + UCA: 'Serine', + UCG: 'Serine', + UAU: 'Tyrosine', + UAC: 'Tyrosine', + UGU: 'Cysteine', + UGC: 'Cysteine', + UGG: 'Tryptophan', + UAA: 'STOP', + UAG: 'STOP', + UGA: 'STOP', +}; + +const getProtein = codon => ACID_PROTEIN_MAP[codon] || 'INVALID'; + +export default function translate(rnaStrand) { + const proteins = []; + + if (rnaStrand) { + for (let i = 0; i < rnaStrand.length; i += 3) { + const protein = getProtein(rnaStrand.substring(i, i + 3)); + + if (protein) { + if (protein === 'STOP') { + break; + } + + if (protein === 'INVALID') { + throw new Error('Invalid codon'); + } + + proteins.push(protein); + } + } + } + + return proteins; +} diff --git a/exercises/protein-translation/package.json b/exercises/protein-translation/package.json new file mode 100644 index 0000000000..67a12e6049 --- /dev/null +++ b/exercises/protein-translation/package.json @@ -0,0 +1,71 @@ +{ + "name": "xecmascript", + "version": "0.0.0", + "description": "Exercism exercises in ECMAScript 6.", + "author": "Katrina Owen", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/exercism/xecmascript" + }, + "devDependencies": { + "babel-jest": "^20.0.3", + "babel-plugin-transform-builtin-extend": "^1.1.2", + "babel-preset-env": "^1.4.0", + "eslint": "^3.19.0", + "eslint-config-airbnb": "^15.0.1", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^5.0.1", + "eslint-plugin-react": "^7.0.1", + "jest": "^20.0.4" + }, + "jest": { + "modulePathIgnorePatterns": [ + "package.json" + ] + }, + "babel": { + "presets": [ + "env" + ], + "plugins": [ + [ + "babel-plugin-transform-builtin-extend", + { + "globals": [ + "Error" + ] + } + ], + [ + "transform-regenerator" + ] + ] + }, + "scripts": { + "test": "jest --no-cache ./*", + "watch": "jest --no-cache --watch ./*", + "lint": "eslint .", + "lint-test": "eslint . && jest --no-cache ./* " + }, + "eslintConfig": { + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "env": { + "es6": true, + "node": true, + "jest": true + }, + "extends": "airbnb", + "rules": { + "import/no-unresolved": "off", + "import/extensions": "off" + } + }, + "licenses": [ + "MIT" + ], + "dependencies": {} +} diff --git a/exercises/protein-translation/protein-translation.spec.js b/exercises/protein-translation/protein-translation.spec.js new file mode 100644 index 0000000000..da60d177d8 --- /dev/null +++ b/exercises/protein-translation/protein-translation.spec.js @@ -0,0 +1,59 @@ +import translate from './protein-translation'; + +describe('ProteinTranslation', () => { + test('Empty RNA has no proteins', () => { + expect(translate()).toEqual([]); + }); + + xtest('Methionine codon translates into protein', () => { + expect(translate('AUG')).toEqual(['Methionine']); + }); + + xtest('Phenylalanine codons translate into protein', () => { + expect(translate('UUUUUC')).toEqual(['Phenylalanine', 'Phenylalanine']); + }); + + xtest('Leucine codons translate into protein', () => { + expect(translate('UUAUUG')).toEqual(['Leucine', 'Leucine']); + }); + + xtest('Serine codons translate into protein', () => { + expect(translate('UCUUCCUCAUCG')).toEqual(['Serine', 'Serine', 'Serine', 'Serine']); + }); + + xtest('Tyrosine codons translate into protein', () => { + expect(translate('UAUUAC')).toEqual(['Tyrosine', 'Tyrosine']); + }); + + xtest('Cysteine codons translate into protein', () => { + expect(translate('UGUUGC')).toEqual(['Cysteine', 'Cysteine']); + }); + + xtest('Tryptophan codon translates into protein', () => { + expect(translate('UGG')).toEqual(['Tryptophan']); + }); + + xtest('Sequence starts with stop codon 1', () => { + expect(translate('UAAUUUUUA')).toEqual([]); + }); + + xtest('Sequence starts with stop codon 2', () => { + expect(translate('UAGAUGUAU')).toEqual([]); + }); + + xtest('Sequence starts with stop codon 3', () => { + expect(translate('UGAUGU')).toEqual([]); + }); + + xtest('Small RNA strand', () => { + expect(translate('AUGUUUUCU')).toEqual(['Methionine', 'Phenylalanine', 'Serine']); + }); + + xtest('Stop codon ends translation', () => { + expect(translate('AUGUUUUCUUAAAUG')).toEqual(['Methionine', 'Phenylalanine', 'Serine']); + }); + + xtest('Invalid codon throws error', () => { + expect(() => translate('LOL')).toThrow(new Error('Invalid codon')); + }); +});