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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/simple-cipher/description.md +1 -1
  3. data/common/exercises/triangle/description.md +12 -23
  4. data/lib/trackler/version.rb +1 -1
  5. data/tracks/kotlin/config.json +5 -0
  6. data/tracks/kotlin/exercises/bank-account/build.gradle +32 -0
  7. data/tracks/kotlin/exercises/bank-account/src/example/kotlin/BankAccount.kt +27 -0
  8. data/tracks/kotlin/exercises/bank-account/src/main/kotlin/.keep +0 -0
  9. data/tracks/kotlin/exercises/bank-account/src/test/kotlin/BankAccountTest.kt +73 -0
  10. data/tracks/kotlin/exercises/settings.gradle +1 -0
  11. data/tracks/python/config.json +11 -11
  12. data/tracks/python/exercises/accumulate/accumulate_test.py +16 -14
  13. data/tracks/python/exercises/acronym/acronym_test.py +8 -7
  14. data/tracks/python/exercises/allergies/allergies_test.py +5 -6
  15. data/tracks/python/exercises/atbash-cipher/atbash_cipher_test.py +16 -22
  16. data/tracks/python/exercises/binary-search/binary_search_test.py +12 -10
  17. data/tracks/python/exercises/binary/binary_test.py +7 -8
  18. data/tracks/python/exercises/circular-buffer/circular_buffer_test.py +16 -17
  19. data/tracks/python/exercises/clock/clock_test.py +35 -35
  20. data/tracks/python/exercises/crypto-square/crypto_square_test.py +5 -6
  21. data/tracks/python/exercises/diamond/diamond_test.py +3 -4
  22. data/tracks/python/exercises/etl/etl_test.py +4 -4
  23. data/tracks/python/exercises/gigasecond/gigasecond_test.py +11 -19
  24. data/tracks/python/exercises/grade-school/grade_school_test.py +17 -19
  25. data/tracks/python/exercises/grains/grains_test.py +14 -14
  26. data/tracks/python/exercises/grep/grep_test.py +51 -64
  27. data/tracks/python/exercises/hamming/hamming_test.py +13 -13
  28. data/tracks/python/exercises/hello-world/hello_world_test.py +1 -2
  29. data/tracks/python/exercises/hexadecimal/hexadecimal_test.py +9 -10
  30. data/tracks/python/exercises/house/house_test.py +6 -6
  31. data/tracks/python/exercises/kindergarten-garden/kindergarten_garden_test.py +22 -19
  32. data/tracks/python/exercises/largest-series-product/largest_series_product_test.py +29 -28
  33. data/tracks/python/exercises/linked-list/linked_list_test.py +18 -19
  34. data/tracks/python/exercises/list-ops/list_ops_test.py +44 -39
  35. data/tracks/python/exercises/matrix/matrix_test.py +6 -6
  36. data/tracks/python/exercises/meetup/meetup_test.py +27 -27
  37. data/tracks/python/exercises/minesweeper/example.py +4 -2
  38. data/tracks/python/exercises/minesweeper/minesweeper_test.py +9 -9
  39. data/tracks/python/exercises/nucleotide-count/nucleotide_count_test.py +6 -6
  40. data/tracks/python/exercises/ocr-numbers/ocr_numbers_test.py +63 -49
  41. data/tracks/python/exercises/octal/octal_test.py +7 -7
  42. data/tracks/python/exercises/palindrome-products/palindrome_products_test.py +9 -9
  43. data/tracks/python/exercises/pascals-triangle/pascals_triangle_test.py +7 -7
  44. data/tracks/python/exercises/phone-number/phone_number_test.py +8 -8
  45. data/tracks/python/exercises/pig-latin/pig_latin_test.py +15 -15
  46. data/tracks/python/exercises/point-mutations/point_mutations_test.py +11 -11
  47. data/tracks/python/exercises/poker/poker_test.py +32 -30
  48. data/tracks/python/exercises/prime-factors/prime_factors_test.py +11 -11
  49. data/tracks/python/exercises/proverb/proverb_test.py +16 -9
  50. data/tracks/python/exercises/pythagorean-triplet/pythagorean_triplet_test.py +14 -12
  51. data/tracks/python/exercises/queen-attack/queen_attack_test.py +10 -10
  52. data/tracks/python/exercises/rail-fence-cipher/example.py +2 -1
  53. data/tracks/python/exercises/rail-fence-cipher/rail_fence_cipher_test.py +14 -13
  54. data/tracks/python/exercises/raindrops/raindrops_test.py +16 -16
  55. data/tracks/python/exercises/rectangles/rectangles_test.py +9 -9
  56. data/tracks/python/exercises/rna-transcription/rna_transcription_test.py +8 -8
  57. data/tracks/python/exercises/robot-name/robot_name_test.py +1 -1
  58. data/tracks/python/exercises/robot-simulator/robot_simulator_test.py +18 -19
  59. data/tracks/python/exercises/roman-numerals/roman_numerals_test.py +1 -1
  60. data/tracks/python/exercises/run-length-encoding/run_length_encoding_test.py +15 -16
  61. data/tracks/python/exercises/saddle-points/saddle_points_test.py +4 -4
  62. data/tracks/python/exercises/say/say_test.py +21 -23
  63. data/tracks/python/exercises/scrabble-score/scrabble_score_test.py +9 -9
  64. data/tracks/python/exercises/secret-handshake/secret_handshake_test.py +14 -13
  65. data/tracks/python/exercises/series/example.py +3 -3
  66. data/tracks/python/exercises/series/series_test.py +16 -12
  67. data/tracks/python/exercises/simple-cipher/simple_cipher_test.py +21 -19
  68. data/tracks/python/exercises/space-age/space_age_test.py +16 -16
  69. data/tracks/python/exercises/strain/strain_test.py +9 -8
  70. data/tracks/python/exercises/sublist/sublist_test.py +19 -20
  71. data/tracks/python/exercises/sum-of-multiples/example.py +1 -4
  72. data/tracks/python/exercises/sum-of-multiples/sum_of_multiples_test.py +31 -26
  73. data/tracks/python/exercises/triangle/triangle_test.py +15 -30
  74. data/tracks/python/exercises/trinary/trinary_test.py +7 -7
  75. data/tracks/python/exercises/twelve-days/twelve_days_test.py +13 -14
  76. data/tracks/python/exercises/word-count/example.py +1 -9
  77. data/tracks/python/exercises/word-count/word_count_test.py +0 -15
  78. data/tracks/python/exercises/wordy/wordy_test.py +17 -18
  79. data/tracks/python/exercises/zebra-puzzle/example.py +20 -23
  80. data/tracks/python/exercises/zebra-puzzle/zebra_puzzle_test.py +3 -3
  81. data/tracks/python/test/check-exercises.py +1 -1
  82. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5c894b894e9f0f3d11e47d960d538044a4863cd
