trackler 2.2.1.83 → 2.2.1.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/bash/config.json +43 -6
- data/tracks/bash/exercises/collatz-conjecture/README.md +34 -0
- data/tracks/bash/exercises/collatz-conjecture/collatz_test.sh +49 -0
- data/tracks/bash/exercises/collatz-conjecture/example.sh +22 -0
- data/tracks/bash/exercises/grains/README.md +35 -0
- data/tracks/bash/exercises/grains/example.sh +10 -0
- data/tracks/bash/exercises/grains/grains_test.sh +81 -0
- data/tracks/bash/exercises/luhn/README.md +76 -0
- data/tracks/bash/exercises/luhn/example.sh +32 -0
- data/tracks/bash/exercises/luhn/luhn_test.sh +105 -0
- data/tracks/clojure/config.json +9 -1
- data/tracks/clojure/exercises/two-fer/README.md +19 -0
- data/tracks/clojure/exercises/two-fer/project.clj +4 -0
- data/tracks/clojure/exercises/two-fer/src/example.clj +5 -0
- data/tracks/clojure/exercises/two-fer/src/two_fer.clj +5 -0
- data/tracks/clojure/exercises/two-fer/test/two_fer_test.clj +12 -0
- data/tracks/python/config.json +5 -3
- data/tracks/python/exercises/parallel-letter-frequency/README.md +36 -0
- data/tracks/python/exercises/parallel-letter-frequency/example.py +56 -0
- data/tracks/python/exercises/parallel-letter-frequency/parallel_letter_frequency.py +2 -0
- data/tracks/python/exercises/parallel-letter-frequency/parallel_letter_frequency_test.py +61 -0
- data/tracks/python/exercises/reverse-string/reverse_string_test.py +5 -5
- data/tracks/ruby/README.md +7 -1
- data/tracks/ruby/exercises/rotational-cipher/README.md +63 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3ec763db2b39453f204556765096d8b89410636
|
4
|
+
data.tar.gz: 0b10a5133a6d4f9fa08142ae215484fd257b8bc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 136ccecbe72a54b7da0c44b660a02b8dbe4e0304d0e42360f71f53937617221936a011a525b5f6ccd00f98e7ba969b7ddf52f8c16d4725c247a80d078c3731ce
|
7
|
+
data.tar.gz: 3d20a2d47b630cc688667dc3ad626e13c603f50c61a969b19a4059cc3a4ed61b74d72a7ef57ac09340cfb84d8d9502f9a637e1b4e88f8f61b15611010d561639
|
data/lib/trackler/version.rb
CHANGED
data/tracks/bash/config.json
CHANGED
@@ -51,6 +51,17 @@
|
|
51
51
|
],
|
52
52
|
"uuid": "e24451fd-761d-4d20-81d9-e470486ec44a"
|
53
53
|
},
|
54
|
+
{
|
55
|
+
"core": true,
|
56
|
+
"difficulty": 1,
|
57
|
+
"slug": "grains",
|
58
|
+
"topics": [
|
59
|
+
"control_flow_conditionals",
|
60
|
+
"input_validation",
|
61
|
+
"mathematics"
|
62
|
+
],
|
63
|
+
"uuid": "c9d36155-10e8-4a75-a732-3c43a68910eb"
|
64
|
+
},
|
54
65
|
{
|
55
66
|
"core": false,
|
56
67
|
"difficulty": 1,
|
@@ -182,6 +193,19 @@
|
|
182
193
|
"unlocked_by": "pangram",
|
183
194
|
"uuid": "51bd6542-408b-4a73-8343-1c4d50db5315"
|
184
195
|
},
|
196
|
+
{
|
197
|
+
"core": false,
|
198
|
+
"difficulty": 2,
|
199
|
+
"slug": "triangle",
|
200
|
+
"topics": [
|
201
|
+
"boolean_logic",
|
202
|
+
"input_validation",
|
203
|
+
"number_comparison",
|
204
|
+
"mathematics"
|
205
|
+
],
|
206
|
+
"unlocked_by": "leap",
|
207
|
+
"uuid": "0f79f9ab-4a51-468c-88ca-84f0bf7cfc38"
|
208
|
+
},
|
185
209
|
{
|
186
210
|
"core": false,
|
187
211
|
"difficulty": 2,
|
@@ -195,16 +219,29 @@
|
|
195
219
|
},
|
196
220
|
{
|
197
221
|
"core": false,
|
198
|
-
"difficulty":
|
199
|
-
"slug": "
|
222
|
+
"difficulty": 3,
|
223
|
+
"slug": "luhn",
|
200
224
|
"topics": [
|
201
|
-
"
|
225
|
+
"algorithms",
|
226
|
+
"control_flow_conditionals",
|
227
|
+
"integers",
|
228
|
+
"mathematics"
|
229
|
+
],
|
230
|
+
"unlocked_by": "difference-of-squares",
|
231
|
+
"uuid": "a3b16d02-2963-445d-9339-7e3002375a71"
|
232
|
+
},
|
233
|
+
{
|
234
|
+
"core": false,
|
235
|
+
"difficulty": 3,
|
236
|
+
"slug": "collatz-conjecture",
|
237
|
+
"topics": [
|
238
|
+
"control_flow_conditionals",
|
202
239
|
"input_validation",
|
203
|
-
"
|
240
|
+
"integers",
|
204
241
|
"mathematics"
|
205
242
|
],
|
206
|
-
"unlocked_by": "
|
207
|
-
"uuid": "
|
243
|
+
"unlocked_by": "armstrong-numbers",
|
244
|
+
"uuid": "b4793e6d-f443-41ea-8289-95e18a5dbef4"
|
208
245
|
},
|
209
246
|
{
|
210
247
|
"core": false,
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Collatz Conjecture
|
2
|
+
|
3
|
+
The Collatz Conjecture or 3x+1 problem can be summarized as follows:
|
4
|
+
|
5
|
+
Take any positive integer n. If n is even, divide n by 2 to get n / 2. If n is
|
6
|
+
odd, multiply n by 3 and add 1 to get 3n + 1. Repeat the process indefinitely.
|
7
|
+
The conjecture states that no matter which number you start with, you will
|
8
|
+
always reach 1 eventually.
|
9
|
+
|
10
|
+
Given a number n, return the number of steps required to reach 1.
|
11
|
+
|
12
|
+
## Examples
|
13
|
+
|
14
|
+
Starting with n = 12, the steps would be as follows:
|
15
|
+
|
16
|
+
0. 12
|
17
|
+
1. 6
|
18
|
+
2. 3
|
19
|
+
3. 10
|
20
|
+
4. 5
|
21
|
+
5. 16
|
22
|
+
6. 8
|
23
|
+
7. 4
|
24
|
+
8. 2
|
25
|
+
9. 1
|
26
|
+
|
27
|
+
Resulting in 9 steps. So for input n = 12, the return value would be 9.
|
28
|
+
|
29
|
+
## Source
|
30
|
+
|
31
|
+
An unsolved problem in mathematics named after mathematician Lothar Collatz [Wikipedia](https://en.wikipedia.org/wiki/3x_%2B_1_problem)
|
32
|
+
|
33
|
+
## Submitting Incomplete Solutions
|
34
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env bats
|
2
|
+
|
3
|
+
@test "zero steps for one" {
|
4
|
+
#skip
|
5
|
+
run bash collatz.sh 1
|
6
|
+
|
7
|
+
[ "$status" -eq 0 ]
|
8
|
+
[ "$output" -eq 0 ]
|
9
|
+
}
|
10
|
+
|
11
|
+
@test "divide if even" {
|
12
|
+
skip
|
13
|
+
run bash collatz.sh 16
|
14
|
+
|
15
|
+
[ "$status" -eq 0 ]
|
16
|
+
[ "$output" -eq 4 ]
|
17
|
+
}
|
18
|
+
|
19
|
+
@test "even and odd steps" {
|
20
|
+
skip
|
21
|
+
run bash collatz.sh 12
|
22
|
+
|
23
|
+
[ "$status" -eq 0 ]
|
24
|
+
[ "$output" -eq 9 ]
|
25
|
+
}
|
26
|
+
|
27
|
+
@test "large number of even and odd steps" {
|
28
|
+
skip
|
29
|
+
run bash collatz.sh 1000000
|
30
|
+
|
31
|
+
[ "$status" -eq 0 ]
|
32
|
+
[ "$output" -eq 152 ]
|
33
|
+
}
|
34
|
+
|
35
|
+
@test "zero is an error" {
|
36
|
+
skip
|
37
|
+
run bash collatz.sh 0
|
38
|
+
|
39
|
+
[ "$status" -eq 1 ]
|
40
|
+
[ "$output" == "Error: Only positive numbers are allowed" ]
|
41
|
+
}
|
42
|
+
|
43
|
+
@test "negative value is an error" {
|
44
|
+
skip
|
45
|
+
run bash collatz.sh -15
|
46
|
+
|
47
|
+
[ "$status" -eq 1 ]
|
48
|
+
[ "$output" == "Error: Only positive numbers are allowed" ]
|
49
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
if [ "$1" -gt 0 ]; then
|
4
|
+
N=$1
|
5
|
+
else
|
6
|
+
echo "Error: Only positive numbers are allowed"
|
7
|
+
exit 1
|
8
|
+
fi
|
9
|
+
|
10
|
+
STEP=0
|
11
|
+
|
12
|
+
while [ "$N" -ne "1" ]
|
13
|
+
do
|
14
|
+
if [ "$(($N % 2))" -eq "0" ]; then
|
15
|
+
N=$(($N / 2))
|
16
|
+
else
|
17
|
+
N=$((($N * 3) + 1))
|
18
|
+
fi
|
19
|
+
STEP=$(($STEP + 1))
|
20
|
+
done
|
21
|
+
|
22
|
+
echo $STEP
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Grains
|
2
|
+
|
3
|
+
Calculate the number of grains of wheat on a chessboard given that the number
|
4
|
+
on each square doubles.
|
5
|
+
|
6
|
+
There once was a wise servant who saved the life of a prince. The king
|
7
|
+
promised to pay whatever the servant could dream up. Knowing that the
|
8
|
+
king loved chess, the servant told the king he would like to have grains
|
9
|
+
of wheat. One grain on the first square of a chess board. Two grains on
|
10
|
+
the next. Four on the third, and so on.
|
11
|
+
|
12
|
+
There are 64 squares on a chessboard.
|
13
|
+
|
14
|
+
Write code that shows:
|
15
|
+
- how many grains were on each square, and
|
16
|
+
- the total number of grains
|
17
|
+
|
18
|
+
## For bonus points
|
19
|
+
|
20
|
+
Did you get the tests passing and the code clean? If you want to, these
|
21
|
+
are some additional things you could try:
|
22
|
+
|
23
|
+
- Optimize for speed.
|
24
|
+
- Optimize for readability.
|
25
|
+
|
26
|
+
Then please share your thoughts in a comment on the submission. Did this
|
27
|
+
experiment make the code better? Worse? Did you learn anything from it?
|
28
|
+
|
29
|
+
## Source
|
30
|
+
|
31
|
+
Calculate the number of grains of wheat on a chessboard given that the number on each square doubles. [JavaRanch Cattle Drive, exercise 6](http://www.javaranch.com/grains.jsp)
|
32
|
+
|
33
|
+
## Submitting Incomplete Solutions
|
34
|
+
|
35
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env bats
|
2
|
+
|
3
|
+
@test "Square 1" {
|
4
|
+
#skip
|
5
|
+
run bash grains.sh 1
|
6
|
+
|
7
|
+
[ "$status" -eq 0 ]
|
8
|
+
[ "$output" = "1" ]
|
9
|
+
}
|
10
|
+
|
11
|
+
@test "Square 2" {
|
12
|
+
#skip
|
13
|
+
run bash grains.sh 2
|
14
|
+
|
15
|
+
[ "$status" -eq 0 ]
|
16
|
+
[ "$output" = "2" ]
|
17
|
+
}
|
18
|
+
|
19
|
+
@test "Square 3" {
|
20
|
+
#skip
|
21
|
+
run bash grains.sh 3
|
22
|
+
|
23
|
+
[ "$status" -eq 0 ]
|
24
|
+
[ "$output" = "4" ]
|
25
|
+
}
|
26
|
+
|
27
|
+
@test "Square 4" {
|
28
|
+
#skip
|
29
|
+
run bash grains.sh 4
|
30
|
+
|
31
|
+
[ "$status" -eq 0 ]
|
32
|
+
[ "$output" = "8" ]
|
33
|
+
}
|
34
|
+
|
35
|
+
@test "Square 16" {
|
36
|
+
#skip
|
37
|
+
run bash grains.sh 16
|
38
|
+
|
39
|
+
[ "$status" -eq 0 ]
|
40
|
+
[ "$output" = "32768" ]
|
41
|
+
}
|
42
|
+
|
43
|
+
@test "Square 32" {
|
44
|
+
#skip
|
45
|
+
run bash grains.sh 32
|
46
|
+
|
47
|
+
[ "$status" -eq 0 ]
|
48
|
+
[ "$output" = "2147483648" ]
|
49
|
+
}
|
50
|
+
|
51
|
+
@test "Square 64" {
|
52
|
+
#skip
|
53
|
+
run bash grains.sh 64
|
54
|
+
|
55
|
+
[ "$status" -eq 0 ]
|
56
|
+
[ "$output" = "9223372036854775808" ]
|
57
|
+
}
|
58
|
+
|
59
|
+
@test "Square 0 causes error" {
|
60
|
+
#skip
|
61
|
+
run bash grains.sh 0
|
62
|
+
|
63
|
+
[ "$status" -eq 1 ]
|
64
|
+
[ "$output" = "Error: invalid input" ]
|
65
|
+
}
|
66
|
+
|
67
|
+
@test "Square -1 causes error" {
|
68
|
+
#skip
|
69
|
+
run bash grains.sh -1
|
70
|
+
|
71
|
+
[ "$status" -eq 1 ]
|
72
|
+
[ "$output" = "Error: invalid input" ]
|
73
|
+
}
|
74
|
+
|
75
|
+
@test "Square 65 causes error" {
|
76
|
+
#skip
|
77
|
+
run bash grains.sh 65
|
78
|
+
|
79
|
+
[ "$status" -eq 1 ]
|
80
|
+
[ "$output" = "Error: invalid input" ]
|
81
|
+
}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Luhn
|
2
|
+
|
3
|
+
Given a number determine whether or not it is valid per the Luhn formula.
|
4
|
+
|
5
|
+
The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is
|
6
|
+
a simple checksum formula used to validate a variety of identification
|
7
|
+
numbers, such as credit card numbers and Canadian Social Insurance
|
8
|
+
Numbers.
|
9
|
+
|
10
|
+
The task is to check if a given string is valid.
|
11
|
+
|
12
|
+
Validating a Number
|
13
|
+
------
|
14
|
+
|
15
|
+
Strings of length 1 or less are not valid. Spaces are allowed in the input,
|
16
|
+
but they should be stripped before checking. All other non-digit characters
|
17
|
+
are disallowed.
|
18
|
+
|
19
|
+
## Example 1: valid credit card number
|
20
|
+
|
21
|
+
```text
|
22
|
+
4539 1488 0343 6467
|
23
|
+
```
|
24
|
+
|
25
|
+
The first step of the Luhn algorithm is to double every second digit,
|
26
|
+
starting from the right. We will be doubling
|
27
|
+
|
28
|
+
```text
|
29
|
+
4_3_ 1_8_ 0_4_ 6_6_
|
30
|
+
```
|
31
|
+
|
32
|
+
If doubling the number results in a number greater than 9 then subtract 9
|
33
|
+
from the product. The results of our doubling:
|
34
|
+
|
35
|
+
```text
|
36
|
+
8569 2478 0383 3437
|
37
|
+
```
|
38
|
+
|
39
|
+
Then sum all of the digits:
|
40
|
+
|
41
|
+
```text
|
42
|
+
8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80
|
43
|
+
```
|
44
|
+
|
45
|
+
If the sum is evenly divisible by 10, then the number is valid. This number is valid!
|
46
|
+
|
47
|
+
## Example 2: invalid credit card number
|
48
|
+
|
49
|
+
```text
|
50
|
+
8273 1232 7352 0569
|
51
|
+
```
|
52
|
+
|
53
|
+
Double the second digits, starting from the right
|
54
|
+
|
55
|
+
```text
|
56
|
+
7253 2262 5312 0539
|
57
|
+
```
|
58
|
+
|
59
|
+
Sum the digits
|
60
|
+
|
61
|
+
```text
|
62
|
+
7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57
|
63
|
+
```
|
64
|
+
|
65
|
+
57 is not evenly divisible by 10, so this number is not valid.
|
66
|
+
|
67
|
+
Run the tests with:
|
68
|
+
|
69
|
+
bats whatever_test.sh
|
70
|
+
|
71
|
+
## Source
|
72
|
+
|
73
|
+
The Luhn Algorithm on Wikipedia [Wikipedia](http://en.wikipedia.org/wiki/Luhn_algorithm)
|
74
|
+
|
75
|
+
## Submitting Incomplete Solutions
|
76
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
num=$(echo "$1" | sed 's/[\ ]//g')
|
4
|
+
|
5
|
+
if ! [[ 10#$num -ge 0 ]] 2>/dev/null || ! [[ ${#num} -gt 1 ]] ; then
|
6
|
+
echo "false"
|
7
|
+
else
|
8
|
+
shift 1
|
9
|
+
|
10
|
+
len=${#num}
|
11
|
+
is_odd=1
|
12
|
+
sum=0
|
13
|
+
|
14
|
+
for((t = len - 1; t >= 0; --t)) {
|
15
|
+
digit=${num:$t:1}
|
16
|
+
|
17
|
+
if [[ $is_odd -eq 1 ]]; then
|
18
|
+
sum=$(( sum + $digit ))
|
19
|
+
else
|
20
|
+
sum=$(( $sum + ( $digit != 9 ? ( ( 2 * $digit ) % 9 ) : 9 ) ))
|
21
|
+
fi
|
22
|
+
|
23
|
+
is_odd=$(( ! $is_odd ))
|
24
|
+
}
|
25
|
+
|
26
|
+
if [[ 0 -eq $(( 0 != ( $sum % 10 ) )) ]] ; then
|
27
|
+
echo "true"
|
28
|
+
else
|
29
|
+
echo "false"
|
30
|
+
fi
|
31
|
+
|
32
|
+
fi
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env bats
|
2
|
+
|
3
|
+
@test "single digit strings cannot be valid" {
|
4
|
+
#skip
|
5
|
+
run bash luhn.sh "1"
|
6
|
+
|
7
|
+
[ "$status" -eq 0 ]
|
8
|
+
[ "$output" == "false" ]
|
9
|
+
}
|
10
|
+
|
11
|
+
@test "a single zero is invalid" {
|
12
|
+
#skip
|
13
|
+
run bash luhn.sh "0"
|
14
|
+
|
15
|
+
[ "$status" -eq 0 ]
|
16
|
+
[ "$output" == "false" ]
|
17
|
+
}
|
18
|
+
|
19
|
+
@test "a simple valid SIN that remains valid if reversed" {
|
20
|
+
#skip
|
21
|
+
run bash luhn.sh "059"
|
22
|
+
|
23
|
+
[ "$status" -eq 0 ]
|
24
|
+
[ "$output" == "true" ]
|
25
|
+
}
|
26
|
+
|
27
|
+
@test "a simple valid SIN that becomes invalid if reversed" {
|
28
|
+
#skip
|
29
|
+
run bash luhn.sh "59"
|
30
|
+
|
31
|
+
[ "$status" -eq 0 ]
|
32
|
+
[ "$output" == "true" ]
|
33
|
+
}
|
34
|
+
|
35
|
+
@test "a valid Canadian SIN" {
|
36
|
+
#skip
|
37
|
+
run bash luhn.sh "055 444 285"
|
38
|
+
|
39
|
+
[ "$status" -eq 0 ]
|
40
|
+
[ "$output" == "true" ]
|
41
|
+
}
|
42
|
+
|
43
|
+
@test "invalid Canadian SID" {
|
44
|
+
#skip
|
45
|
+
run bash luhn.sh "055 444 286"
|
46
|
+
|
47
|
+
[ "$status" -eq 0 ]
|
48
|
+
[ "$output" == "false" ]
|
49
|
+
}
|
50
|
+
|
51
|
+
@test "invalid credit card" {
|
52
|
+
#skip
|
53
|
+
run bash luhn.sh "8273 1232 7352 0569"
|
54
|
+
|
55
|
+
[ "$status" -eq 0 ]
|
56
|
+
[ "$output" == "false" ]
|
57
|
+
}
|
58
|
+
|
59
|
+
@test "valid strings with a non-digit included become invalid" {
|
60
|
+
#skip
|
61
|
+
run bash luhn.sh "055a 444 285"
|
62
|
+
|
63
|
+
[ "$status" -eq 0 ]
|
64
|
+
[ "$output" == "false" ]
|
65
|
+
}
|
66
|
+
|
67
|
+
@test "valid strings with punctuation included become invalid" {
|
68
|
+
#skip
|
69
|
+
run bash luhn.sh "055-444-285"
|
70
|
+
|
71
|
+
[ "$status" -eq 0 ]
|
72
|
+
[ "$output" == "false" ]
|
73
|
+
}
|
74
|
+
|
75
|
+
@test "valid strings with symbols included become invalid" {
|
76
|
+
#skip
|
77
|
+
run bash luhn.sh "055£ 444$ 285"
|
78
|
+
|
79
|
+
[ "$status" -eq 0 ]
|
80
|
+
[ "$output" == "false" ]
|
81
|
+
}
|
82
|
+
|
83
|
+
@test "single zero with space is invalid" {
|
84
|
+
#skip
|
85
|
+
run bash luhn.sh " 0"
|
86
|
+
|
87
|
+
[ "$status" -eq 0 ]
|
88
|
+
[ "$output" == "false" ]
|
89
|
+
}
|
90
|
+
|
91
|
+
@test "more than a single zero is valid" {
|
92
|
+
#skip
|
93
|
+
run bash luhn.sh "0000 0"
|
94
|
+
|
95
|
+
[ "$status" -eq 0 ]
|
96
|
+
[ "$output" == "true" ]
|
97
|
+
}
|
98
|
+
|
99
|
+
@test "input digit 9 is correctly converted to output digit 9" {
|
100
|
+
#skip
|
101
|
+
run bash luhn.sh "091"
|
102
|
+
|
103
|
+
[ "$status" -eq 0 ]
|
104
|
+
[ "$output" == "true" ]
|
105
|
+
}
|
data/tracks/clojure/config.json
CHANGED
@@ -17,6 +17,14 @@
|
|
17
17
|
"unlocked_by": null,
|
18
18
|
"uuid": "a4bdbdfd-1db1-425c-a243-dd032dc7b93a"
|
19
19
|
},
|
20
|
+
{
|
21
|
+
"core": false,
|
22
|
+
"difficulty": 1,
|
23
|
+
"slug": "two-fer",
|
24
|
+
"topics": null,
|
25
|
+
"unlocked_by": null,
|
26
|
+
"uuid": "91a1f32c-0dac-4c65-8a13-49da90d21520"
|
27
|
+
},
|
20
28
|
{
|
21
29
|
"core": false,
|
22
30
|
"difficulty": 1,
|
@@ -585,4 +593,4 @@
|
|
585
593
|
],
|
586
594
|
"foregone": [],
|
587
595
|
"language": "Clojure"
|
588
|
-
}
|
596
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Two-fer
|
2
|
+
|
3
|
+
`Two-fer` or `2-fer` is short for two for one. One for you and one for me.
|
4
|
+
|
5
|
+
```text
|
6
|
+
"One for X, one for me."
|
7
|
+
```
|
8
|
+
|
9
|
+
When X is a name or "you".
|
10
|
+
|
11
|
+
If the given name is "Alice", the result should be "One for Alice, one for me."
|
12
|
+
If no name is given, the result should be "One for you, one for me."
|
13
|
+
|
14
|
+
## Source
|
15
|
+
|
16
|
+
This is an exercise to introduce users to basic programming constructs, just after hello World. [http://en.wikipedia.org/wiki/Two-fer](http://en.wikipedia.org/wiki/Two-fer)
|
17
|
+
|
18
|
+
## Submitting Incomplete Solutions
|
19
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
(ns two-fer-test
|
2
|
+
(:require [clojure.test :refer [deftest is]]
|
3
|
+
two-fer))
|
4
|
+
|
5
|
+
(deftest two-fer-test
|
6
|
+
(is (= "One for you, one for me." (two-fer/two-fer))))
|
7
|
+
|
8
|
+
(deftest name-alice-test
|
9
|
+
(is (= "One for Alice, one for me." (two-fer/two-fer "Alice"))))
|
10
|
+
|
11
|
+
(deftest name-bob-test
|
12
|
+
(is (= "One for Bob, one for me." (two-fer/two-fer "Bob"))))
|
data/tracks/python/config.json
CHANGED
@@ -1298,9 +1298,11 @@
|
|
1298
1298
|
"uuid": "6b7f7b1f-c388-4f4c-b924-84535cc5e1a0",
|
1299
1299
|
"slug": "hexadecimal",
|
1300
1300
|
"deprecated": true
|
1301
|
+
},
|
1302
|
+
{
|
1303
|
+
"uuid": "da03fca4-4606-48d8-9137-6e40396f7759",
|
1304
|
+
"slug": "parallel-letter-frequency",
|
1305
|
+
"deprecated": true
|
1301
1306
|
}
|
1302
|
-
],
|
1303
|
-
"foregone": [
|
1304
|
-
"parallel-letter-frequency"
|
1305
1307
|
]
|
1306
1308
|
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Parallel Letter Frequency
|
2
|
+
|
3
|
+
Count the frequency of letters in texts using parallel computation.
|
4
|
+
|
5
|
+
Parallelism is about doing things in parallel that can also be done
|
6
|
+
sequentially. A common example is counting the frequency of letters.
|
7
|
+
Create a function that returns the total frequency of each letter in a
|
8
|
+
list of texts and that employs parallelism.
|
9
|
+
|
10
|
+
## Exception messages
|
11
|
+
|
12
|
+
Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
|
13
|
+
indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
|
14
|
+
every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
|
15
|
+
a message.
|
16
|
+
|
17
|
+
To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
|
18
|
+
`raise Exception`, you shold write:
|
19
|
+
|
20
|
+
```python
|
21
|
+
raise Exception("Meaningful message indicating the source of the error")
|
22
|
+
```
|
23
|
+
|
24
|
+
|
25
|
+
## Submitting Exercises
|
26
|
+
|
27
|
+
Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
|
28
|
+
|
29
|
+
For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/python/bob/bob.py`.
|
30
|
+
|
31
|
+
For more detailed information about running tests, code style and linting,
|
32
|
+
please see the [help page](http://exercism.io/languages/python).
|
33
|
+
|
34
|
+
|
35
|
+
## Submitting Incomplete Solutions
|
36
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
from collections import Counter
|
3
|
+
from threading import Lock, Thread
|
4
|
+
from time import sleep
|
5
|
+
import sys
|
6
|
+
if sys.version[0] == '2':
|
7
|
+
from Queue import Queue
|
8
|
+
else:
|
9
|
+
from queue import Queue
|
10
|
+
|
11
|
+
total_workers = 3 # Maximum number of threads chosen arbitrarily
|
12
|
+
|
13
|
+
|
14
|
+
class LetterCounter(object):
|
15
|
+
|
16
|
+
def __init__(self):
|
17
|
+
self.lock = Lock()
|
18
|
+
self.value = Counter()
|
19
|
+
|
20
|
+
def add_counter(self, counter_to_add):
|
21
|
+
self.lock.acquire()
|
22
|
+
try:
|
23
|
+
self.value = self.value + counter_to_add
|
24
|
+
finally:
|
25
|
+
self.lock.release()
|
26
|
+
|
27
|
+
|
28
|
+
def count_letters(queue_of_texts, letter_to_frequency, worker_id):
|
29
|
+
while not queue_of_texts.empty():
|
30
|
+
sleep(worker_id + 1)
|
31
|
+
line_input = queue_of_texts.get()
|
32
|
+
if line_input is not None:
|
33
|
+
letters_in_line = Counter([x for x in line_input.lower() if
|
34
|
+
x.isalpha()])
|
35
|
+
letter_to_frequency.add_counter(letters_in_line)
|
36
|
+
queue_of_texts.task_done()
|
37
|
+
if line_input is None:
|
38
|
+
break
|
39
|
+
|
40
|
+
|
41
|
+
def calculate(list_of_texts):
|
42
|
+
queue_of_texts = Queue()
|
43
|
+
[queue_of_texts.put(line) for line in list_of_texts]
|
44
|
+
letter_to_frequency = LetterCounter()
|
45
|
+
threads = []
|
46
|
+
for i in range(total_workers):
|
47
|
+
worker = Thread(target=count_letters, args=(queue_of_texts,
|
48
|
+
letter_to_frequency, i))
|
49
|
+
worker.start()
|
50
|
+
threads.append(worker)
|
51
|
+
queue_of_texts.join()
|
52
|
+
for i in range(total_workers):
|
53
|
+
queue_of_texts.put(None)
|
54
|
+
for t in threads:
|
55
|
+
t.join()
|
56
|
+
return letter_to_frequency.value
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
from collections import Counter
|
3
|
+
import unittest
|
4
|
+
|
5
|
+
from parallel_letter_frequency import calculate
|
6
|
+
|
7
|
+
|
8
|
+
class ParallelLetterFrequencyTest(unittest.TestCase):
|
9
|
+
def test_one_letter(self):
|
10
|
+
actual = calculate(['a'])
|
11
|
+
expected = {'a': 1}
|
12
|
+
self.assertDictEqual(actual, expected)
|
13
|
+
|
14
|
+
def test_case_insensitivity(self):
|
15
|
+
actual = calculate(['aA'])
|
16
|
+
expected = {'a': 2}
|
17
|
+
self.assertDictEqual(actual, expected)
|
18
|
+
|
19
|
+
def test_numbers(self):
|
20
|
+
actual = calculate(['012', '345', '6789'])
|
21
|
+
expected = {}
|
22
|
+
self.assertDictEqual(actual, expected)
|
23
|
+
|
24
|
+
def test_punctuations(self):
|
25
|
+
actual = calculate(['[]\;,', './{}|', ':"<>?'])
|
26
|
+
expected = {}
|
27
|
+
self.assertDictEqual(actual, expected)
|
28
|
+
|
29
|
+
def test_whitespaces(self):
|
30
|
+
actual = calculate([' ', '\t ', '\n\n'])
|
31
|
+
expected = {}
|
32
|
+
self.assertDictEqual(actual, expected)
|
33
|
+
|
34
|
+
def test_repeated_string_with_known_frequencies(self):
|
35
|
+
letter_frequency = 3
|
36
|
+
text_input = 'abc\n' * letter_frequency
|
37
|
+
actual = calculate(text_input.split('\n'))
|
38
|
+
expected = {'a': letter_frequency, 'b': letter_frequency,
|
39
|
+
'c': letter_frequency}
|
40
|
+
self.assertDictEqual(actual, expected)
|
41
|
+
|
42
|
+
def test_multiline_text(self):
|
43
|
+
text_input = "3 Quotes from Excerism Homepage:\n" + \
|
44
|
+
"\tOne moment you feel like you're\n" + \
|
45
|
+
"getting it. The next moment you're\n" + \
|
46
|
+
"stuck.\n" + \
|
47
|
+
"\tYou know what it’s like to be fluent.\n" + \
|
48
|
+
"Suddenly you’re feeling incompetent\n" + \
|
49
|
+
"and clumsy.\n" + \
|
50
|
+
"\tHaphazard, convoluted code is\n" + \
|
51
|
+
"infuriating, not to mention costly. That\n" + \
|
52
|
+
"slapdash explosion of complexity is an\n" + \
|
53
|
+
"expensive yak shave waiting to\n" + \
|
54
|
+
"happen."
|
55
|
+
actual = calculate(text_input.split('\n'))
|
56
|
+
expected = Counter([x for x in text_input.lower() if x.isalpha()])
|
57
|
+
self.assertDictEqual(actual, expected)
|
58
|
+
|
59
|
+
|
60
|
+
if __name__ == '__main__':
|
61
|
+
unittest.main()
|
@@ -6,19 +6,19 @@ from reverse_string import reverse
|
|
6
6
|
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.1
|
7
7
|
|
8
8
|
class ReverseStringTests(unittest.TestCase):
|
9
|
-
def
|
9
|
+
def test_empty_string(self):
|
10
10
|
self.assertEqual(reverse(''), '')
|
11
11
|
|
12
|
-
def
|
12
|
+
def test_a_word(self):
|
13
13
|
self.assertEqual(reverse('robot'), 'tobor')
|
14
14
|
|
15
|
-
def
|
15
|
+
def test_a_capitalized_word(self):
|
16
16
|
self.assertEqual(reverse('Ramen'), 'nemaR')
|
17
17
|
|
18
|
-
def
|
18
|
+
def test_a_sentence_with_punctuation(self):
|
19
19
|
self.assertEqual(reverse('I\'m hungry!'), '!yrgnuh m\'I')
|
20
20
|
|
21
|
-
def
|
21
|
+
def test_a_palindrome(self):
|
22
22
|
self.assertEqual(reverse('racecar'), 'racecar')
|
23
23
|
|
24
24
|
|
data/tracks/ruby/README.md
CHANGED
@@ -315,9 +315,15 @@ string indices to integer indices.
|
|
315
315
|
|
316
316
|
## READMEs
|
317
317
|
|
318
|
-
|
318
|
+
All exercises must have a README.md file, but should not be created manually. The READMEs
|
319
319
|
are constructed using shared metadata, which lives in the [problem-specifications][] repo.
|
320
320
|
|
321
|
+
Use the `configlet` tool to generate a README from shared metadata:
|
322
|
+
|
323
|
+
1. Clone the [problem-specifications][] repo into an adjacent directory.
|
324
|
+
2. Fetch the configlet appropriate for your system: `bin/fetch-configlet`
|
325
|
+
3. Generate the readme for a particular exercise: `bin/configlet generate . --only rotational-cipher`
|
326
|
+
|
321
327
|
## Contributing Guide
|
322
328
|
|
323
329
|
For an in-depth discussion of how exercism language tracks and exercises work, please see the
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Rotational Cipher
|
2
|
+
|
3
|
+
Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.
|
4
|
+
|
5
|
+
The Caesar cipher is a simple shift cipher that relies on
|
6
|
+
transposing all the letters in the alphabet using an integer key
|
7
|
+
between `0` and `26`. Using a key of `0` or `26` will always yield
|
8
|
+
the same output due to modular arithmetic. The letter is shifted
|
9
|
+
for as many values as the value of the key.
|
10
|
+
|
11
|
+
The general notation for rotational ciphers is `ROT + <key>`.
|
12
|
+
The most commonly used rotational cipher is `ROT13`.
|
13
|
+
|
14
|
+
A `ROT13` on the Latin alphabet would be as follows:
|
15
|
+
|
16
|
+
```text
|
17
|
+
Plain: abcdefghijklmnopqrstuvwxyz
|
18
|
+
Cipher: nopqrstuvwxyzabcdefghijklm
|
19
|
+
```
|
20
|
+
|
21
|
+
It is stronger than the Atbash cipher because it has 27 possible keys, and 25 usable keys.
|
22
|
+
|
23
|
+
Ciphertext is written out in the same formatting as the input including spaces and punctuation.
|
24
|
+
|
25
|
+
## Examples
|
26
|
+
|
27
|
+
- ROT5 `omg` gives `trl`
|
28
|
+
- ROT0 `c` gives `c`
|
29
|
+
- ROT26 `Cool` gives `Cool`
|
30
|
+
- ROT13 `The quick brown fox jumps over the lazy dog.` gives `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.`
|
31
|
+
- ROT13 `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` gives `The quick brown fox jumps over the lazy dog.`
|
32
|
+
|
33
|
+
* * * *
|
34
|
+
|
35
|
+
For installation and learning resources, refer to the
|
36
|
+
[exercism help page](http://exercism.io/languages/ruby).
|
37
|
+
|
38
|
+
For running the tests provided, you will need the Minitest gem. Open a
|
39
|
+
terminal window and run the following command to install minitest:
|
40
|
+
|
41
|
+
gem install minitest
|
42
|
+
|
43
|
+
If you would like color output, you can `require 'minitest/pride'` in
|
44
|
+
the test file, or note the alternative instruction, below, for running
|
45
|
+
the test file.
|
46
|
+
|
47
|
+
In order to run the test, you can run the test file from the exercise
|
48
|
+
directory. For example, if the test suite is called
|
49
|
+
`hello_world_test.rb`, you can run the following command:
|
50
|
+
|
51
|
+
ruby hello_world_test.rb
|
52
|
+
|
53
|
+
To include color from the command line:
|
54
|
+
|
55
|
+
ruby -r minitest/pride hello_world_test.rb
|
56
|
+
|
57
|
+
|
58
|
+
## Source
|
59
|
+
|
60
|
+
Wikipedia [https://en.wikipedia.org/wiki/Caesar_cipher](https://en.wikipedia.org/wiki/Caesar_cipher)
|
61
|
+
|
62
|
+
## Submitting Incomplete Solutions
|
63
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trackler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.1.
|
4
|
+
version: 2.2.1.84
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katrina Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -621,6 +621,9 @@ files:
|
|
621
621
|
- tracks/bash/exercises/bob/README.md
|
622
622
|
- tracks/bash/exercises/bob/bob_test.sh
|
623
623
|
- tracks/bash/exercises/bob/example.sh
|
624
|
+
- tracks/bash/exercises/collatz-conjecture/README.md
|
625
|
+
- tracks/bash/exercises/collatz-conjecture/collatz_test.sh
|
626
|
+
- tracks/bash/exercises/collatz-conjecture/example.sh
|
624
627
|
- tracks/bash/exercises/difference-of-squares/README.md
|
625
628
|
- tracks/bash/exercises/difference-of-squares/difference_of_squares_test.sh
|
626
629
|
- tracks/bash/exercises/difference-of-squares/example.sh
|
@@ -631,6 +634,9 @@ files:
|
|
631
634
|
- tracks/bash/exercises/gigasecond/README.md
|
632
635
|
- tracks/bash/exercises/gigasecond/example.sh
|
633
636
|
- tracks/bash/exercises/gigasecond/gigasecond_test.sh
|
637
|
+
- tracks/bash/exercises/grains/README.md
|
638
|
+
- tracks/bash/exercises/grains/example.sh
|
639
|
+
- tracks/bash/exercises/grains/grains_test.sh
|
634
640
|
- tracks/bash/exercises/hamming/README.md
|
635
641
|
- tracks/bash/exercises/hamming/example.sh
|
636
642
|
- tracks/bash/exercises/hamming/hamming_test.sh
|
@@ -641,6 +647,9 @@ files:
|
|
641
647
|
- tracks/bash/exercises/leap/README.md
|
642
648
|
- tracks/bash/exercises/leap/example.sh
|
643
649
|
- tracks/bash/exercises/leap/leap_test.sh
|
650
|
+
- tracks/bash/exercises/luhn/README.md
|
651
|
+
- tracks/bash/exercises/luhn/example.sh
|
652
|
+
- tracks/bash/exercises/luhn/luhn_test.sh
|
644
653
|
- tracks/bash/exercises/nucleotide-count/README.md
|
645
654
|
- tracks/bash/exercises/nucleotide-count/example.sh
|
646
655
|
- tracks/bash/exercises/nucleotide-count/nucleotide_count_test.sh
|
@@ -1715,6 +1724,11 @@ files:
|
|
1715
1724
|
- tracks/clojure/exercises/trinary/project.clj
|
1716
1725
|
- tracks/clojure/exercises/trinary/src/example.clj
|
1717
1726
|
- tracks/clojure/exercises/trinary/test/trinary_test.clj
|
1727
|
+
- tracks/clojure/exercises/two-fer/README.md
|
1728
|
+
- tracks/clojure/exercises/two-fer/project.clj
|
1729
|
+
- tracks/clojure/exercises/two-fer/src/example.clj
|
1730
|
+
- tracks/clojure/exercises/two-fer/src/two_fer.clj
|
1731
|
+
- tracks/clojure/exercises/two-fer/test/two_fer_test.clj
|
1718
1732
|
- tracks/clojure/exercises/word-count/README.md
|
1719
1733
|
- tracks/clojure/exercises/word-count/project.clj
|
1720
1734
|
- tracks/clojure/exercises/word-count/src/example.clj
|
@@ -11085,6 +11099,10 @@ files:
|
|
11085
11099
|
- tracks/python/exercises/pangram/example.py
|
11086
11100
|
- tracks/python/exercises/pangram/pangram.py
|
11087
11101
|
- tracks/python/exercises/pangram/pangram_test.py
|
11102
|
+
- tracks/python/exercises/parallel-letter-frequency/README.md
|
11103
|
+
- tracks/python/exercises/parallel-letter-frequency/example.py
|
11104
|
+
- tracks/python/exercises/parallel-letter-frequency/parallel_letter_frequency.py
|
11105
|
+
- tracks/python/exercises/parallel-letter-frequency/parallel_letter_frequency_test.py
|
11088
11106
|
- tracks/python/exercises/pascals-triangle/README.md
|
11089
11107
|
- tracks/python/exercises/pascals-triangle/example.py
|
11090
11108
|
- tracks/python/exercises/pascals-triangle/pascals_triangle.py
|
@@ -11882,6 +11900,7 @@ files:
|
|
11882
11900
|
- tracks/ruby/exercises/rotational-cipher/.meta/.version
|
11883
11901
|
- tracks/ruby/exercises/rotational-cipher/.meta/generator/rotational_cipher_case.rb
|
11884
11902
|
- tracks/ruby/exercises/rotational-cipher/.meta/solutions/rotational_cipher.rb
|
11903
|
+
- tracks/ruby/exercises/rotational-cipher/README.md
|
11885
11904
|
- tracks/ruby/exercises/rotational-cipher/rotational_cipher_test.rb
|
11886
11905
|
- tracks/ruby/exercises/run-length-encoding/.meta/.version
|
11887
11906
|
- tracks/ruby/exercises/run-length-encoding/.meta/generator/run_length_encoding_case.rb
|