trackler 2.0.8.24 → 2.0.8.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/c/config.json +9 -0
  4. data/tracks/c/exercises/nucleotide-count/makefile +15 -0
  5. data/tracks/c/exercises/nucleotide-count/src/example.c +43 -0
  6. data/tracks/c/exercises/nucleotide-count/src/example.h +6 -0
  7. data/tracks/c/exercises/nucleotide-count/test/test_nucleotide_count.c +58 -0
  8. data/tracks/c/exercises/nucleotide-count/test/vendor/unity.c +1300 -0
  9. data/tracks/c/exercises/nucleotide-count/test/vendor/unity.h +274 -0
  10. data/tracks/c/exercises/nucleotide-count/test/vendor/unity_internals.h +701 -0
  11. data/tracks/ceylon/README.md +2 -2
  12. data/tracks/csharp/.gitattributes +11 -0
  13. data/tracks/csharp/appveyor.yml +1 -4
  14. data/tracks/csharp/exercises/acronym/AcronymTest.cs +1 -1
  15. data/tracks/csharp/exercises/atbash-cipher/AtbashCipher.cs +8 -3
  16. data/tracks/csharp/exercises/atbash-cipher/AtbashCipherTest.cs +76 -0
  17. data/tracks/csharp/exercises/atbash-cipher/Example.cs +22 -23
  18. data/tracks/csharp/exercises/isogram/Example.cs +2 -2
  19. data/tracks/csharp/exercises/isogram/IsogramTest.cs +47 -15
  20. data/tracks/csharp/exercises/nth-prime/Example.cs +4 -1
  21. data/tracks/csharp/exercises/nth-prime/NthPrime.cs +1 -1
  22. data/tracks/csharp/exercises/nth-prime/NthPrimeTest.cs +29 -15
  23. data/tracks/csharp/exercises/perfect-numbers/Example.cs +14 -16
  24. data/tracks/csharp/exercises/perfect-numbers/PerfectNumbers.cs +2 -2
  25. data/tracks/csharp/exercises/perfect-numbers/PerfectNumbersTest.cs +78 -26
  26. data/tracks/csharp/exercises/pig-latin/PigLatinTest.cs +69 -24
  27. data/tracks/csharp/exercises/raindrops/Example.cs +1 -1
  28. data/tracks/csharp/exercises/raindrops/RaindropsTest.cs +93 -31
  29. data/tracks/csharp/exercises/roman-numerals/HINTS.md +2 -0
  30. data/tracks/csharp/exercises/roman-numerals/RomanNumeralsTest.cs +106 -23
  31. data/tracks/csharp/exercises/word-search/HINTS.md +6 -0
  32. data/tracks/csharp/generators/{TestClass.cs → Classes/TestClass.cs} +2 -1
  33. data/tracks/csharp/generators/{TestClassNameTransformer.cs → Classes/TestClassNameTransformer.cs} +1 -1
  34. data/tracks/csharp/generators/{TestClassRenderer.cs → Classes/TestClassRenderer.cs} +2 -1
  35. data/tracks/csharp/generators/Classes/TestedClassNameTransformer.cs +9 -0
  36. data/tracks/csharp/generators/{CanonicalData.cs → Data/CanonicalData.cs} +1 -1
  37. data/tracks/csharp/generators/{CanonicalDataCase.cs → Data/CanonicalDataCase.cs} +3 -3
  38. data/tracks/csharp/generators/{CanonicalDataCaseJsonConverter.cs → Data/CanonicalDataCaseJsonConverter.cs} +1 -1
  39. data/tracks/csharp/generators/{CanonicalDataCasesJsonConverter.cs → Data/CanonicalDataCasesJsonConverter.cs} +2 -2
  40. data/tracks/csharp/generators/{CanonicalDataParser.cs → Data/CanonicalDataParser.cs} +5 -5
  41. data/tracks/csharp/generators/{ExerciseCollection.cs → Data/ExerciseCollection.cs} +3 -3
  42. data/tracks/csharp/generators/Exercises/AcronymExercise.cs +20 -0
  43. data/tracks/csharp/generators/Exercises/AtbashCipherExercise.cs +20 -0
  44. data/tracks/csharp/generators/Exercises/BooleanExercise.cs +14 -0
  45. data/tracks/csharp/generators/Exercises/EqualityExercise.cs +14 -0
  46. data/tracks/csharp/generators/Exercises/Exercise.cs +59 -4
  47. data/tracks/csharp/generators/Exercises/IsogramExercise.cs +9 -0
  48. data/tracks/csharp/generators/Exercises/LeapExercise.cs +1 -4
  49. data/tracks/csharp/generators/Exercises/NthPrimeExercise.cs +25 -0
  50. data/tracks/csharp/generators/Exercises/PerfectNumbersExercise.cs +29 -0
  51. data/tracks/csharp/generators/Exercises/PigLatinExercise.cs +9 -0
  52. data/tracks/csharp/generators/Exercises/RaindropsExercise.cs +20 -0
  53. data/tracks/csharp/generators/Exercises/RomanNumeralsExercise.cs +30 -0
  54. data/tracks/csharp/generators/Helpers/StringExtensions.cs +8 -0
  55. data/tracks/csharp/generators/{To.cs → Helpers/To.cs} +4 -1
  56. data/tracks/csharp/generators/Methods/BooleanTestMethodGenerator.cs +32 -0
  57. data/tracks/csharp/generators/Methods/EqualityTestMethodGenerator.cs +25 -0
  58. data/tracks/csharp/generators/Methods/ExceptionTestMethodGenerator.cs +30 -0
  59. data/tracks/csharp/generators/{TestMethod.cs → Methods/TestMethod.cs} +6 -3
  60. data/tracks/csharp/generators/Methods/TestMethodData.cs +12 -0
  61. data/tracks/csharp/generators/Methods/TestMethodGenerator.cs +64 -0
  62. data/tracks/csharp/generators/Methods/TestMethodNameTransformer.cs +23 -0
  63. data/tracks/csharp/generators/Methods/TestMethodOptions.cs +13 -0
  64. data/tracks/csharp/generators/{TestMethodRenderer.cs → Methods/TestMethodRenderer.cs} +1 -1
  65. data/tracks/csharp/generators/{TestedMethodNameTransformer.cs → Methods/TestedMethodNameTransformer.cs} +1 -1
  66. data/tracks/csharp/generators/Methods/TestedMethodType.cs +9 -0
  67. data/tracks/csharp/generators/Program.cs +2 -0
  68. data/tracks/elixir/config.json +7 -0
  69. data/tracks/elixir/exercises/diffie-hellman/HINTS.md +10 -0
  70. data/tracks/elixir/exercises/diffie-hellman/diffie_hellman.exs +61 -0
  71. data/tracks/elixir/exercises/diffie-hellman/diffie_hellman_test.exs +99 -0
  72. data/tracks/elixir/exercises/diffie-hellman/example.exs +64 -0
  73. data/tracks/haskell/exercises/pov/src/POV.hs +2 -2
  74. data/tracks/haskell/exercises/pythagorean-triplet/src/Triplet.hs +6 -3
  75. data/tracks/haskell/exercises/queen-attack/src/Queens.hs +1 -1
  76. data/tracks/haskell/exercises/raindrops/src/Raindrops.hs +2 -1
  77. data/tracks/haskell/exercises/robot-name/src/Robot.hs +2 -2
  78. data/tracks/haskell/exercises/robot-simulator/src/Robot.hs +6 -6
  79. data/tracks/haskell/exercises/roman-numerals/src/Roman.hs +2 -1
  80. data/tracks/haskell/exercises/run-length-encoding/src/RunLength.hs +2 -2
  81. data/tracks/haskell/exercises/saddle-points/src/Matrix.hs +2 -1
  82. data/tracks/haskell/exercises/say/src/Say.hs +2 -1
  83. data/tracks/haskell/exercises/scrabble-score/src/Scrabble.hs +4 -2
  84. data/tracks/haskell/exercises/secret-handshake/src/SecretHandshake.hs +1 -1
  85. data/tracks/haskell/exercises/sgf-parsing/src/Sgf.hs +1 -1
  86. data/tracks/java/exercises/acronym/src/example/java/Acronym.java +11 -1
  87. data/tracks/java/exercises/acronym/src/test/java/AcronymTest.java +8 -9
  88. data/tracks/java/exercises/grade-school/src/test/java/SchoolTest.java +8 -2
  89. data/tracks/java/exercises/luhn/src/test/java/LuhnValidatorTest.java +20 -13
  90. data/tracks/java/exercises/robot-name/src/test/java/RobotTest.java +6 -1
  91. data/tracks/javascript/README.md +1 -1
  92. data/tracks/javascript/docs/TESTS.md +9 -1
  93. data/tracks/kotlin/exercises/luhn/src/example/kotlin/Luhn.kt +18 -26
  94. data/tracks/kotlin/exercises/luhn/src/test/kotlin/LuhnTest.kt +40 -38
  95. data/tracks/php/README.md +1 -1
  96. data/tracks/php/config.json +5 -0
  97. data/tracks/php/exercises/perfect-numbers/example.php +23 -0
  98. data/tracks/php/exercises/perfect-numbers/perfect-numbers_test.php +99 -0
  99. data/tracks/purescript/.travis.yml +1 -0
  100. data/tracks/purescript/bin/test.sh +33 -8
  101. data/tracks/purescript/config.json +7 -0
  102. data/tracks/purescript/exercises/meetup/bower.json +17 -0
  103. data/tracks/purescript/exercises/meetup/examples/src/Meetup.purs +37 -0
  104. data/tracks/purescript/exercises/meetup/src/Meetup.purs +11 -0
  105. data/tracks/purescript/exercises/meetup/test/Main.purs +395 -0
  106. data/tracks/python/README.md +7 -6
  107. data/tracks/python/docs/TOOLS.md +3 -3
  108. data/tracks/python/exercises/bracket-push/bracket_push_test.py +32 -15
  109. data/tracks/python/exercises/hamming/hamming_test.py +2 -0
  110. data/tracks/python/exercises/luhn/luhn_test.py +2 -0
  111. data/tracks/python/test/check-exercises.py +7 -1
  112. metadata +56 -20
  113. data/tracks/csharp/exercises/atbash-cipher/AtbashTest.cs +0 -17
  114. data/tracks/csharp/generators/BooleanTestMethod.cs +0 -36
  115. data/tracks/csharp/generators/TestMethodNameTransformer.cs +0 -11
  116. data/tracks/csharp/generators/TestedClassNameTransformer.cs +0 -11
  117. data/tracks/java/exercises/allergies/src/main/java/.keep +0 -0