4
- data.tar.gz: f0150355935cc408bc6fe6cfb8922fb32bd32267
3
+ metadata.gz: 88860310ccc044c6401cd6578337ddc2b13bcbf1
4
+ data.tar.gz: 2b09ed02e5926183697dafc3d13f8402cf7ee95f
5
5
  SHA512:
6
- metadata.gz: 7c70f073bbd990f0d6dbbe5734a19016bc18435f151a009e7c6cd48dda5b2101d5096cc993a749c167a228d97ed29588478d4ace4d0c63ced64976b9234f88b6
7
- data.tar.gz: af5c762cba7ea0dc69d25c8e8b05c7108754597a869cf7a5c20ea071a4d6a937c98a5be02d46530a0c8298aba7b7fe59c9ef4a7458e86fa126a949bcb4f6acda
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 they key is not composed of numbers or
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
- The program should raise an error if the triangle cannot exist.
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
- ## Hint
7
+ ## Note
4
8
 
5
- The triangle inequality theorem states:
6
- z x + y
7
- where x,y, and z are the lengths of the sides of a triangle. In other words, the
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
- This exercise does not test for degenerate triangles. Feel free to add your own
28
- tests to check for degenerate triangles.
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.
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.8.27"
2
+ VERSION = "2.0.8.28"
3
3
  end
@@ -233,6 +233,11 @@
233
233
  "slug": "triangle",
234
234
  "topics": []
235
235
  },
236
+ {
237
+ "difficulty": 2,
238
+ "slug": "bank-account",
239
+ "topics": ["Concurrency"]
240
+ },
236
241
  {
237
242
  "difficulty": 10,
238
243
  "slug": "react",
@@ -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
+ }
@@ -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
+
@@ -42,3 +42,4 @@ include 'largest-series-product'
42
42
  include 'change'
43
43
  include 'binary-search'
44
44
  include 'triangle'
45
+ include 'bank-account'
@@ -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([], accumulate([], lambda x: x / 2))
8
+ self.assertEqual(accumulate([], lambda x: x / 2), [])
9
9
 
10
10
  def test_pow(self):
