diff --git a/config.json b/config.json index aae5770..743e90b 100644 --- a/config.json +++ b/config.json @@ -182,6 +182,14 @@ "prerequisites": [], "difficulty": 2 }, + { + "slug": "nucleotide-count", + "name": "Nucleotide Count", + "uuid": "8380e348-348c-4197-9cd4-34fd9c70c71b", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "pangram", "name": "Pangram", diff --git a/exercises/practice/nucleotide-count/.docs/instructions.md b/exercises/practice/nucleotide-count/.docs/instructions.md new file mode 100644 index 0000000..548d9ba --- /dev/null +++ b/exercises/practice/nucleotide-count/.docs/instructions.md @@ -0,0 +1,23 @@ +# Instructions + +Each of us inherits from our biological parents a set of chemical instructions known as DNA that influence how our bodies are constructed. +All known life depends on DNA! + +> Note: You do not need to understand anything about nucleotides or DNA to complete this exercise. + +DNA is a long chain of other chemicals and the most important are the four nucleotides, adenine, cytosine, guanine and thymine. +A single DNA chain can contain billions of these four nucleotides and the order in which they occur is important! +We call the order of these nucleotides in a bit of DNA a "DNA sequence". + +We represent a DNA sequence as an ordered collection of these four nucleotides and a common way to do that is with a string of characters such as "ATTACG" for a DNA sequence of 6 nucleotides. +'A' for adenine, 'C' for cytosine, 'G' for guanine, and 'T' for thymine. + +Given a string representing a DNA sequence, count how many of each nucleotide is present. +If the string contains characters that aren't A, C, G, or T then it is invalid and you should signal an error. + +For example: + +```text +"GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2 +"INVALID" -> error +``` diff --git a/exercises/practice/nucleotide-count/.meta/config.json b/exercises/practice/nucleotide-count/.meta/config.json new file mode 100644 index 0000000..7852581 --- /dev/null +++ b/exercises/practice/nucleotide-count/.meta/config.json @@ -0,0 +1,22 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "src/lib.cairo" + ], + "test": [ + "tests/nucleotide_count.cairo" + ], + "example": [ + ".meta/example.cairo" + ], + "invalidator": [ + "Scarb.toml" + ] + }, + "blurb": "Given a DNA string, compute how many times each nucleotide occurs in the string.", + "source": "The Calculating DNA Nucleotides_problem at Rosalind", + "source_url": "https://rosalind.info/problems/dna/" +} diff --git a/exercises/practice/nucleotide-count/.meta/example.cairo b/exercises/practice/nucleotide-count/.meta/example.cairo new file mode 100644 index 0000000..6fa00df --- /dev/null +++ b/exercises/practice/nucleotide-count/.meta/example.cairo @@ -0,0 +1,30 @@ +#[derive(Debug, Default, Drop, PartialEq)] +pub struct Counter { + pub a: u64, + pub c: u64, + pub g: u64, + pub t: u64 +} + +pub fn counts(strand: ByteArray) -> Counter { + let mut counter: Counter = Default::default(); + let mut i = 0; + + while i < strand.len() { + let chr = strand[i]; + if chr == 'A' { + counter.a += 1; + } else if chr == 'C' { + counter.c += 1; + } else if chr == 'G' { + counter.g += 1; + } else if chr == 'T' { + counter.t += 1; + } else { + panic!("Invalid nucleotide in strand"); + } + i += 1; + }; + + counter +} diff --git a/exercises/practice/nucleotide-count/.meta/tests.toml b/exercises/practice/nucleotide-count/.meta/tests.toml new file mode 100644 index 0000000..7c55e53 --- /dev/null +++ b/exercises/practice/nucleotide-count/.meta/tests.toml @@ -0,0 +1,25 @@ +# 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. + +[3e5c30a8-87e2-4845-a815-a49671ade970] +description = "empty strand" + +[a0ea42a6-06d9-4ac6-828c-7ccaccf98fec] +description = "can count one nucleotide in single-character input" + +[eca0d565-ed8c-43e7-9033-6cefbf5115b5] +description = "strand with repeated nucleotide" + +[40a45eac-c83f-4740-901a-20b22d15a39f] +description = "strand with multiple nucleotides" + +[b4c47851-ee9e-4b0a-be70-a86e343bd851] +description = "strand with invalid nucleotides" diff --git a/exercises/practice/nucleotide-count/Scarb.toml b/exercises/practice/nucleotide-count/Scarb.toml new file mode 100644 index 0000000..9ab2093 --- /dev/null +++ b/exercises/practice/nucleotide-count/Scarb.toml @@ -0,0 +1,7 @@ +[package] +name = "nucleotide_count" +version = "0.1.0" +edition = "2024_07" + +[dev-dependencies] +cairo_test = "2.7.1" diff --git a/exercises/practice/nucleotide-count/src/lib.cairo b/exercises/practice/nucleotide-count/src/lib.cairo new file mode 100644 index 0000000..1e9f32a --- /dev/null +++ b/exercises/practice/nucleotide-count/src/lib.cairo @@ -0,0 +1,11 @@ +#[derive(Debug, Drop, PartialEq)] +pub struct Counter { + pub a: u64, + pub c: u64, + pub g: u64, + pub t: u64 +} + +pub fn counts(strand: ByteArray) -> Counter { + panic!("implement `counts`") +} diff --git a/exercises/practice/nucleotide-count/tests/nucleotide_count.cairo b/exercises/practice/nucleotide-count/tests/nucleotide_count.cairo new file mode 100644 index 0000000..804e3b3 --- /dev/null +++ b/exercises/practice/nucleotide-count/tests/nucleotide_count.cairo @@ -0,0 +1,43 @@ +use nucleotide_count::{counts, Counter}; + +#[test] +fn empty_strand() { + let strand = ""; + let output = counts(strand); + let expected = Counter { a: 0, c: 0, g: 0, t: 0 }; + assert_eq!(output, expected); +} + +#[test] +#[ignore] +fn can_count_one_nucleotide_in_single_character_input() { + let strand = "G"; + let output = counts(strand); + let expected = Counter { a: 0, c: 0, g: 1, t: 0 }; + assert_eq!(output, expected); +} + +#[test] +#[ignore] +fn strand_with_repeated_nucleotide() { + let strand = "GGGGGGG"; + let output = counts(strand); + let expected = Counter { a: 0, c: 0, g: 7, t: 0 }; + assert_eq!(output, expected); +} + +#[test] +#[ignore] +fn strand_with_multiple_nucleotides() { + let strand = "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC"; + let output = counts(strand); + let expected = Counter { a: 20, c: 12, g: 17, t: 21 }; + assert_eq!(output, expected); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Invalid nucleotide in strand",))] +fn strand_with_invalid_nucleotides() { + counts("AGXXACT"); +}