@@ -0,0 +1,99 @@
1
+ if !System.get_env("EXERCISM_TEST_EXAMPLES") do
2
+ Code.load_file("diffie_hellman.exs", __DIR__)
3
+ end
4
+
5
+ ExUnit.start
6
+ ExUnit.configure exclude: :pending, trace: true
7
+
8
+ defmodule DiffieHellmanTest do
9
+ use ExUnit.Case
10
+
11
+ #@tag :pending
12
+ test "private key should be between 1 and P-1, inclusive" do
13
+ prime_p = 23
14
+
15
+ assert DiffieHellman.generate_private_key(prime_p) in Range.new(1, prime_p-1)
16
+ end
17
+
18
+ @tag :pending
19
+ test "private key generator should support very large primes" do
20
+ prime_p = 120227323036150778550155526710966921740030662694578947298423549235265759593711587341037426347114541533006628856300552706996143592240453345642869233562886752930249953227657883929905072620233073626594386072962776144691433658814261874113232461749035425712805067202910389407991986070558964461330091797026762932543
21
+
22
+ assert DiffieHellman.generate_private_key(prime_p) in Range.new(1, prime_p-1)
23
+ end
24
+
25
+ @tag :pending
26
+ test "private keys should be random" do
27
+ prime_p = 23
28
+
29
+ # Due to the nature of random generators, there's a small chance it could generate
30
+ # the same numbers over an over, so this may fail, but the RNG should be good enough
31
+ # that 100 generated keys between 1 and 22 ought to be at least half unique.
32
+
33
+ unique_key_count = Stream.repeatedly(fn -> DiffieHellman.generate_private_key(prime_p) end)
34
+ |> Enum.take(100)
35
+ |> Enum.uniq
36
+ |> length
37
+ min_expected_unique_keys = div(prime_p, 2)
38
+
39
+ assert unique_key_count > min_expected_unique_keys
40
+ end
41
+
42
+ @tag :pending
43
+ test "public key correctly calculated from two primes and private key" do
44
+ prime_p = 23
45
+ prime_g = 5
46
+ private_key = 6
47
+ expected_public_key = 8
48
+
49
+ assert DiffieHellman.generate_public_key(prime_p, prime_g, private_key) == expected_public_key
50
+ end
51
+
52
+ @tag :pending
53
+ test "public key generator should support very large primes" do
54
+ prime_p = 120227323036150778550155526710966921740030662694578947298423549235265759593711587341037426347114541533006628856300552706996143592240453345642869233562886752930249953227657883929905072620233073626594386072962776144691433658814261874113232461749035425712805067202910389407991986070558964461330091797026762932543
55
+ prime_g = 75205441154357919442925546169208711235485855904969178206313309299205868312399046149367516336607966149689640419216591714331722664409474612463910928128055994157922930443733535659848264364106037925315974095321112757711756912144137705613776063541350548911512715512539186192176020596861210448363099541947258202188
56
+ private_key = 8675309
57
+ expected_public_key = 81945102766205597052444239927191366879878802281637258134656723311532689587789695879960502348293388789700383121890410484395608064685866057972603193444399431765316092443741213175747052166212523610645396217140238838864033970876203333493173215068467082830013531737232331628864212666452277691016389511356912249174
58
+
59
+ assert DiffieHellman.generate_public_key(prime_p, prime_g, private_key) == expected_public_key
60
+ end
61
+
62
+ @tag :pending
63
+ test "shared secret key correctly calculated from initial prime, Bob's public key, and Alice's private key" do
64
+ prime_p = 23
65
+ bob_public_key = 19
66
+ alice_private_key = 6
67
+ expected_shared_secret = 2
68
+
69
+ assert DiffieHellman.generate_shared_secret(prime_p, bob_public_key, alice_private_key) == expected_shared_secret
70
+ end
71
+
72
+ @tag :pending
73
+ test "shared secret correctly calculated when using large primes" do
74
+ prime_p = 120227323036150778550155526710966921740030662694578947298423549235265759593711587341037426347114541533006628856300552706996143592240453345642869233562886752930249953227657883929905072620233073626594386072962776144691433658814261874113232461749035425712805067202910389407991986070558964461330091797026762932543
75
+ bob_public_key = 75205441154357919442925546169208711235485855904969178206313309299205868312399046149367516336607966149689640419216591714331722664409474612463910928128055994157922930443733535659848264364106037925315974095321112757711756912144137705613776063541350548911512715512539186192176020596861210448363099541947258202188
76
+ alice_private_key = 2483479393625932939911081304356888505153797135447327501792696199190469015215177630758617902200417377685436170904594686456961202706692908603181062371925882
77
+ expected_shared_secret = 70900735223964890815905879227737819348808518698920446491346508980461201746567735331455825644429877946556431095820785835497384849778344216981228226252639932672153547963980483673419756271345828771971984887453014488572245819864454136618980914729839523581263886740821363010486083940557620831348661126601106717071
78
+
79
+ assert DiffieHellman.generate_shared_secret(prime_p, bob_public_key, alice_private_key) == expected_shared_secret
80
+ end
81
+
82
+ @tag :pending
83
+ test "exchanging public keys between Alice and Bob should calculate the same shared secret" do
84
+ prime_p = 23
85
+ prime_g = 5
86
+
87
+ alice_private_key = DiffieHellman.generate_private_key(prime_p)
88
+ bob_private_key = DiffieHellman.generate_private_key(prime_p)
89
+
90
+ alice_public_key = DiffieHellman.generate_public_key(prime_p, prime_g, alice_private_key)
91
+ bob_public_key = DiffieHellman.generate_public_key(prime_p, prime_g, bob_private_key)
92
+
93
+ alice_shared_secret = DiffieHellman.generate_shared_secret(prime_p, bob_public_key, alice_private_key)
94
+ bob_shared_secret = DiffieHellman.generate_shared_secret(prime_p, alice_public_key, bob_private_key)
95
+
96
+ assert alice_shared_secret == bob_shared_secret
97
+ end
98
+ end
99
+
@@ -0,0 +1,64 @@
1
+ defmodule DiffieHellman do
2
+ @moduledoc """
3
+ Diffie-Hellman is a method of securely exchanging keys in a public-key
4
+ cryptosystem. Two users, Alice and Bob, want to share a secret between
5
+ themselves, while ensuring nobody else can read it.
6
+
7
+ Step 0: Alice and Bob agree on two prime numbers, P and G. An attacker, Eve,
8
+ can intercept these numbers, but without one of Alice or Bob's private keys,
9
+ we'll see Eve can't do anything useful with them.
10
+
11
+ Step 1: Alice and Bob each generate a private key between 1 and P-1.
12
+ P).
13
+
14
+ Step 2: Using the initial primes P and G, Alice and Bob calculate their
15
+ public keys by raising G to the power of their private key, then calculating
16
+ the modulus of that number by P. ((G**private_key) % P)
17
+
18
+ Step 3: Alice and Bob exchange public keys. Alice and Bob calculate a secret
19
+ shared key by raising the other's public key to the power of their private
20
+ key, then doing a modulus of the result by P. Due to the way modulus math
21
+ works, they should both generate the same shared key.
22
+
23
+ Alice calculates: (bob_public ** alice_private) % P
24
+ Bob calculates: (alice_public ** bob_private) % P
25
+
26
+ As long as their private keys are never lost or transmitted, only they know
27
+ their private keys, so even if Eve has P, G, and both public keys, she can't
28
+ do anything with them.
29
+
30
+ A video example is available at:
31
+ https://www.khanacademy.org/computing/computer-science/cryptography/modern-crypt/v/diffie-hellman-key-exchange-part-2
32
+ """
33
+
34
+ @doc """
35
+ Given a prime integer `prime_p`, return a random integer between 1 and `prime_p` - 1
36
+ """
37
+ @spec generate_private_key(prime_p :: integer) :: integer
38
+ def generate_private_key(prime_p) do
39
+ 1 |> Range.new(prime_p - 1) |> Enum.random
40
+ end
41
+
42
+ @doc """
43
+ Given two prime integers as generators (`prime_p` and `prime_g`), and a private key,
44
+ generate a public key using the mathematical formula:
45
+
46
+ (prime_g ** private_key) % prime_p
47
+ """
48
+ @spec generate_public_key(prime_p :: integer, prime_g :: integer, private_key :: integer) :: integer
49
+ def generate_public_key(prime_p, prime_g, private_key) do
50
+ :crypto.mod_pow(prime_g, private_key, prime_p) |> :binary.decode_unsigned
51
+ end
52
+
53
+ @doc """
54
+ Given a prime integer `prime_p`, user B's public key, and user A's private key,
55
+ generate a shared secret using the mathematical formula:
56
+
57
+ (public_key_b ** private_key_a) % prime_p
58
+ """
59
+ @spec generate_shared_secret(prime_p :: integer, public_key_b :: integer, private_key_a :: integer) :: integer
60
+ def generate_shared_secret(prime_p, public_key_b, private_key_a) do
61
+ :crypto.mod_pow(public_key_b, private_key_a, prime_p) |> :binary.decode_unsigned
62
+ end
63
+ end
64
+
@@ -3,7 +3,7 @@ module POV (fromPOV, tracePathBetween) where
3
3
  import Data.Tree (Tree)
