trackler 2.2.1.179 → 2.2.1.180
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/yacht/description.md +14 -13
- data/tracks/ballerina/config.json +1 -0
- data/tracks/coffeescript/config.json +138 -41
- data/tracks/coffeescript/docs/ABOUT.md +3 -7
- data/tracks/coq/config.json +1 -0
- data/tracks/d/config.json +1 -0
- data/tracks/dart/config.json +1 -0
- data/tracks/elixir/config.json +17 -16
- data/tracks/elixir/docs/ABOUT.md +10 -2
- data/tracks/fortran/config.json +1 -0
- data/tracks/gnu-apl/config.json +1 -0
- data/tracks/go/config.json +13 -0
- data/tracks/go/exercises/list-ops/README.md +27 -0
- data/tracks/go/exercises/list-ops/example.go +99 -0
- data/tracks/go/exercises/list-ops/listops_test.go +291 -0
- data/tracks/groovy/config.json +1 -0
- data/tracks/haxe/config.json +1 -0
- data/tracks/perl5/exercises/leap/.meta/exercise-data.yaml +3 -5
- data/tracks/perl5/exercises/leap/.meta/solutions/Leap.pm +2 -4
- data/tracks/perl5/exercises/leap/Leap.pm +1 -1
- data/tracks/perl5/exercises/leap/leap.t +2 -2
- data/tracks/php/config.json +1 -0
- data/tracks/plsql/config.json +1 -0
- data/tracks/pony/config.json +1 -0
- data/tracks/purescript/config.json +1 -0
- data/tracks/reasonml/config/exercise_readme.go.tmpl +18 -2
- data/tracks/reasonml/exercises/anagram/README.md +15 -4
- data/tracks/reasonml/exercises/armstrong-numbers/README.md +3 -4
- data/tracks/reasonml/exercises/binary-search/README.md +14 -7
- data/tracks/reasonml/exercises/bob/README.md +14 -6
- data/tracks/reasonml/exercises/change/README.md +2 -4
- data/tracks/reasonml/exercises/hello-world/README.md +2 -3
- data/tracks/reasonml/exercises/isogram/README.md +4 -6
- data/tracks/reasonml/exercises/leap/README.md +14 -4
- data/tracks/reasonml/exercises/pangram/README.md +13 -3
- data/tracks/reasonml/exercises/phone-number/README.md +15 -7
- data/tracks/reasonml/exercises/raindrops/README.md +14 -7
- data/tracks/reasonml/exercises/rna-transcription/README.md +13 -3
- data/tracks/reasonml/exercises/roman-numerals/README.md +4 -8
- data/tracks/reasonml/exercises/run-length-encoding/README.md +14 -7
- data/tracks/reasonml/exercises/space-age/README.md +13 -3
- data/tracks/reasonml/exercises/word-count/README.md +18 -8
- data/tracks/rust/.travis.yml +1 -0
- data/tracks/rust/_test/check-exercises-for-authors.sh +10 -0
- data/tracks/rust/bin/format_exercises +2 -0
- data/tracks/rust/exercises/accumulate/Cargo.toml +0 -1
- data/tracks/rust/exercises/accumulate/example.rs +4 -1
- data/tracks/rust/exercises/acronym/example.rs +6 -5
- data/tracks/rust/exercises/acronym/tests/acronym.rs +1 -1
- data/tracks/rust/exercises/all-your-base/example.rs +8 -2
- data/tracks/rust/exercises/allergies/example.rs +28 -6
- data/tracks/rust/exercises/alphametics/example.rs +18 -10
- data/tracks/rust/exercises/anagram/example.rs +8 -4
- data/tracks/rust/exercises/atbash-cipher/example.rs +15 -15
- data/tracks/rust/exercises/beer-song/example.rs +18 -12
- data/tracks/rust/exercises/binary-search/Cargo.toml +0 -1
- data/tracks/rust/exercises/binary-search/example.rs +3 -4
- data/tracks/rust/exercises/bob/example.rs +11 -5
- data/tracks/rust/exercises/book-store/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/book-store/Cargo.toml +0 -1
- data/tracks/rust/exercises/book-store/example.rs +15 -19
- data/tracks/rust/exercises/bowling/example.rs +3 -1
- data/tracks/rust/exercises/bracket-push/example.rs +7 -2
- data/tracks/rust/exercises/circular-buffer/example.rs +1 -1
- data/tracks/rust/exercises/clock/.meta/ALLOWED_TO_NOT_COMPILE +3 -0
- data/tracks/rust/exercises/clock/Cargo.toml +0 -1
- data/tracks/rust/exercises/clock/example.rs +5 -3
- data/tracks/rust/exercises/clock/src/lib.rs +14 -0
- data/tracks/rust/exercises/collatz-conjecture/example.rs +2 -2
- data/tracks/rust/exercises/crypto-square/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/crypto-square/Cargo.toml +0 -1
- data/tracks/rust/exercises/custom-set/example.rs +17 -15
- data/tracks/rust/exercises/decimal/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/decimal/Cargo.toml +0 -1
- data/tracks/rust/exercises/decimal/example.rs +5 -5
- data/tracks/rust/exercises/diamond/Cargo.toml +0 -1
- data/tracks/rust/exercises/difference-of-squares/example.rs +1 -1
- data/tracks/rust/exercises/dominoes/example.rs +20 -19
- data/tracks/rust/exercises/etl/example.rs +4 -3
- data/tracks/rust/exercises/forth/example.rs +29 -45
- data/tracks/rust/exercises/grade-school/example.rs +4 -2
- data/tracks/rust/exercises/hexadecimal/example.rs +2 -4
- data/tracks/rust/exercises/isbn-verifier/example.rs +5 -6
- data/tracks/rust/exercises/isbn-verifier/tests/isbn-verifier.rs +12 -0
- data/tracks/rust/exercises/isogram/example.rs +9 -3
- data/tracks/rust/exercises/largest-series-product/example.rs +2 -1
- data/tracks/rust/exercises/luhn-from/example.rs +3 -1
- data/tracks/rust/exercises/luhn/example.rs +5 -3
- data/tracks/rust/exercises/macros/Cargo.toml +0 -1
- data/tracks/rust/exercises/nth-prime/Cargo.toml +0 -1
- data/tracks/rust/exercises/nth-prime/example.rs +6 -6
- data/tracks/rust/exercises/nucleotide-codons/Cargo.toml +0 -1
- data/tracks/rust/exercises/nucleotide-codons/example.rs +23 -17
- data/tracks/rust/exercises/nucleotide-count/example.rs +15 -5
- data/tracks/rust/exercises/nucleotide-count/src/lib.rs +15 -0
- data/tracks/rust/exercises/nucleotide-count/tests/nucleotide-count.rs +3 -3
- data/tracks/rust/exercises/palindrome-products/Cargo.toml +0 -1
- data/tracks/rust/exercises/pangram/example.rs +6 -6
- data/tracks/rust/exercises/parallel-letter-frequency/example.rs +7 -4
- data/tracks/rust/exercises/pascals-triangle/example.rs +6 -2
- data/tracks/rust/exercises/perfect-numbers/example.rs +2 -2
- data/tracks/rust/exercises/phone-number/example.rs +11 -15
- data/tracks/rust/exercises/pig-latin/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/pig-latin/Cargo.toml +0 -1
- data/tracks/rust/exercises/pig-latin/example.rs +6 -2
- data/tracks/rust/exercises/poker/Cargo-example.toml +0 -1
- data/tracks/rust/exercises/poker/Cargo.toml +0 -1
- data/tracks/rust/exercises/poker/example.rs +9 -8
- data/tracks/rust/exercises/prime-factors/Cargo.toml +0 -1
- data/tracks/rust/exercises/prime-factors/example.rs +1 -1
- data/tracks/rust/exercises/protein-translation/Cargo.toml +0 -1
- data/tracks/rust/exercises/protein-translation/example.rs +6 -5
- data/tracks/rust/exercises/proverb/Cargo.toml +0 -1
- data/tracks/rust/exercises/proverb/example.rs +0 -1
- data/tracks/rust/exercises/pythagorean-triplet/Cargo.toml +0 -1
- data/tracks/rust/exercises/pythagorean-triplet/example.rs +3 -3
- data/tracks/rust/exercises/queen-attack/example.rs +3 -3
- data/tracks/rust/exercises/react/example.rs +61 -29
- data/tracks/rust/exercises/reverse-string/Cargo.toml +0 -1
- data/tracks/rust/exercises/rna-transcription/example.rs +17 -9
- data/tracks/rust/exercises/robot-name/example.rs +4 -3
- data/tracks/rust/exercises/robot-simulator/example.rs +5 -2
- data/tracks/rust/exercises/roman-numerals/example.rs +15 -14
- data/tracks/rust/exercises/rotational-cipher/Cargo.toml +0 -1
- data/tracks/rust/exercises/rotational-cipher/example.rs +10 -14
- data/tracks/rust/exercises/rotational-cipher/src/lib.rs +7 -1
- data/tracks/rust/exercises/run-length-encoding/Cargo.toml +0 -1
- data/tracks/rust/exercises/run-length-encoding/example.rs +34 -29
- data/tracks/rust/exercises/saddle-points/example.rs +0 -1
- data/tracks/rust/exercises/say/Cargo.toml +0 -1
- data/tracks/rust/exercises/say/example.rs +34 -8
- data/tracks/rust/exercises/series/example.rs +6 -8
- data/tracks/rust/exercises/simple-linked-list/example.rs +0 -2
- data/tracks/rust/exercises/spiral-matrix/example.rs +0 -1
- data/tracks/rust/exercises/tournament/example.rs +33 -20
- data/tracks/rust/exercises/triangle/example.rs +1 -1
- data/tracks/rust/exercises/two-bucket/example.rs +2 -6
- data/tracks/rust/exercises/two-fer/example.rs +3 -3
- data/tracks/rust/exercises/variable-length-quantity/example.rs +2 -3
- data/tracks/rust/exercises/word-count/example.rs +4 -1
- data/tracks/rust/exercises/wordy/example.rs +10 -4
- metadata +7 -2
@@ -1,7 +1,8 @@
|
|
1
1
|
use std::collections::BTreeMap;
|
2
2
|
|
3
3
|
pub fn transform(input: &BTreeMap<i32, Vec<char>>) -> BTreeMap<char, i32> {
|
4
|
-
input
|
5
|
-
|
6
|
-
|
4
|
+
input
|
5
|
+
.iter()
|
6
|
+
.flat_map(|(&n, vec)| vec.iter().map(move |c| (c.to_ascii_lowercase(), n)))
|
7
|
+
.collect()
|
7
8
|
}
|
@@ -41,10 +41,9 @@ impl FromStr for Term {
|
|
41
41
|
match s {
|
42
42
|
":" => Ok(StartDefinition),
|
43
43
|
";" => Ok(EndDefinition),
|
44
|
-
_
|
45
|
-
}
|
46
|
-
|
47
|
-
.or_else(|_| Ok(Word(s.to_ascii_lowercase())))
|
44
|
+
_ => Err(()),
|
45
|
+
}.or_else(|_| Value::from_str(s).map(Number))
|
46
|
+
.or_else(|_| Ok(Word(s.to_ascii_lowercase())))
|
48
47
|
}
|
49
48
|
}
|
50
49
|
|
@@ -77,15 +76,16 @@ impl Forth {
|
|
77
76
|
|
78
77
|
fn step_term(&mut self, term: Term) -> ForthResult {
|
79
78
|
match term {
|
80
|
-
Number(value)
|
81
|
-
Word(word)
|
79
|
+
Number(value) => self.push(value),
|
80
|
+
Word(word) => self.step_word(word),
|
82
81
|
StartDefinition => self.store_definition(),
|
83
|
-
EndDefinition
|
82
|
+
EndDefinition => Err(Error::InvalidWord),
|
84
83
|
}
|
85
84
|
}
|
86
85
|
|
87
86
|
fn step_word(&mut self, word: String) -> ForthResult {
|
88
|
-
self.defs
|
87
|
+
self.defs
|
88
|
+
.get(&word)
|
89
89
|
.ok_or(Error::UnknownWord)
|
90
90
|
.map(Clone::clone)
|
91
91
|
.map(|mut code| self.code.append(&mut code))
|
@@ -94,32 +94,17 @@ impl Forth {
|
|
94
94
|
|
95
95
|
fn step_built_in(&mut self, word: &String) -> ForthResult {
|
96
96
|
match word.as_ref() {
|
97
|
-
"+" =>
|
98
|
-
|
99
|
-
"
|
100
|
-
|
101
|
-
"
|
102
|
-
|
103
|
-
"
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
self.pop().and_then(|a| {
|
109
|
-
self.push(a).and(self.push(a))
|
110
|
-
}),
|
111
|
-
"drop" =>
|
112
|
-
self.pop().and(Forth::ok()),
|
113
|
-
"swap" =>
|
114
|
-
self.pop_two().and_then(|(a, b)| {
|
115
|
-
self.push(b).and(self.push(a))
|
116
|
-
}),
|
117
|
-
"over" =>
|
118
|
-
self.pop_two().and_then(|(a, b)| {
|
119
|
-
self.push(a).and(self.push(b)).and(self.push(a))
|
120
|
-
}),
|
121
|
-
_ =>
|
122
|
-
Err(Error::UnknownWord)
|
97
|
+
"+" => self.bin_op(|(a, b)| Ok(a + b)),
|
98
|
+
"-" => self.bin_op(|(a, b)| Ok(a - b)),
|
99
|
+
"*" => self.bin_op(|(a, b)| Ok(a * b)),
|
100
|
+
"/" => self.bin_op(|(a, b)| a.checked_div(b).ok_or(Error::DivisionByZero)),
|
101
|
+
"dup" => self.pop().and_then(|a| self.push(a).and(self.push(a))),
|
102
|
+
"drop" => self.pop().and(Forth::ok()),
|
103
|
+
"swap" => self.pop_two()
|
104
|
+
.and_then(|(a, b)| self.push(b).and(self.push(a))),
|
105
|
+
"over" => self.pop_two()
|
106
|
+
.and_then(|(a, b)| self.push(a).and(self.push(b)).and(self.push(a))),
|
107
|
+
_ => Err(Error::UnknownWord),
|
123
108
|
}
|
124
109
|
}
|
125
110
|
|
@@ -129,8 +114,8 @@ impl Forth {
|
|
129
114
|
loop {
|
130
115
|
match self.code.pop_front() {
|
131
116
|
Some(EndDefinition) => break,
|
132
|
-
Some(term)
|
133
|
-
None
|
117
|
+
Some(term) => def.push_back(term),
|
118
|
+
None => return Err(Error::InvalidWord),
|
134
119
|
}
|
135
120
|
}
|
136
121
|
|
@@ -147,20 +132,17 @@ impl Forth {
|
|
147
132
|
}
|
148
133
|
|
149
134
|
fn pop(&mut self) -> StackResult<Value> {
|
150
|
-
self.stack.pop_back()
|
151
|
-
.ok_or(Error::StackUnderflow)
|
135
|
+
self.stack.pop_back().ok_or(Error::StackUnderflow)
|
152
136
|
}
|
153
137
|
|
154
138
|
fn pop_two(&mut self) -> StackResult<(Value, Value)> {
|
155
|
-
self.pop()
|
156
|
-
.and_then(|b| {
|
157
|
-
self.pop()
|
158
|
-
.and_then(|a| Ok((a, b)))
|
159
|
-
})
|
139
|
+
self.pop().and_then(|b| self.pop().and_then(|a| Ok((a, b))))
|
160
140
|
}
|
161
141
|
|
162
142
|
fn bin_op<F>(&mut self, op: F) -> ForthResult
|
163
|
-
|
143
|
+
where
|
144
|
+
F: FnOnce((Value, Value)) -> StackResult<Value>,
|
145
|
+
{
|
164
146
|
self.pop_two()
|
165
147
|
.and_then(op)
|
166
148
|
.and_then(|value| self.push(value))
|
@@ -180,5 +162,7 @@ impl Forth {
|
|
180
162
|
.collect()
|
181
163
|
}
|
182
164
|
|
183
|
-
fn ok() -> ForthResult {
|
165
|
+
fn ok() -> ForthResult {
|
166
|
+
Ok(())
|
167
|
+
}
|
184
168
|
}
|
@@ -1,12 +1,14 @@
|
|
1
1
|
use std::collections::HashMap;
|
2
2
|
|
3
3
|
pub struct School {
|
4
|
-
grades: HashMap<u32, Vec<String
|
4
|
+
grades: HashMap<u32, Vec<String>>,
|
5
5
|
}
|
6
6
|
|
7
7
|
impl School {
|
8
8
|
pub fn new() -> School {
|
9
|
-
School {
|
9
|
+
School {
|
10
|
+
grades: HashMap::new(),
|
11
|
+
}
|
10
12
|
}
|
11
13
|
|
12
14
|
pub fn add(&mut self, grade: u32, student: &str) {
|
@@ -16,7 +16,7 @@ fn parse_hex_digit(c: char) -> Option<i64> {
|
|
16
16
|
'd' => Some(13),
|
17
17
|
'e' => Some(14),
|
18
18
|
'f' => Some(15),
|
19
|
-
_
|
19
|
+
_ => None,
|
20
20
|
}
|
21
21
|
}
|
22
22
|
|
@@ -28,8 +28,6 @@ pub fn hex_to_int(string: &str) -> Option<i64> {
|
|
28
28
|
.rev()
|
29
29
|
.enumerate()
|
30
30
|
.fold(Some(0), |acc, (pos, c)| {
|
31
|
-
parse_hex_digit(c).and_then(|n|
|
32
|
-
acc.map(|acc| acc + n * base.pow(pos as u32))
|
33
|
-
})
|
31
|
+
parse_hex_digit(c).and_then(|n| acc.map(|acc| acc + n * base.pow(pos as u32)))
|
34
32
|
})
|
35
33
|
}
|
@@ -8,14 +8,13 @@ enum IsbnType {
|
|
8
8
|
/// Checks if an 'X' is valid at the given position for the given ISBN type
|
9
9
|
#[allow(non_snake_case)]
|
10
10
|
fn is_X_valid(position: &usize, isbn_type: &IsbnType) -> bool {
|
11
|
-
(isbn_type == &IsbnType::Isbn10 && position == &9
|
12
|
-
|
11
|
+
(isbn_type == &IsbnType::Isbn10 && position == &9)
|
12
|
+
|| (isbn_type == &IsbnType::Isbn13 && position == &12)
|
13
13
|
}
|
14
14
|
|
15
15
|
/// Checks if a '-' is valid at the given position for the given ISBN type
|
16
16
|
fn is_dash_valid(position: &usize, isbn_type: &IsbnType) -> bool {
|
17
|
-
isbn_type == &IsbnType::Isbn13 &&
|
18
|
-
(position == &1 || position == &5 || position == &11)
|
17
|
+
isbn_type == &IsbnType::Isbn13 && (position == &1 || position == &5 || position == &11)
|
19
18
|
}
|
20
19
|
|
21
20
|
/// Determines whether the supplied string is a valid ISBN number
|
@@ -30,10 +29,10 @@ pub fn is_valid_isbn(isbn: &str) -> bool {
|
|
30
29
|
let mut coefficient = 10;
|
31
30
|
for (position, c) in isbn.char_indices() {
|
32
31
|
let digit_value = match c {
|
33
|
-
'0'
|
32
|
+
'0'...'9' => c.to_digit(10).unwrap(),
|
34
33
|
'X' if is_X_valid(&position, &isbn_type) => 10,
|
35
34
|
'-' if is_dash_valid(&position, &isbn_type) => continue,
|
36
|
-
_
|
35
|
+
_ => return false,
|
37
36
|
};
|
38
37
|
|
39
38
|
checksum += coefficient * digit_value;
|
@@ -75,6 +75,18 @@ fn test_invalid_isbn_too_long() {
|
|
75
75
|
assert!(!is_valid_isbn("3-598-21507-XX"));
|
76
76
|
}
|
77
77
|
|
78
|
+
#[test]
|
79
|
+
#[ignore]
|
80
|
+
fn test_valid_digits_invalid_length() {
|
81
|
+
assert!(!is_valid_isbn("35982150881"));
|
82
|
+
}
|
83
|
+
|
84
|
+
#[test]
|
85
|
+
#[ignore]
|
86
|
+
fn test_special_characters() {
|
87
|
+
assert!(!is_valid_isbn("!@#%!@"));
|
88
|
+
}
|
89
|
+
|
78
90
|
#[test]
|
79
91
|
#[ignore]
|
80
92
|
#[allow(non_snake_case)]
|
@@ -1,12 +1,18 @@
|
|
1
1
|
pub fn check(word: &str) -> bool {
|
2
|
-
|
3
2
|
// Filter all non-Alphabetic character out and collect them in a new String
|
4
|
-
let normalized_string: String = word.to_lowercase()
|
3
|
+
let normalized_string: String = word.to_lowercase()
|
4
|
+
.chars()
|
5
|
+
.filter(|c| c.is_alphabetic())
|
6
|
+
.collect();
|
5
7
|
|
6
8
|
/* Find the char element from back and front and compare the index.
|
7
9
|
If it is the same unique char the index will be the same.*/
|
8
10
|
let is_unique = |x: char, word: &str| word.find(x).unwrap() == word.rfind(x).unwrap();
|
9
11
|
|
10
12
|
// Length should be the same if it is a isogram
|
11
|
-
normalized_string.len()
|
13
|
+
normalized_string.len()
|
14
|
+
== normalized_string
|
15
|
+
.chars()
|
16
|
+
.filter(|&x| is_unique(x, normalized_string.as_str()))
|
17
|
+
.count()
|
12
18
|
}
|
@@ -13,7 +13,8 @@ pub fn lsp(string_digits: &str, span: usize) -> Result<u64, Error> {
|
|
13
13
|
return Err(Error::InvalidDigit(invalid));
|
14
14
|
}
|
15
15
|
|
16
|
-
let products: Vec<u64> = string_digits
|
16
|
+
let products: Vec<u64> = string_digits
|
17
|
+
.chars()
|
17
18
|
.map(|c| c.to_digit(10).unwrap() as u64)
|
18
19
|
.collect::<Vec<u64>>()
|
19
20
|
.windows(span)
|
@@ -1,10 +1,12 @@
|
|
1
1
|
pub fn is_valid(candidate: &str) -> bool {
|
2
|
-
if candidate.chars().filter(|c| c.is_digit(10)).take(2).count() <= 1
|
3
|
-
|
2
|
+
if candidate.chars().filter(|c| c.is_digit(10)).take(2).count() <= 1
|
3
|
+
|| candidate.chars().any(|c| !c.is_digit(10) && c != ' ')
|
4
|
+
{
|
4
5
|
return false;
|
5
6
|
}
|
6
7
|
|
7
|
-
candidate
|
8
|
+
candidate
|
9
|
+
.chars()
|
8
10
|
.filter_map(|c| c.to_digit(10))
|
9
11
|
.rev()
|
10
12
|
.enumerate()
|
@@ -1,12 +1,12 @@
|
|
1
1
|
fn is_prime(n: u32) -> bool {
|
2
2
|
let mut i: u32 = 3;
|
3
3
|
while (i * i) < (n + 1) {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
if n % i == 0 {
|
5
|
+
return false;
|
6
|
+
}
|
7
|
+
i += 1;
|
8
|
+
}
|
9
|
+
return true;
|
10
10
|
}
|
11
11
|
|
12
12
|
pub fn nth(n: u32) -> Option<u32> {
|
@@ -1,36 +1,42 @@
|
|
1
1
|
use std::collections::HashMap;
|
2
2
|
|
3
3
|
pub struct CodonInfo<'a> {
|
4
|
-
actual_codons: HashMap<&'a str, &'a str
|
4
|
+
actual_codons: HashMap<&'a str, &'a str>,
|
5
5
|
}
|
6
6
|
|
7
7
|
pub fn parse<'a>(pairs: Vec<(&'a str, &'a str)>) -> CodonInfo<'a> {
|
8
|
-
CodonInfo{
|
9
|
-
actual_codons: pairs.into_iter().collect()
|
8
|
+
CodonInfo {
|
9
|
+
actual_codons: pairs.into_iter().collect(),
|
10
10
|
}
|
11
11
|
}
|
12
12
|
|
13
13
|
impl<'a> CodonInfo<'a> {
|
14
14
|
pub fn name_for(&self, codon: &str) -> Result<&'a str, &'static str> {
|
15
15
|
if codon.len() != 3 {
|
16
|
-
return Err("invalid length")
|
16
|
+
return Err("invalid length");
|
17
17
|
}
|
18
18
|
|
19
19
|
let mut valid = true;
|
20
|
-
let lookup: String = codon
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
20
|
+
let lookup: String = codon
|
21
|
+
.chars()
|
22
|
+
.map(|l| {
|
23
|
+
// Get an example of a "letter" represented by the possibly encoded letter.
|
24
|
+
// Since every codon represented by the compressed notation has to be of
|
25
|
+
// the desired amino acid just picking one at random will do.
|
26
|
+
match l {
|
27
|
+
'A' | 'W' | 'M' | 'R' | 'D' | 'H' | 'V' | 'N' => 'A',
|
28
|
+
'C' | 'S' | 'Y' | 'B' => 'C',
|
29
|
+
'G' | 'K' => 'G',
|
30
|
+
'T' => 'T',
|
31
|
+
_ => {
|
32
|
+
valid = false;
|
33
|
+
' '
|
34
|
+
}
|
35
|
+
}
|
36
|
+
})
|
37
|
+
.collect();
|
32
38
|
if !valid {
|
33
|
-
return Err("invalid char")
|
39
|
+
return Err("invalid char");
|
34
40
|
}
|
35
41
|
|
36
42
|
// If the input table is correct (which it is) every valid codon is in it
|
@@ -2,13 +2,23 @@ use std::collections::HashMap;
|
|
2
2
|
|
3
3
|
static VALID_NUCLEOTIDES: &'static str = "ACGT";
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
Ok(input.chars().filter(|&c| c == nucleotide).count())
|
5
|
+
fn valid(c: char) -> Result<char, char> {
|
6
|
+
if VALID_NUCLEOTIDES.contains(c) {
|
7
|
+
Ok(c)
|
9
8
|
} else {
|
10
|
-
Err(
|
9
|
+
Err(c)
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
pub fn count(nucleotide: char, input: &str) -> Result<usize, char> {
|
14
|
+
valid(nucleotide)?;
|
15
|
+
let mut count = 0;
|
16
|
+
for c in input.chars() {
|
17
|
+
if valid(c)? == nucleotide {
|
18
|
+
count += 1;
|
19
|
+
}
|
11
20
|
}
|
21
|
+
Ok(count)
|
12
22
|
}
|
13
23
|
|
14
24
|
pub fn nucleotide_counts(input: &str) -> Result<HashMap<char, usize>, char> {
|
@@ -1 +1,16 @@
|
|
1
|
+
use std::collections::HashMap;
|
1
2
|
|
3
|
+
pub fn count(nucleotide: char, dna: &str) -> Result<usize, char> {
|
4
|
+
unimplemented!(
|
5
|
+
"How much of nucleotide type '{}' is contained inside DNA string '{}'?",
|
6
|
+
nucleotide,
|
7
|
+
dna
|
8
|
+
);
|
9
|
+
}
|
10
|
+
|
11
|
+
pub fn nucleotide_counts(dna: &str) -> Result<HashMap<char, usize>, char> {
|
12
|
+
unimplemented!(
|
13
|
+
"How much of every nucleotide type is contained inside DNA string '{}'?",
|
14
|
+
dna
|
15
|
+
);
|
16
|
+
}
|
@@ -29,13 +29,13 @@ fn test_count_empty() {
|
|
29
29
|
#[test]
|
30
30
|
#[ignore]
|
31
31
|
fn count_invalid_nucleotide() {
|
32
|
-
|
32
|
+
assert_eq!(dna::count('X', "A"), Err('X'));
|
33
33
|
}
|
34
34
|
|
35
35
|
#[test]
|
36
36
|
#[ignore]
|
37
37
|
fn count_invalid_dna() {
|
38
|
-
|
38
|
+
assert_eq!(dna::count('A', "AX"), Err('X'));
|
39
39
|
}
|
40
40
|
|
41
41
|
#[test]
|
@@ -81,5 +81,5 @@ fn test_nucleotide_count_counts_all() {
|
|
81
81
|
#[test]
|
82
82
|
#[ignore]
|
83
83
|
fn counts_invalid_nucleotide_results_in_err() {
|
84
|
-
|
84
|
+
assert_eq!(dna::nucleotide_counts("GGXXX"), Err('X'));
|
85
85
|
}
|