trackler 2.0.8.27 → 2.0.8.28
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/simple-cipher/description.md +1 -1
- data/common/exercises/triangle/description.md +12 -23
- data/lib/trackler/version.rb +1 -1
- data/tracks/kotlin/config.json +5 -0
- data/tracks/kotlin/exercises/bank-account/build.gradle +32 -0
- data/tracks/kotlin/exercises/bank-account/src/example/kotlin/BankAccount.kt +27 -0
- data/tracks/kotlin/exercises/bank-account/src/main/kotlin/.keep +0 -0
- data/tracks/kotlin/exercises/bank-account/src/test/kotlin/BankAccountTest.kt +73 -0
- data/tracks/kotlin/exercises/settings.gradle +1 -0
- data/tracks/python/config.json +11 -11
- data/tracks/python/exercises/accumulate/accumulate_test.py +16 -14
- data/tracks/python/exercises/acronym/acronym_test.py +8 -7
- data/tracks/python/exercises/allergies/allergies_test.py +5 -6
- data/tracks/python/exercises/atbash-cipher/atbash_cipher_test.py +16 -22
- data/tracks/python/exercises/binary-search/binary_search_test.py +12 -10
- data/tracks/python/exercises/binary/binary_test.py +7 -8
- data/tracks/python/exercises/circular-buffer/circular_buffer_test.py +16 -17
- data/tracks/python/exercises/clock/clock_test.py +35 -35
- data/tracks/python/exercises/crypto-square/crypto_square_test.py +5 -6
- data/tracks/python/exercises/diamond/diamond_test.py +3 -4
- data/tracks/python/exercises/etl/etl_test.py +4 -4
- data/tracks/python/exercises/gigasecond/gigasecond_test.py +11 -19
- data/tracks/python/exercises/grade-school/grade_school_test.py +17 -19
- data/tracks/python/exercises/grains/grains_test.py +14 -14
- data/tracks/python/exercises/grep/grep_test.py +51 -64
- data/tracks/python/exercises/hamming/hamming_test.py +13 -13
- data/tracks/python/exercises/hello-world/hello_world_test.py +1 -2
- data/tracks/python/exercises/hexadecimal/hexadecimal_test.py +9 -10
- data/tracks/python/exercises/house/house_test.py +6 -6
- data/tracks/python/exercises/kindergarten-garden/kindergarten_garden_test.py +22 -19
- data/tracks/python/exercises/largest-series-product/largest_series_product_test.py +29 -28
- data/tracks/python/exercises/linked-list/linked_list_test.py +18 -19
- data/tracks/python/exercises/list-ops/list_ops_test.py +44 -39
- data/tracks/python/exercises/matrix/matrix_test.py +6 -6
- data/tracks/python/exercises/meetup/meetup_test.py +27 -27
- data/tracks/python/exercises/minesweeper/example.py +4 -2
- data/tracks/python/exercises/minesweeper/minesweeper_test.py +9 -9
- data/tracks/python/exercises/nucleotide-count/nucleotide_count_test.py +6 -6
- data/tracks/python/exercises/ocr-numbers/ocr_numbers_test.py +63 -49
- data/tracks/python/exercises/octal/octal_test.py +7 -7
- data/tracks/python/exercises/palindrome-products/palindrome_products_test.py +9 -9
- data/tracks/python/exercises/pascals-triangle/pascals_triangle_test.py +7 -7
- data/tracks/python/exercises/phone-number/phone_number_test.py +8 -8
- data/tracks/python/exercises/pig-latin/pig_latin_test.py +15 -15
- data/tracks/python/exercises/point-mutations/point_mutations_test.py +11 -11
- data/tracks/python/exercises/poker/poker_test.py +32 -30
- data/tracks/python/exercises/prime-factors/prime_factors_test.py +11 -11
- data/tracks/python/exercises/proverb/proverb_test.py +16 -9
- data/tracks/python/exercises/pythagorean-triplet/pythagorean_triplet_test.py +14 -12
- data/tracks/python/exercises/queen-attack/queen_attack_test.py +10 -10
- data/tracks/python/exercises/rail-fence-cipher/example.py +2 -1
- data/tracks/python/exercises/rail-fence-cipher/rail_fence_cipher_test.py +14 -13
- data/tracks/python/exercises/raindrops/raindrops_test.py +16 -16
- data/tracks/python/exercises/rectangles/rectangles_test.py +9 -9
- data/tracks/python/exercises/rna-transcription/rna_transcription_test.py +8 -8
- data/tracks/python/exercises/robot-name/robot_name_test.py +1 -1
- data/tracks/python/exercises/robot-simulator/robot_simulator_test.py +18 -19
- data/tracks/python/exercises/roman-numerals/roman_numerals_test.py +1 -1
- data/tracks/python/exercises/run-length-encoding/run_length_encoding_test.py +15 -16
- data/tracks/python/exercises/saddle-points/saddle_points_test.py +4 -4
- data/tracks/python/exercises/say/say_test.py +21 -23
- data/tracks/python/exercises/scrabble-score/scrabble_score_test.py +9 -9
- data/tracks/python/exercises/secret-handshake/secret_handshake_test.py +14 -13
- data/tracks/python/exercises/series/example.py +3 -3
- data/tracks/python/exercises/series/series_test.py +16 -12
- data/tracks/python/exercises/simple-cipher/simple_cipher_test.py +21 -19
- data/tracks/python/exercises/space-age/space_age_test.py +16 -16
- data/tracks/python/exercises/strain/strain_test.py +9 -8
- data/tracks/python/exercises/sublist/sublist_test.py +19 -20
- data/tracks/python/exercises/sum-of-multiples/example.py +1 -4
- data/tracks/python/exercises/sum-of-multiples/sum_of_multiples_test.py +31 -26
- data/tracks/python/exercises/triangle/triangle_test.py +15 -30
- data/tracks/python/exercises/trinary/trinary_test.py +7 -7
- data/tracks/python/exercises/twelve-days/twelve_days_test.py +13 -14
- data/tracks/python/exercises/word-count/example.py +1 -9
- data/tracks/python/exercises/word-count/word_count_test.py +0 -15
- data/tracks/python/exercises/wordy/wordy_test.py +17 -18
- data/tracks/python/exercises/zebra-puzzle/example.py +20 -23
- data/tracks/python/exercises/zebra-puzzle/zebra_puzzle_test.py +3 -3
- data/tracks/python/test/check-exercises.py +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88860310ccc044c6401cd6578337ddc2b13bcbf1
|
4
|
+
data.tar.gz: 2b09ed02e5926183697dafc3d13f8402cf7ee95f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 778a87faf57b3b14f0260da2c758dbb284d88e6b7d4e0befc81426e6724f6147129c19037398b21d85824efe1ab4d7aaa8d8f071695b8f29fda71f8c0a3d99f4
|
7
|
+
data.tar.gz: 0d89dad5d10d0087386d7704eaf9e80255642b039aa0590ac9d61de0e4aca0674f5aecaa2c3934fab785012bdda26fde53bb11eb94ce9d21d02b4c950f9979c1
|
@@ -54,7 +54,7 @@ would get the same thing as the Caesar Cipher.
|
|
54
54
|
|
55
55
|
The weakest link in any cipher is the human being. Let's make your
|
56
56
|
substitution cipher a little more fault tolerant by providing a source
|
57
|
-
of randomness and ensuring that
|
57
|
+
of randomness and ensuring that the key is not composed of numbers or
|
58
58
|
capital letters.
|
59
59
|
|
60
60
|
If someone doesn't submit a key at all, generate a truly random key of
|
@@ -1,28 +1,17 @@
|
|
1
|
-
|
1
|
+
An _equilateral_ triangle has all three sides the same length.<br/>
|
2
|
+
An _isoceles_ triangle has at least two sides the same length. (It is sometimes
|
3
|
+
specified as having exactly two sides the same length, but for the purposes of
|
4
|
+
this exercise we'll say at least two.)<br/>
|
5
|
+
A _scalene_ triangle has all sides of different lengths.
|
2
6
|
|
3
|
-
##
|
7
|
+
## Note
|
4
8
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
sum of the lengths of any two sides of a triangle always exceeds or is equal to
|
9
|
-
the length of the third side.
|
10
|
-
|
11
|
-
A corollary to the triangle inequality theorem is there are two classes of
|
12
|
-
triangles--degenerate and non-degenerate. If the sum of the lengths of any two
|
13
|
-
sides of a triangle is greater than the length of the third side, that triangle
|
14
|
-
is two dimensional, has area, and belongs to the non-degenerate class. In
|
15
|
-
mathematics, a degenerate case is a limiting case in which an element of a class
|
16
|
-
of objects is qualitatively different from the rest of the class and hence
|
17
|
-
belongs to another, usually simpler, class. The degenerate case of the triangle
|
18
|
-
inequality theorem is when the sum of the lengths of any two sides of a triangle
|
19
|
-
is equal to the length of the third side. A triangle with such qualities is
|
20
|
-
qualitatively different from all the triangles in the non-degenerate class since
|
21
|
-
it is one dimensional, looks like a straight line, and has no area. Such
|
22
|
-
triangles are called degenerate triangles and they belong to the degenerate
|
23
|
-
class.
|
9
|
+
For a shape to be a triangle at all, all sides have to be of length > 0, and
|
10
|
+
the sum of the lengths of any two sides must be greater than or equal to the
|
11
|
+
length of the third side. See [Triangle Inequality](https://en.wikipedia.org/wiki/Triangle_inequality).
|
24
12
|
|
25
13
|
## Dig Deeper
|
26
14
|
|
27
|
-
|
28
|
-
|
15
|
+
The case where the sum of the lengths of two sides _equals_ that of the
|
16
|
+
third is known as a _degenerate_ triangle - it has zero area and looks like
|
17
|
+
a single line. Feel free to add your own code/tests to check for degenerate triangles.
|
data/lib/trackler/version.rb
CHANGED
data/tracks/kotlin/config.json
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
buildscript {
|
2
|
+
ext.kotlin_version = '1.1.1'
|
3
|
+
repositories {
|
4
|
+
mavenCentral()
|
5
|
+
}
|
6
|
+
dependencies {
|
7
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
apply plugin: 'kotlin'
|
12
|
+
|
13
|
+
kotlin.experimental.coroutines = 'enable'
|
14
|
+
|
15
|
+
repositories {
|
16
|
+
mavenCentral()
|
17
|
+
jcenter()
|
18
|
+
}
|
19
|
+
|
20
|
+
dependencies {
|
21
|
+
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
22
|
+
|
23
|
+
testCompile 'junit:junit:4.12'
|
24
|
+
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
|
25
|
+
testCompile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.13'
|
26
|
+
}
|
27
|
+
test {
|
28
|
+
testLogging {
|
29
|
+
exceptionFormat = 'full'
|
30
|
+
events = ["passed", "failed", "skipped"]
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class BankAccount {
|
2
|
+
var balance: Long = 0
|
3
|
+
get() {
|
4
|
+
synchronized(lock) {
|
5
|
+
if (!isOpen) throw IllegalStateException("Account is closed")
|
6
|
+
return field
|
7
|
+
}
|
8
|
+
}
|
9
|
+
private set
|
10
|
+
|
11
|
+
var isOpen = true
|
12
|
+
private set
|
13
|
+
|
14
|
+
fun adjustBalance(amount: Long) {
|
15
|
+
synchronized(lock) {
|
16
|
+
balance += amount
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
fun close() {
|
21
|
+
synchronized(lock) {
|
22
|
+
isOpen = false
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
private val lock = Any()
|
27
|
+
}
|
File without changes
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import org.junit.Ignore
|
2
|
+
import org.junit.Test
|
3
|
+
import java.util.*
|
4
|
+
import kotlin.test.assertEquals
|
5
|
+
import kotlin.test.assertFailsWith
|
6
|
+
import kotlinx.coroutines.experimental.*
|
7
|
+
|
8
|
+
class BankAccountTest {
|
9
|
+
|
10
|
+
@Test
|
11
|
+
fun zeroBalanceWhenOpened() {
|
12
|
+
val account = BankAccount()
|
13
|
+
assertEquals(0, account.balance)
|
14
|
+
}
|
15
|
+
|
16
|
+
@Ignore
|
17
|
+
@Test
|
18
|
+
fun sequentialBalanceAdjustments() {
|
19
|
+
val account = BankAccount()
|
20
|
+
|
21
|
+
account.adjustBalance(1000)
|
22
|
+
assertEquals(1000, account.balance)
|
23
|
+
|
24
|
+
account.adjustBalance(-958)
|
25
|
+
assertEquals(42, account.balance)
|
26
|
+
}
|
27
|
+
|
28
|
+
@Ignore
|
29
|
+
@Test
|
30
|
+
fun closedAccountHasNoBalance() {
|
31
|
+
val account = BankAccount()
|
32
|
+
account.close()
|
33
|
+
|
34
|
+
assertFailsWith(IllegalStateException::class, { account.balance })
|
35
|
+
}
|
36
|
+
|
37
|
+
@Ignore
|
38
|
+
@Test
|
39
|
+
fun closedAccountCannotBeAdjusted() {
|
40
|
+
val account = BankAccount()
|
41
|
+
account.close()
|
42
|
+
|
43
|
+
assertFailsWith(IllegalStateException::class, { account.adjustBalance(1000) })
|
44
|
+
}
|
45
|
+
|
46
|
+
@Ignore
|
47
|
+
@Test
|
48
|
+
fun concurrentBalanceAdjustments() {
|
49
|
+
val threads = 1000
|
50
|
+
val iterations = 500
|
51
|
+
val random = Random()
|
52
|
+
|
53
|
+
val account = BankAccount()
|
54
|
+
|
55
|
+
val jobs = List(threads) {
|
56
|
+
launch(CommonPool) {
|
57
|
+
repeat(iterations) {
|
58
|
+
account.adjustBalance(1)
|
59
|
+
delay(random.nextInt(10).toLong())
|
60
|
+
account.adjustBalance(-1)
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
runBlocking {
|
66
|
+
jobs.forEach { it.join() }
|
67
|
+
}
|
68
|
+
|
69
|
+
assertEquals(0, account.balance)
|
70
|
+
}
|
71
|
+
|
72
|
+
}
|
73
|
+
|
data/tracks/python/config.json
CHANGED
@@ -22,17 +22,6 @@
|
|
22
22
|
"logic"
|
23
23
|
]
|
24
24
|
},
|
25
|
-
{
|
26
|
-
"slug": "clock",
|
27
|
-
"difficulty": 2,
|
28
|
-
"topics": [
|
29
|
-
"classes",
|
30
|
-
"time",
|
31
|
-
"mathematics",
|
32
|
-
"logic",
|
33
|
-
"text formatting"
|
34
|
-
]
|
35
|
-
},
|
36
25
|
{
|
37
26
|
"slug": "isogram",
|
38
27
|
"difficulty": 1,
|
@@ -432,6 +421,17 @@
|
|
432
421
|
"transforming"
|
433
422
|
]
|
434
423
|
},
|
424
|
+
{
|
425
|
+
"slug": "clock",
|
426
|
+
"difficulty": 2,
|
427
|
+
"topics": [
|
428
|
+
"classes",
|
429
|
+
"time",
|
430
|
+
"mathematics",
|
431
|
+
"logic",
|
432
|
+
"text formatting"
|
433
|
+
]
|
434
|
+
},
|
435
435
|
{
|
436
436
|
"slug": "grep",
|
437
437
|
"difficulty": 4,
|
@@ -5,32 +5,34 @@ from accumulate import accumulate
|
|
5
5
|
|
6
6
|
class AccumulateTest(unittest.TestCase):
|
7
7
|
def test_empty_sequence(self):
|
8
|
-
self.assertEqual(
|
8
|
+
self.assertEqual(accumulate([], lambda x: x / 2), [])
|
9
9
|
|
10
10
|
def test_pow(self):
|
11
|
-
self.assertEqual(
|
12
|
-
|
11
|
+
self.assertEqual(
|
12
|
+
accumulate([1, 2, 3, 4, 5], lambda x: x * x), [1, 4, 9, 16, 25])
|
13
13
|
|
14
14
|
def test_divmod(self):
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
self.assertEqual(
|
16
|
+
accumulate([10, 17, 23], lambda x: divmod(x, 7)),
|
17
|
+
[(1, 3), (2, 3), (3, 2)])
|
18
18
|
|
19
19
|
def test_composition(self):
|
20
20
|
inp = [10, 17, 23]
|
21
|
-
self.assertEqual(
|
22
|
-
|
21
|
+
self.assertEqual(
|
22
|
+
accumulate(
|
23
|
+
accumulate(inp, lambda x: divmod(x, 7)),
|
24
|
+
lambda x: 7 * x[0] + x[1]), inp)
|
23
25
|
|
24
26
|
def test_capitalize(self):
|
25
|
-
|
26
|
-
|
27
|
-
self.assertEqual(out, accumulate(inp, str.upper))
|
27
|
+
self.assertEqual(
|
28
|
+
accumulate(['hello', 'world'], str.upper), ['HELLO', 'WORLD'])
|
28
29
|
|
29
30
|
def test_recursive(self):
|
30
|
-
inp =
|
31
|
+
inp = ['a', 'b', 'c']
|
31
32
|
out = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3'], ['c1', 'c2', 'c3']]
|
32
|
-
self.assertEqual(
|
33
|
-
|
33
|
+
self.assertEqual(
|
34
|
+
accumulate(
|
35
|
+
inp, lambda x: accumulate(list('123'), lambda y: x + y)), out)
|
34
36
|
|
35
37
|
|
36
38
|
if __name__ == '__main__':
|
@@ -7,25 +7,26 @@ from acronym import abbreviate
|
|
7
7
|
|
8
8
|
class AcronymTest(unittest.TestCase):
|
9
9
|
def test_basic(self):
|
10
|
-
self.assertEqual(
|
10
|
+
self.assertEqual(abbreviate('Portable Network Graphics'), 'PNG')
|
11
11
|
|
12
12
|
def test_lowercase_words(self):
|
13
|
-
self.assertEqual(
|
13
|
+
self.assertEqual(abbreviate('Ruby on Rails'), 'ROR')
|
14
14
|
|
15
15
|
def test_camelcase(self):
|
16
|
-
self.assertEqual(
|
16
|
+
self.assertEqual(abbreviate('HyperText Markup Language'), 'HTML')
|
17
17
|
|
18
18
|
def test_punctuation(self):
|
19
|
-
self.assertEqual(
|
19
|
+
self.assertEqual(abbreviate('First In, First Out'), 'FIFO')
|
20
20
|
|
21
21
|
def test_all_caps_words(self):
|
22
|
-
self.assertEqual(
|
22
|
+
self.assertEqual(abbreviate('PHP: Hypertext Preprocessor'), 'PHP')
|
23
23
|
|
24
24
|
def test_non_acronym_all_caps_word(self):
|
25
|
-
self.assertEqual(
|
25
|
+
self.assertEqual(abbreviate('GNU Image Manipulation Program'), 'GIMP')
|
26
26
|
|
27
27
|
def test_hyphenated(self):
|
28
|
-
self.assertEqual(
|
28
|
+
self.assertEqual(
|
29
|
+
abbreviate('Complementary metal-oxide semiconductor'), 'CMOS')
|
29
30
|
|
30
31
|
|
31
32
|
if __name__ == '__main__':
|
@@ -4,7 +4,6 @@ from allergies import Allergies
|
|
4
4
|
|
5
5
|
|
6
6
|
class AllergiesTests(unittest.TestCase):
|
7
|
-
|
8
7
|
def test_no_allergies_means_not_allergic(self):
|
9
8
|
allergies = Allergies(0)
|
10
9
|
self.assertFalse(allergies.is_allergic_to('peanuts'))
|
@@ -21,20 +20,20 @@ class AllergiesTests(unittest.TestCase):
|
|
21
20
|
self.assertFalse(allergies.is_allergic_to('strawberries'))
|
22
21
|
|
23
22
|
def test_no_allergies_at_all(self):
|
24
|
-
self.assertEqual(
|
23
|
+
self.assertEqual(Allergies(0).lst, [])
|
25
24
|
|
26
25
|
def test_allergic_to_just_peanuts(self):
|
27
|
-
self.assertEqual(
|
26
|
+
self.assertEqual(Allergies(2).lst, ['peanuts'])
|
28
27
|
|
29
28
|
def test_allergic_to_everything(self):
|
30
29
|
self.assertEqual(
|
30
|
+
sorted(Allergies(255).lst),
|
31
31
|
sorted(('eggs peanuts shellfish strawberries tomatoes '
|
32
|
-
'chocolate pollen cats').split())
|
33
|
-
sorted(Allergies(255).lst))
|
32
|
+
'chocolate pollen cats').split()))
|
34
33
|
|
35
34
|
@unittest.skip('Extra Credit: Passes with a specific type of solution')
|
36
35
|
def test_ignore_non_allergen_score_parts(self):
|
37
|
-
self.assertEqual(
|
36
|
+
self.assertEqual(Allergies(257).lst, ['eggs'])
|
38
37
|
|
39
38
|
|
40
39
|
if __name__ == '__main__':
|
@@ -6,61 +6,55 @@ from atbash_cipher import decode, encode
|
|
6
6
|
# test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
|
7
7
|
|
8
8
|
class AtbashCipherTest(unittest.TestCase):
|
9
|
-
|
10
9
|
def test_encode_no(self):
|
11
|
-
self.assertMultiLineEqual("
|
10
|
+
self.assertMultiLineEqual(encode("no"), "ml")
|
12
11
|
|
13
12
|
def test_encode_yes(self):
|
14
|
-
self.assertMultiLineEqual("
|
13
|
+
self.assertMultiLineEqual(encode("yes"), "bvh")
|
15
14
|
|
16
15
|
def test_encode_OMG(self):
|
17
|
-
self.assertMultiLineEqual("
|
16
|
+
self.assertMultiLineEqual(encode("OMG"), "lnt")
|
18
17
|
|
19
18
|
def test_encode_O_M_G(self):
|
20
|
-
self.assertMultiLineEqual(
|
19
|
+
self.assertMultiLineEqual(encode("O M G"), "lnt")
|
21
20
|
|
22
21
|
def test_encode_long_word(self):
|
23
|
-
self.assertMultiLineEqual("nrmwy oldrm tob"
|
22
|
+
self.assertMultiLineEqual(encode("mindblowingly"), "nrmwy oldrm tob")
|
24
23
|
|
25
24
|
def test_encode_numbers(self):
|
26
|
-
self.assertMultiLineEqual(
|
27
|
-
|
25
|
+
self.assertMultiLineEqual(
|
26
|
+
encode("Testing, 1 2 3, testing."), "gvhgr mt123 gvhgr mt")
|
28
27
|
|
29
28
|
def test_encode_sentence(self):
|
30
|
-
self.assertMultiLineEqual(
|
31
|
-
|
29
|
+
self.assertMultiLineEqual(
|
30
|
+
encode("Truth is fiction."), "gifgs rhurx grlm")
|
32
31
|
|
33
32
|
def test_encode_all_things(self):
|
34
33
|
plaintext = "The quick brown fox jumps over the lazy dog."
|
35
34
|
ciphertext = "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"
|
36
|
-
self.assertMultiLineEqual(
|
35
|
+
self.assertMultiLineEqual(encode(plaintext), ciphertext)
|
37
36
|
|
38
37
|
def test_decode_word(self):
|
39
|
-
self.assertMultiLineEqual(
|
38
|
+
self.assertMultiLineEqual(decode("vcvix rhn"), "exercism")
|
40
39
|
|
41
40
|
def test_decode_sentence(self):
|
42
41
|
self.assertMultiLineEqual(
|
43
|
-
"
|
44
|
-
|
45
|
-
)
|
42
|
+
decode("zmlyh gzxov rhlug vmzhg vkkrm thglm v"),
|
43
|
+
"anobstacleisoftenasteppingstone")
|
46
44
|
|
47
45
|
def test_decode_numbers(self):
|
48
46
|
self.assertMultiLineEqual(
|
49
|
-
"testing123testing"
|
50
|
-
decode("gvhgr mt123 gvhgr mt")
|
51
|
-
)
|
47
|
+
decode("gvhgr mt123 gvhgr mt"), "testing123testing")
|
52
48
|
|
53
49
|
def test_decode_all_the_letters(self):
|
54
50
|
ciphertext = "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"
|
55
51
|
plaintext = "thequickbrownfoxjumpsoverthelazydog"
|
56
|
-
self.assertMultiLineEqual(
|
52
|
+
self.assertMultiLineEqual(decode(ciphertext), plaintext)
|
57
53
|
|
58
54
|
# additional track specific test
|
59
55
|
def test_encode_decode(self):
|
60
56
|
self.assertMultiLineEqual(
|
61
|
-
"testing123testing"
|
62
|
-
decode(encode("Testing, 1 2 3, testing."))
|
63
|
-
)
|
57
|
+
decode(encode("Testing, 1 2 3, testing.")), "testing123testing")
|
64
58
|
|
65
59
|
|
66
60
|
if __name__ == '__main__':
|