4
4
 
5
5
  fromPOV :: Eq a => a -> Tree a -> Maybe (Tree a)
6
- fromPOV = error "You need to implement this function."
6
+ fromPOV x tree = error "You need to implement this function."
7
7
 
8
8
  tracePathBetween :: Eq a => a -> a -> Tree a -> Maybe [a]
9
- tracePathBetween = error "You need to implement this function."
9
+ tracePathBetween from to tree = error "You need to implement this function."
@@ -1,7 +1,10 @@
1
1
  module Triplet (isPythagorean, mkTriplet, pythagoreanTriplets) where
2
2
 
3
- isPythagorean = error "You need to implement this function."
3
+ isPythagorean :: (Int, Int, Int) -> Bool
4
+ isPythagorean triplet = error "You need to implement this function."
4
5
 
5
- mkTriplet = error "You need to implement this function."
6
+ mkTriplet :: Int -> Int -> Int -> (Int, Int, Int)
7
+ mkTriplet a b c = error "You need to implement this function."
6
8
 
7
- pythagoreanTriplets = error "You need to implement this function."
9
+ pythagoreanTriplets :: Int -> Int -> [(Int, Int, Int)]
10
+ pythagoreanTriplets minFactor maxFactor = error "You need to implement this function."
@@ -4,4 +4,4 @@ boardString :: Maybe (Int, Int) -> Maybe (Int, Int) -> String
4
4
  boardString white black = error "You need to implement this function."