11
- self.assertEqual([1, 4, 9, 16, 25], accumulate([1, 2, 3, 4, 5],
12
- lambda x: x * x))
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
- inp = [10, 17, 23]
16
- out = [(1, 3), (2, 3), (3, 2)]
17
- self.assertEqual(out, accumulate(inp, lambda x: divmod(x, 7)))
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(inp, accumulate(accumulate(inp, lambda x: divmod(x, 7)),
22
- lambda x: 7 * x[0] + x[1]))
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
- inp = ['hello', 'world']
26
- out = ['HELLO', 'WORLD']
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 = list('abc')
31
+ inp = ['a', 'b', 'c']
31
32
  out = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3'], ['c1', 'c2', 'c3']]
32
- self.assertEqual(out, accumulate(inp, lambda x: accumulate(list('123'),
33
- lambda y: x + y)))
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('PNG', abbreviate('Portable Network Graphics'))
10
+ self.assertEqual(abbreviate('Portable Network Graphics'), 'PNG')
11
11
 
12
12
  def test_lowercase_words(self):
13
- self.assertEqual('ROR', abbreviate('Ruby on Rails'))
13
+ self.assertEqual(abbreviate('Ruby on Rails'), 'ROR')
14
14
 
15
15
  def test_camelcase(self):
16
- self.assertEqual('HTML', abbreviate('HyperText Markup Language'))
16
+ self.assertEqual(abbreviate('HyperText Markup Language'), 'HTML')
17
17
 
18
18
  def test_punctuation(self):
19
- self.assertEqual('FIFO', abbreviate('First In, First Out'))
19
+ self.assertEqual(abbreviate('First In, First Out'), 'FIFO')
20
20
 
21
21
  def test_all_caps_words(self):
22
- self.assertEqual('PHP', abbreviate('PHP: Hypertext Preprocessor'))
22
+ self.assertEqual(abbreviate('PHP: Hypertext Preprocessor'), 'PHP')
23
23
 
24
24
  def test_non_acronym_all_caps_word(self):
25
- self.assertEqual('GIMP', abbreviate('GNU Image Manipulation Program'))
25
+ self.assertEqual(abbreviate('GNU Image Manipulation Program'), 'GIMP')
26
26
 
27
27
  def test_hyphenated(self):
28
- self.assertEqual('CMOS', abbreviate('Complementary metal-oxide semiconductor'))
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([], Allergies(0).lst)
23
+ self.assertEqual(Allergies(0).lst, [])
25
24
 
26
25
  def test_allergic_to_just_peanuts(self):
27
- self.assertEqual(['peanuts'], Allergies(2).lst)
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(['eggs'], Allergies(257).lst)
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("ml", encode("no"))
10
+ self.assertMultiLineEqual(encode("no"), "ml")
12
11
 
13
12
  def test_encode_yes(self):
14
- self.assertMultiLineEqual("bvh", encode("yes"))
13
+ self.assertMultiLineEqual(encode("yes"), "bvh")
15
14
 
16
15
  def test_encode_OMG(self):
17
- self.assertMultiLineEqual("lnt", encode("OMG"))
16
+ self.assertMultiLineEqual(encode("OMG"), "lnt")
18
17
 
19
18
  def test_encode_O_M_G(self):
20
- self.assertMultiLineEqual("lnt", encode("O M G"))
19
+ self.assertMultiLineEqual(encode("O M G"), "lnt")
21
20
 
22
21
  def test_encode_long_word(self):
23
- self.assertMultiLineEqual("nrmwy oldrm tob", encode("mindblowingly"))
22
+ self.assertMultiLineEqual(encode("mindblowingly"), "nrmwy oldrm tob")
24
23
 
25
24
  def test_encode_numbers(self):
26
- self.assertMultiLineEqual("gvhgr mt123 gvhgr mt",
27
- encode("Testing, 1 2 3, testing."))
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("gifgs rhurx grlm",
31
- encode("Truth is fiction."))
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(ciphertext, encode(plaintext))
35
+ self.assertMultiLineEqual(encode(plaintext), ciphertext)
37
36
 
38
37
  def test_decode_word(self):
39
- self.assertMultiLineEqual("exercism", decode("vcvix rhn"))
38
+ self.assertMultiLineEqual(decode("vcvix rhn"), "exercism")
40
39
 
41
40
  def test_decode_sentence(self):
42
41
  self.assertMultiLineEqual(
43
- "anobstacleisoftenasteppingstone",
44
- decode("zmlyh gzxov rhlug vmzhg vkkrm thglm v")
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(plaintext, decode(ciphertext))
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__':