trackler 2.2.1.83 → 2.2.1.84
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/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
|