5
5
 
6
6
  canAttack :: (Int, Int) -> (Int, Int) -> Bool
7
- canAttack = error "You need to implement this function."
7
+ canAttack queenA queenB = error "You need to implement this function."
@@ -1,3 +1,4 @@
1
1
  module Raindrops (convert) where
2
2
 
3
- convert = error "You need to implement this function."
3
+ convert :: Int -> String
4
+ convert n = error "You need to implement this function."
@@ -6,7 +6,7 @@ mkRobot :: IO Robot
6
6
  mkRobot = error "You need to implement this function."
7
7
 
8
8
  resetName :: Robot -> IO ()
9
- resetName = error "You need to implement this function."
9
+ resetName robot = error "You need to implement this function."
10
10
 
11
11
  robotName :: Robot -> IO String
12
- robotName = error "You need to implement this function."
12
+ robotName robot = error "You need to implement this function."
@@ -17,19 +17,19 @@ data Bearing = North
17
17
  data Robot = Dummy
18
18
 
19
19
  bearing :: Robot -> Bearing
20
- bearing = error "You need to implement this function."
20
+ bearing robot = error "You need to implement this function."
21
21
 
22
22
  coordinates :: Robot -> (Integer, Integer)
23
- coordinates = error "You need to implement this function."
23
+ coordinates robot = error "You need to implement this function."
24
24
 
25
25
  mkRobot :: Bearing -> (Integer, Integer) -> Robot
26
- mkRobot = error "You need to implement this function."
26
+ mkRobot direction coordinates = error "You need to implement this function."
27
27
 
28
28
  simulate :: Robot -> String -> Robot
29
- simulate = error "You need to implement this function."
29
+ simulate robot instructions = error "You need to implement this function."
30
30
 
31
31
  turnLeft :: Bearing -> Bearing
32
- turnLeft = error "You need to implement this function."
32
+ turnLeft direction = error "You need to implement this function."
33
33
 
34
34
  turnRight :: Bearing -> Bearing
35
- turnRight = error "You need to implement this function."
35
+ turnRight direction = error "You need to implement this function."
@@ -1,3 +1,4 @@
1
1
  module Roman (numerals) where
2
2
 
3
- numerals = error "You need to implement this function."
3
+ numerals :: Integer -> Maybe String
4
+ numerals n = error "You need to implement this function."
@@ -1,7 +1,7 @@
1
1
  module RunLength (decode, encode) where
2
2
 
3
3
  decode :: String -> String
4
- decode = error "You need to implement this function."
4
+ decode encodedText = error "You need to implement this function."
5
5
 
6
6
  encode :: String -> String
7
- encode = error "You need to implement this function."
7
+ encode text = error "You need to implement this function."
@@ -2,4 +2,5 @@ module Matrix (saddlePoints) where
2
2
 
3
3
  import Data.Array (Array)
4
4
 
5
- saddlePoints = error "You need to implement this function."
5
+ saddlePoints :: Array i e -> [i]
6
+ saddlePoints matrix = error "You need to implement this function."
@@ -1,3 +1,4 @@
1
1
  module Say (inEnglish) where
2
2
 
3
- inEnglish = error "You need to implement this function."
3
+ inEnglish :: Integer -> Maybe String
4
+ inEnglish n = error "You need to implement this function."
@@ -1,5 +1,7 @@
1
1
  module Scrabble (scoreLetter, scoreWord) where
2
2
 
3
- scoreLetter = error "You need to implement this function."
3
+ scoreLetter :: Char -> Integer
4
+ scoreLetter letter = error "You need to implement this function."
4
5
 
5
- scoreWord = error "You need to implement this function."
6
+ scoreWord :: String -> Integer
7
+ scoreWord word = error "You need to implement this function."
@@ -1,4 +1,4 @@
1
1
  module SecretHandshake (handshake) where
2
2
 
3
3
  handshake :: Int -> [String]
4
- handshake = error "You need to implement this function."
4
+ handshake n = error "You need to implement this function."
@@ -5,4 +5,4 @@ import Data.Text (Text)
5
5
  import Data.Tree (Tree)
6
6
 
7
7
  parseSgf :: Text -> Maybe (Tree (Map Text [Text]))
8
- parseSgf = error "You need to implement this function."
8
+ parseSgf sgf = error "You need to implement this function."
@@ -2,7 +2,17 @@ import java.util.regex.Matcher;
2
2
  import java.util.regex.Pattern;
3
3
 
4
4
  public class Acronym {
5
- public static String generate(String phrase){
5
+ private final String acronym;
6
+
7
+ public Acronym(String phrase) {
8
+ acronym = generateAcronym(phrase);
9
+ }
10
+
11
+ public String get() {
12
+ return acronym;
13
+ }
14
+
15
+ private String generateAcronym(String phrase){
6
16
  final Pattern BREAK_WORDS = Pattern.compile("[A-Z]+[a-z]*|[a-z]+");
7
17
  final Matcher matcher = BREAK_WORDS.matcher(phrase);
8
18
  final StringBuilder b = new StringBuilder();
@@ -5,12 +5,11 @@ import static org.junit.Assert.assertEquals;
5
5
 
6
6
  public class AcronymTest {
7
7
 
8
-
9
8
  @Test
10
9
  public void fromTitleCasedPhrases() {
11
10
  final String phrase = "Portable Network Graphics";
12
11
  final String expected = "PNG";
13
- assertEquals(expected, Acronym.generate(phrase));
12
+ assertEquals(expected, new Acronym(phrase).get());
14
13
  }
15
14
 
16
15
  @Ignore
@@ -18,7 +17,7 @@ public class AcronymTest {
18
17
  public void fromOtherTitleCasedPhrases() {
19
18
  final String phrase = "Ruby on Rails";
20
19
  final String expected = "ROR";
21
- assertEquals(expected, Acronym.generate(phrase));
20
+ assertEquals(expected, new Acronym(phrase).get());
22
21
  }
23
22
 
24
23
  @Ignore
@@ -26,7 +25,7 @@ public class AcronymTest {
26
25
  public void fromInconsistentlyCasedPhrases() {
27
26
  final String phrase = "HyperText Markup Language";
28
27
  final String expected = "HTML";
29
- assertEquals(expected, Acronym.generate(phrase));
28
+ assertEquals(expected, new Acronym(phrase).get());
30
29
  }
31
30
 
32
31
  @Ignore
@@ -34,7 +33,7 @@ public class AcronymTest {
34
33
  public void fromPhrasesWithPunctuation() {
35
34
  final String phrase = "First In, First Out";
36
35
  final String expected = "FIFO";
37
- assertEquals(expected, Acronym.generate(phrase));
36
+ assertEquals(expected, new Acronym(phrase).get());
38
37
  }
39
38
 
40
39
  @Ignore
@@ -42,7 +41,7 @@ public class AcronymTest {
42
41
  public void fromOtherPhrasesWithPunctuation() {
43
42
  final String phrase = "PHP: Hypertext Preprocessor";
44
43
  final String expected = "PHP";
45
- assertEquals(expected, Acronym.generate(phrase));
44
+ assertEquals(expected, new Acronym(phrase).get());
46
45
  }
47
46
 
48
47
  @Ignore
@@ -50,7 +49,7 @@ public class AcronymTest {
50
49
  public void fromPhrasesWithNonAcronymAllCapsWord() {
51
50
  final String phrase = "GNU Image Manipulation Program";
52
51
  final String expected = "GIMP";
53
- assertEquals(expected, Acronym.generate(phrase));
52
+ assertEquals(expected, new Acronym(phrase).get());
54
53
  }
55
54
 
56
55
  @Ignore
@@ -58,7 +57,7 @@ public class AcronymTest {
58
57
  public void fromPhrasesWithPunctuationAndSentenceCasing() {
59
58
  final String phrase = "Complementary metal-oxide semiconductor";
60
59
  final String expected = "CMOS";
61
- assertEquals(expected, Acronym.generate(phrase));
60
+ assertEquals(expected, new Acronym(phrase).get());
62
61
  }
63
62
 
64
63
  @Ignore
@@ -66,7 +65,7 @@ public class AcronymTest {
66
65
  public void fromPhraseWithSingleLetterWord() {
67
66
  final String phrase = "Cat in a Hat";
68
67
  final String expected = "CIAH";
69
- assertEquals(expected, Acronym.generate(phrase));
68
+ assertEquals(expected, new Acronym(phrase).get());
70
69
  }
71
70
 
72
71
  }
@@ -1,3 +1,4 @@
1
+ import org.junit.Before;
1
2
  import org.junit.Ignore;
2
3
  import org.junit.Test;
3
4
 
@@ -15,7 +16,12 @@ import static org.junit.Assert.assertTrue;
15
16
  import static org.junit.Assert.assertEquals;
16
17
 
17
18
  public class SchoolTest {
18
- private final School school = new School();
19
+ private School school;
20
+
21
+ @Before
22
+ public void setUp() {
23
+ school = new School();
24
+ }
19
25
 
20
26
  @Test
21
27
  public void startsWithNoStudents() {
@@ -120,7 +126,7 @@ public class SchoolTest {
120
126
  // Such as UnsupportedOperationException when an unmodifiableMap is used
121
127
  }
122
128
 
123
- assertThat(school.studentsByGradeAlphabetical().get(grade),
129
+ assertThat(school.studentsByGradeAlphabetical().get(grade),
124
130
  not(hasItem(studentWhichShouldNotBeAdded)));
125
131
  }
126
132
  }
@@ -1,86 +1,93 @@
1
1
  import org.junit.Ignore;
2
+ import org.junit.Before;
2
3
  import org.junit.Test;
3
4
 
4
5
  import static org.junit.Assert.assertFalse;
5
6
  import static org.junit.Assert.assertTrue;
6
7
 
7
8
  public class LuhnValidatorTest {
9
+ private LuhnValidator luhnValidator;
10
+
11
+ @Before
12
+ public void setUp() {
13
+ luhnValidator = new LuhnValidator();
14
+ }
8
15
 
9
16
  @Test
10
17
  public void testThatSingleDigitStringIsNotValid() {
11
- assertFalse(new LuhnValidator().isValid("1"));
18
+ assertFalse(luhnValidator.isValid("1"));
12
19
  }
13
20
 
14
21
  @Ignore
15
22
  @Test
16
23
  public void testThatTheStringConsistingOfASingleZeroIsInvalid() {
17
- assertFalse(new LuhnValidator().isValid("0"));
24
+ assertFalse(luhnValidator.isValid("0"));
18
25
  }
19
26
 
20
27
  @Ignore
21
28
  @Test
22
29
  public void testThatASimpleValidNumberIsIdentifiedAsValid() {
23
- assertTrue(new LuhnValidator().isValid(" 5 9 "));
30
+ assertTrue(luhnValidator.isValid(" 5 9 "));
24
31
  }
25
32
 
26
33
  @Ignore
27
34
  @Test
28
35
  public void testThatAValidCanadianSocialInsuranceNumberIsIdentifiedAsValidV1() {
29
- assertTrue(new LuhnValidator().isValid("046 454 286"));
36
+ assertTrue(luhnValidator.isValid("046 454 286"));
30
37
  }
31
38
 
32
39
  @Ignore
33
40
  @Test
34
41
  public void testThatAValidCanadianSocialInsuranceNumberIsIdentifiedAsValidV2() {
35
- assertTrue(new LuhnValidator().isValid("055 444 285"));
42
+ assertTrue(luhnValidator.isValid("055 444 285"));
36
43
  }
37
44
 
38
45
  @Ignore
39
46
  @Test
40
47
  public void testThatAnInvalidCanadianSocialInsuranceNumberIsIdentifiedAsInvalid() {
41
- assertFalse(new LuhnValidator().isValid("046 454 287"));
48
+ assertFalse(luhnValidator.isValid("046 454 287"));
42
49
  }
43
50
 
44
51
  @Ignore
45
52
  @Test
46
53
  public void testThatAnInvalidCreditCardIsIdentifiedAsInvalid() {
47
- assertFalse(new LuhnValidator().isValid("8273 1232 7352 0569"));
54
+ assertFalse(luhnValidator.isValid("8273 1232 7352 0569"));
48
55
  }
49
56
 
50
57
  @Ignore
51
58
  @Test
52
59
  public void testThatAddingANonDigitCharacterToAValidStringInvalidatesTheString() {
53
- assertFalse(new LuhnValidator().isValid("046a 454 286"));
60
+ assertFalse(luhnValidator.isValid("046a 454 286"));
54
61
  }
55
62
 
56
63
  @Ignore
57
64
  @Test
58
65
  public void testThatStringContainingPunctuationIsInvalid() {
59
- assertFalse(new LuhnValidator().isValid("055-444-285"));
66
+ assertFalse(luhnValidator.isValid("055-444-285"));
60
67
  }
61
68
 
62
69
  @Ignore
63
70
  @Test
64
71
  public void testThatStringContainingSymbolsIsInvalid() {
65
- assertFalse(new LuhnValidator().isValid("055£ 444$ 285"));
72
+ assertFalse(luhnValidator.isValid("055£ 444$ 285"));
66
73
  }
67
74
 
68
75
  @Ignore
69
76
  @Test
70
77
  public void testThatTheStringConsistingOfASpaceAndASingleZeroIsInvalid() {
71
- assertFalse(new LuhnValidator().isValid(" 0"));
78
+ assertFalse(luhnValidator.isValid(" 0"));
72
79
  }
73
80
 
74
81
  @Ignore
75
82
  @Test
76
83
  public void testThatStringContainingMultipleZerosIsValid() {
77
- assertTrue(new LuhnValidator().isValid(" 00000"));
84
+ assertTrue(luhnValidator.isValid(" 00000"));
78
85
  }
79
86
 
80
87
  @Ignore
81
88
  @Test
82
89
  public void testThatDoublingNineIsHandledCorrectly() {
83
- assertTrue(new LuhnValidator().isValid("091"));
90
+ assertTrue(luhnValidator.isValid("091"));
84
91
  }
85
92
 
86
93
  }
@@ -1,5 +1,6 @@
1
1
  import org.junit.Test;
2
2
  import org.junit.Ignore;
3
+ import org.junit.Before;
3
4
 
4
5
  import static org.hamcrest.CoreMatchers.equalTo;
5
6
  import static org.hamcrest.core.Is.is;
@@ -9,8 +10,12 @@ import static org.junit.Assert.assertThat;
9
10
  public class RobotTest {
10
11
 
11
12
  private static final String EXPECTED_ROBOT_NAME_PATTERN = "[A-Z]{2}\\d{3}";
12
- private final Robot robot = new Robot();
13
+ private Robot robot;
13
14
 
15
+ @Before
16
+ public void setUp() {
17
+ robot = new Robot();
18
+ }
14
19
 
15
20
  @Test
16
21
  public void hasName() {
@@ -1,4 +1,4 @@
1
- # xJavaScript [![Build Status](https://travis-ci.org/exercism/xjavascript.png?branch=master)](https://travis-ci.org/exercism/xjavascript)
1
+ # xJavaScript [![Build Status](https://travis-ci.org/exercism/xjavascript.svg?branch=master)](https://travis-ci.org/exercism/xjavascript)
2
2
 
3
3
  Exercism exercises in JavaScript
4
4
 
@@ -1,4 +1,12 @@
1
- After configuring `exercism` command-line client and fetching your first JavaScript exercise (see [command-line interface overview](http://exercism.io/cli)) is time to run some tests. Move to the folder where that exercise's files are located (a path similar to `<EXERCISM_HOME_DIR>/<TRACK_ID>/<EXERCISE>`) and run the tests with the `jasmine-node` command you should have installed on *Installing JavaScript* step:
1
+ After configuring `exercism` command-line client you can fetch the very next exercise
2
+
3
+ exercism fetch javascript
4
+
5
+ or you can fetch a specific exercise, passing the exercise name after the language. For example, to fetch the `bob` exercise:
6
+
7
+ exercism fetch javascript bob
8
+
9
+ Now, it's time to run some tests. Move to the folder where that exercise's files are located (a path similar to `<EXERCISM_HOME_DIR>/<TRACK_ID>/<EXERCISE>`) and run the tests with the `jasmine-node` command you should have installed on the *Installing JavaScript* step:
2
10
 
3
11
  cd ~/exercism/javascript/bob
4
12
  jasmine-node bob_test.spec.js
@@ -1,37 +1,29 @@
1
- data class Luhn(val number: Long) {
1
+ object Luhn {
2
2
 
3
- val checkDigit: Int by lazy { checkDigit(number) }
3
+ fun isValid(candidate: String): Boolean =
4
+ isValidCandidate(candidate) && checksum(number(candidate)) == 0
4
5
 
5
- val addends: List<Int> by lazy {
6
- digits(number).withIndex().reversed()
7
- .map { if (isOdd(it.index)) dbl(it.value) else it.value }
8
- }
6
+ private fun isValidCandidate(candidate: String): Boolean =
7
+ candidate.filter(Char::isDigit).length > 1 &&
8
+ candidate.all { it.isDigit() || Character.isSpaceChar(it) }
9
9
 
10
- val checksum: Int by lazy { addends.sum() }
10
+ private fun number(candidate: String) = candidate.filter(Char::isDigit).toLong()
11
11
 
12
- val isValid: Boolean by lazy { checksum % 10 == 0 }
12
+ private fun checksum(number: Long) = addends(number).sum() % 10
13
13
 
14
- val create: Long by lazy {
15
- val zeroCheckDigitNumber = number * 10
16
- val luhn = Luhn(zeroCheckDigitNumber)
14
+ private fun addends(number: Long): List<Int> = digits(number).withIndex().reversed()
15
+ .map { if (isOdd(it.index)) dbl(it.value) else it.value }
17
16
 
18
- if (luhn.isValid) zeroCheckDigitNumber else zeroCheckDigitNumber + (10 - luhn.checksum % 10)
17
+ private fun digits(n: Long): List<Int> = when (n) {
18
+ 0L -> emptyList()
19
+ else -> listOf((n % 10).toInt()) + digits(n / 10)
19
20
  }
20
21
 
21
- companion object {
22
- private fun checkDigit(n: Long) = (n % 10).toInt()
23
-
24
- private fun digits(n: Long): List<Int> = when (n) {
25
- 0L -> emptyList()
26
- else -> listOf(checkDigit(n)) + digits(n / 10)
27
- }
28
-
29
- private fun dbl(n: Int): Int {
30
- val dbled = n * 2
31
- return if (dbled > 10) dbled - 9 else dbled
32
- }
33
-
34
- private fun isOdd(i: Int) = i % 2 == 1
22
+ private fun dbl(n: Int): Int {
23
+ val dbled = n * 2
24
+ return if (dbled > 9) dbled - 9 else dbled
35
25
  }
36
26
 
27
+ private fun isOdd(i: Int) = i % 2 == 1
28
+
37
29
  }