trackler 2.0.6.8 → 2.0.6.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/luhn/canonical-data.json +32 -68
  3. data/common/exercises/luhn/description.md +79 -52
  4. data/lib/trackler/version.rb +1 -1
  5. data/tracks/csharp/exercises/accumulate/AccumulateTest.cs +9 -0
  6. data/tracks/csharp/exercises/accumulate/Example.cs +1 -1
  7. data/tracks/csharp/exercises/luhn/Example.cs +15 -31
  8. data/tracks/csharp/exercises/luhn/LuhnTest.cs +9 -55
  9. data/tracks/fsharp/exercises/luhn/Example.fs +15 -17
  10. data/tracks/fsharp/exercises/luhn/LuhnTest.fs +8 -38
  11. data/tracks/java/config.json +6 -0
  12. data/tracks/java/exercises/settings.gradle +2 -0
  13. data/tracks/java/exercises/twelve-days/build.gradle +17 -0
  14. data/tracks/java/exercises/twelve-days/src/example/java/TwelveDays.java +46 -0
  15. data/tracks/java/exercises/twelve-days/src/main/java/.keep +0 -0
  16. data/tracks/java/exercises/twelve-days/src/test/java/TwelveDaysTest.java +172 -0
  17. data/tracks/ocaml/tools/test-generator/src/controller.ml +2 -2
  18. data/tracks/ocaml/tools/test-generator/src/parser.ml +12 -12
  19. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +4 -0
  20. data/tracks/ocaml/tools/test-generator/templates/luhn/template.ml +16 -0
  21. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +2 -2
  22. data/tracks/pascal/config.json +1 -1
  23. data/tracks/pascal/exercises/hello-world/uTestHelloWorld.pas +2 -3
  24. data/tracks/scala/config.json +9 -0
  25. data/tracks/scala/exercises/pascals-triangle/build.sbt +2 -2
  26. data/tracks/scala/exercises/pig-latin/build.sbt +2 -2
  27. data/tracks/scala/exercises/pythagorean-triplet/build.sbt +3 -2
  28. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 06eb068eafe08df34df6d6694c3addea1a148d25
4
- data.tar.gz: 40fc285269f963be93d20e6aa3b6e88502f83713
3
+ metadata.gz: b14825c924ae155ef47cfae4208988fc6fe0792a
4
+ data.tar.gz: d95acda90518c0b892a492427df1449ada88ef61
5
5
  SHA512:
6
- metadata.gz: bdc0498d9f33dea2d191d3b728f8f33fc0808f4cfc17413674440ef0a6352a7a6e50389df6c434a2e243b1a25e9e97f3eb5ed7ee74383079c55b9b5692cd7206
7
- data.tar.gz: 720ef4ddced6739a38e22c33ff657e8ca0b14b019d4d7940a587b18b0ed7d22572d7010b83c7c72b43ca1a8b003ab0081a7ae88aa64059a892e2b60e143a5e77
6
+ metadata.gz: 6b246ba31cee380b84c8419cd4cc55ef0e52955888e5f1da274fff1956a71f9f5cb81e6f4625be50dc2d4a82d26650aee8372b2cde6377e3a149c083d681ae0d
7
+ data.tar.gz: 2248d24225e54c4ea418a19cdf51e68140f5993e92d869866a0553023b6623ab83f9a385b1a408910db48a21bf398ea4c76bae8cb3876909020b818deb91d84c
@@ -1,70 +1,34 @@
1
1
  {
2
- "#": [
3
- "The only note about this exercise is to make sure that the methods used",
4
- "to check if a number is valid and to compute its checksum DO NOT modify",
5
- "the value of the internal attributes. ",
6
- "I say this because I've seen for the Python testcases that it needs a last",
7
- "test to call the validation method twice to assure this. ",
8
- "Simply assure that the two methods are const methods (to use a C++ notation)",
9
- "using the tools available in your language. ",
10
- "Here is a pretty universal solution for the validation method: ",
11
- "`return (0 === (this.checksum % 10)) ? true : false;`"
12
- ],
13
- "cases": [
14
- {
15
- "description": "check digit",
16
- "input": 34567,
17
- "expected": 7
18
- },
19
- {
20
- "description": "check digit with input ending in zero",
21
- "input": 91370,
22
- "expected": 0
23
- },
24
- {
25
- "description": "check addends",
26
- "input": 12121,
27
- "expected": [1, 4, 1, 4, 1]
28
- },
29
- {
30
- "description": "check too large addends",
31
- "input": 8631,
32
- "expected": [7, 6, 6, 1]
33
- },
34
- {
35
- "description": "checksum",
36
- "input": 4913,
37
- "expected": 22
38
- },
39
- {
40
- "description": "checksum of larger number",
41
- "input": 201773,
42
- "expected": 21
43
- },
44
- {
45
- "description": "check invalid number",
46
- "input": 738,
47
- "expected": false
48
- },
49
- {
50
- "description": "check valid number",
51
- "input": 8739567,
52
- "expected": true
53
- },
54
- {
55
- "description": "create valid number",
56
- "input": 123,
57
- "expected": 1230
58
- },
59
- {
60
- "description": "create larger valid number",
61
- "input": 873956,
62
- "expected": 8739567
63
- },
64
- {
65
- "description": "create even larger valid number",
66
- "input": 837263756,
67
- "expected": 8372637564
68
- }
69
- ]
2
+ "valid": [
3
+ {
4
+ "description": "single digit strings can not be valid",
5
+ "input": "1",
6
+ "expected": false
7
+ },
8
+ {
9
+ "description": "A single zero is invalid",
10
+ "input": "0",
11
+ "expected": false
12
+ },
13
+ {
14
+ "description": "valid Canadian SIN",
15
+ "input": "046 454 286",
16
+ "expected": true
17
+ },
18
+ {
19
+ "description": "invalid Canadian SIN",
20
+ "input": "046 454 287",
21
+ "expected": false
22
+ },
23
+ {
24
+ "description": "invalid credit card",
25
+ "input": "8273 1232 7352 0569",
26
+ "expected": false
27
+ },
28
+ {
29
+ "description": "strings that contain non-digits are not valid",
30
+ "input": "827a 1232 7352 0569",
31
+ "expected": false
32
+ }
33
+ ]
70
34
  }
@@ -1,53 +1,80 @@
1
- The Luhn formula is a simple checksum formula used to validate a variety
2
- of identification numbers, such as credit card numbers and Canadian
3
- Social Insurance Numbers.
4
-
5
- The formula verifies a number against its included check digit, which is
6
- usually appended to a partial number to generate the full number. This
7
- number must pass the following test:
8
-
9
- - Counting from rightmost digit (which is the check digit) and moving
10
- left, double the value of every second digit.
11
- - For any digits that thus become 10 or more, subtract 9 from the
12
- result.
13
- - 1111 becomes 2121.
14
- - 8763 becomes 7733 (from 2×6=12 → 12-9=3 and 2×8=16 → 16-9=7).
15
- - Add all these digits together.
16
- - 1111 becomes 2121 sums as 2+1+2+1 to give a check digit of 6.
17
- - 8763 becomes 7733, and 7+7+3+3 is 20.
18
-
19
- If the total ends in 0 (put another way, if the total modulus 10 is
20
- congruent to 0), then the number is valid according to the Luhn formula;
21
- else it is not valid. So, 1111 is not valid (as shown above, it comes
22
- out to 6), while 8763 is valid (as shown above, it comes out to 20).
23
-
24
- Write a program that, given a number
25
-
26
- - Can check if it is valid per the Luhn formula. This should treat, for
27
- example, "2323 2005 7766 3554" as valid.
28
- - Can return the checksum, or the remainder from using the Luhn method.
29
- - Can add a check digit to make the number valid per the Luhn formula and
30
- return the original number plus that digit. This should give "2323 2005 7766
31
- 3554" in response to "2323 2005 7766 355".
32
-
33
- ## About Checksums
34
-
35
- A checksum has to do with error-detection. There are a number of different
36
- ways in which a checksum could be calculated.
37
-
38
- When transmitting data, you might also send along a checksum that says how
39
- many bytes of data are being sent. That means that when the data arrives on
40
- the other side, you can count the bytes and compare it to the checksum. If
41
- these are different, then the data has been garbled in transmission.
42
-
43
- In the Luhn problem the final digit acts as a sanity check for all the prior
44
- digits. Running those prior digits through a particular algorithm should give
45
- you that final digit.
46
-
47
- It doesn't actually tell you if it's a real credit card number, only that it's
48
- a plausible one. It's the same thing with the bytes that get transmitted --
49
- you could have the right number of bytes and still have a garbled message. So
50
- checksums are a simple sanity-check, not a real in-depth verification of the
51
- authenticity of some data. It's often a cheap first pass, and can be used to
52
- quickly discard obviously invalid things.
1
+ The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is
2
+ a simple checksum formula used to validate a variety of identification
3
+ numbers, such as credit card numbers and Canadian Social Insurance
4
+ Numbers.
53
5
 
6
+ The task is to write a function that checks if a given string is valid.
7
+
8
+ Validating a Number
9
+ ------
10
+
11
+ As an example, here is a valid (but fictitious) Canadian Social Insurance
12
+ Number.
13
+
14
+ ```
15
+ 046 454 286
16
+ ```
17
+
18
+ The first step of the Luhn algorithm is to double every second digit,
19
+ starting from the right. We will be doubling
20
+
21
+ ```
22
+ _4_ 4_4 _8_
23
+ ```
24
+
25
+ If doubling the number results in a number greater than 9 then subtract 9
26
+ from the product. The results of our doubling:
27
+
28
+ ```
29
+ 086 858 276
30
+ ```
31
+
32
+ Then sum all of the digits
33
+
34
+ ```
35
+ 0+8+6+8+5+8+2+7+6 = 50
36
+ ```
37
+
38
+ If the sum is evenly divisible by 10, then the number is valid. This number is valid!
39
+
40
+ An example of an invalid Canadian SIN where we've changed the final digit
41
+
42
+ ```
43
+ 046 454 287
44
+ ```
45
+
46
+ Double the second digits, starting from the right
47
+
48
+ ```
49
+ 086 858 277
50
+ ```
51
+
52
+ Sum the digits
53
+
54
+ ```
55
+ 0+8+6+8+5+8+2+7+7 = 51
56
+ ```
57
+
58
+ 51 is not evenly divisible by 10, so this number is not valid.
59
+
60
+ ----
61
+
62
+ An example of an invalid credit card account
63
+
64
+ ```
65
+ 8273 1232 7352 0569
66
+ ```
67
+
68
+ Double the second digits, starting from the right
69
+
70
+ ```
71
+ 7253 2262 5312 0539
72
+ ```
73
+
74
+ Sum the digits
75
+
76
+ ```
77
+ 7+2+5+3+2+2+5+2+5+3+1+2+0+5+3+9 = 57
78
+ ```
79
+
80
+ 57 is not evenly divisible by 10, so this number is not valid.
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.6.8"
2
+ VERSION = "2.0.6.9"
3
3
  end
@@ -62,4 +62,13 @@ public class AccumulateTest
62
62
  accumulation.ToList();
63
63
  Assert.That(counter, Is.EqualTo(3));
64
64
  }
65
+
66
+ [Ignore("Remove to run test")]
67
+ [Test]
68
+ public void Accumulate_allows_different_return_type()
69
+ {
70
+ Assert.That(
71
+ new[] { 1, 2, 3 }.Accumulate(x => x.ToString()),
72
+ Is.EqualTo(new[] { "1", "2", "3" }));
73
+ }
65
74
  }
@@ -3,7 +3,7 @@ using System.Collections.Generic;
3
3
 
4
4
  public static class AccumulateExtensions
5
5
  {
6
- public static IEnumerable<T> Accumulate<T>(this IEnumerable<T> collection, Func<T, T> func)
6
+ public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
7
7
  {
8
8
  foreach (var item in collection)
9
9
  yield return func(item);
@@ -1,22 +1,23 @@
1
1
  using System;
2
2
  using System.Linq;
3
3
 
4
- public class Luhn
4
+ public static class Luhn
5
5
  {
6
- private readonly long number;
6
+ public static bool IsValid(string number)
7
+ {
8
+ number = number.Replace(" ", "");
7
9
 
8
- public long CheckDigit { get { return number % 10; } }
9
- public int[] Addends { get; private set; }
10
- public int Checksum { get { return Addends.Sum(); } }
11
- public bool Valid { get { return Checksum % 10 == 0; } }
10
+ if (number.Length < 2 || number.Any(c => c < '0' || c > '9'))
11
+ {
12
+ return false;
13
+ }
12
14
 
13
- public Luhn(long number)
14
- {
15
- this.number = number;
16
- Addends = GenerateAddends();
15
+ var checksum = GenerateChecksum(number);
16
+
17
+ return checksum % 10 == 0;
17
18
  }
18
19
 
19
- private int[] GenerateAddends()
20
+ private static int GenerateChecksum(string number)
20
21
  {
21
22
  var reversedIntArray = SplitToReversedIntArray(number);
22
23
  for (int i = 1; i < reversedIntArray.Length; i++)
@@ -25,12 +26,12 @@ public class Luhn
25
26
  reversedIntArray[i] = ConvertDigitForAddend(reversedIntArray[i]);
26
27
  }
27
28
  Array.Reverse(reversedIntArray);
28
- return reversedIntArray;
29
+ return reversedIntArray.Sum();
29
30
  }
30
31
 
31
- private static int[] SplitToReversedIntArray(long value)
32
+ private static int[] SplitToReversedIntArray(string value)
32
33
  {
33
- return value.ToString().Select(c => int.Parse(c.ToString())).Reverse().ToArray();
34
+ return value.Select(c => int.Parse(c.ToString())).Reverse().ToArray();
34
35
  }
35
36
 
36
37
  private static int ConvertDigitForAddend(int value)
@@ -38,21 +39,4 @@ public class Luhn
38
39
  var doubled = value * 2;
39
40
  return doubled < 10 ? doubled : doubled - 9;
40
41
  }
41
-
42
- public static long Create(long number)
43
- {
44
- var zeroCheckDigitNumber = number * 10;
45
- var luhn = new Luhn(zeroCheckDigitNumber);
46
-
47
- if (luhn.Valid)
48
- return zeroCheckDigitNumber;
49
-
50
- return zeroCheckDigitNumber + CreateCheckDigit(luhn.Checksum);
51
- }
52
-
53
- private static int CreateCheckDigit(int value)
54
- {
55
- var nearestTen = (int)(Math.Ceiling(value / 10.0m) * 10);
56
- return nearestTen - value;
57
- }
58
42
  }
@@ -3,60 +3,14 @@ using NUnit.Framework;
3
3
  [TestFixture]
4
4
  public class LuhnTest
5
5
  {
6
- [Test]
7
- public void Check_digit_is_the_rightmost_digit()
8
- {
9
- Assert.That(new Luhn(34567).CheckDigit, Is.EqualTo(7));
10
- }
11
-
12
- [Ignore("Remove to run test")]
13
- [Test]
14
- public void Addends_doubles_every_other_number_from_the_right()
15
- {
16
- Assert.That(new Luhn(12121).Addends, Is.EqualTo(new[] { 1, 4, 1, 4, 1 }));
17
- }
18
-
19
- [Ignore("Remove to run test")]
20
- [Test]
21
- public void Addends_subtracts_9_when_doubled_number_is_more_than_9()
22
- {
23
- Assert.That(new Luhn(8631).Addends, Is.EqualTo(new[] { 7, 6, 6, 1 }));
24
- }
25
-
26
- [Ignore("Remove to run test")]
27
- [TestCase(4913, ExpectedResult = 22)]
28
- [TestCase(201773, ExpectedResult = 21)]
29
- public int Checksum_adds_addends_together(int number)
30
- {
31
- return new Luhn(number).Checksum;
32
- }
33
-
34
- [Ignore("Remove to run test")]
35
- [TestCase(738, ExpectedResult = false)]
36
- [TestCase(8739567, ExpectedResult = true)]
37
- public bool Number_is_valid_when_checksum_mod_10_is_zero(int number)
38
- {
39
- return new Luhn(number).Valid;
40
- }
41
-
42
- [Ignore("Remove to run test")]
43
- [Test]
44
- public void Luhn_can_create_simple_numbers_with_valid_check_digit()
45
- {
46
- Assert.That(Luhn.Create(123), Is.EqualTo(1230));
47
- }
48
-
49
- [Ignore("Remove to run test")]
50
- [Test]
51
- public void Luhn_can_create_larger_numbers_with_valid_check_digit()
52
- {
53
- Assert.That(Luhn.Create(873956), Is.EqualTo(8739567));
54
- }
55
-
56
- [Ignore("Remove to run test")]
57
- [Test]
58
- public void Luhn_can_create_huge_numbers_with_valid_check_digit()
59
- {
60
- Assert.That(Luhn.Create(837263756), Is.EqualTo(8372637564));
6
+ [TestCase("1", ExpectedResult = false)] // single digit strings can not be valid
7
+ [TestCase("0", ExpectedResult = false, Ignore = "Remove to run test")] // a single zero is invalid
8
+ [TestCase("046 454 286", ExpectedResult = true, Ignore = "Remove to run test")] // valid Canadian SIN
9
+ [TestCase("046 454 287", ExpectedResult = false, Ignore = "Remove to run test")] // invalid Canadian SIN
10
+ [TestCase("8273 1232 7352 0569", ExpectedResult = false, Ignore = "Remove to run test")] // invalid credit card
11
+ [TestCase("827a 1232 7352 0569", ExpectedResult = false, Ignore = "Remove to run test")] // strings that contain non-digits are not valid
12
+ public bool ValidateChecksum(string number)
13
+ {
14
+ return Luhn.IsValid(number);
61
15
  }
62
16
  }
@@ -1,29 +1,27 @@
1
1
  module Luhn
2
-
3
- let digit c = (int)c - (int)'0'
4
- let digits number = number.ToString() |> Seq.map digit
5
2
 
6
- let addend index digit =
3
+ let private digit c = (int)c - (int)'0'
4
+ let private digits number = number.ToString() |> Seq.map digit
5
+
6
+ let private addend index digit =
7
7
  if (index % 2 = 0) then digit else
8
8
  if (digit >= 5) then digit * 2 - 9
9
9
  else digit * 2
10
10
 
11
- let checkDigit (number:int64) = number % 10L
12
-
13
- let addends (number:int64) =
14
- number
15
- |> digits
11
+ let private addends number =
12
+ number
16
13
  |> List.ofSeq
17
14
  |> List.rev
18
15
  |> List.mapi addend
19
16
  |> List.rev
20
17
 
21
- let checksum (number:int64) = (number |> addends |> List.sum) % 10
22
-
23
- let valid (number:int64) = checksum number = 0
24
-
25
- let create (target:int64) =
26
- let targetNumber = target * 10L
18
+ let private checksum number = (number |> digits |> addends |> List.sum) % 10
27
19
 
28
- if valid targetNumber then targetNumber
29
- else targetNumber + 10L - (int64)(checksum targetNumber)
20
+ let valid (number : string) =
21
+ let noSpaces = number.Replace(" ", "")
22
+ match Seq.length noSpaces with
23
+ | 0 | 1 -> false
24
+ | _ ->
25
+ match Seq.forall (fun c -> c >= '0' && c <= '9') noSpaces with
26
+ | false -> false
27
+ | true -> checksum noSpaces = 0
@@ -3,41 +3,11 @@ module LuhnTest
3
3
  open NUnit.Framework
4
4
  open Luhn
5
5
 
6
- [<Test>]
7
- let ``Check digit is the rightmost digit`` () =
8
- Assert.That(checkDigit 34567L, Is.EqualTo 7)
9
-
10
- [<Test>]
11
- [<Ignore("Remove to run test")>]
12
- let ``Addends doubles every other number from the right`` () =
13
- Assert.That(addends 12121L, Is.EqualTo [1; 4; 1; 4; 1])
14
-
15
- [<Test>]
16
- [<Ignore("Remove to run test")>]
17
- let ``Addends subtracts 9 when doubled number is more than 9`` () =
18
- Assert.That(addends 8631L, Is.EqualTo [7; 6; 6; 1])
19
-
20
- [<TestCase(4913, ExpectedResult = 2)>]
21
- [<TestCase(201773, ExpectedResult = 1)>]
22
- let ``Checksum adds addends together`` (number) =
23
- checksum number
24
-
25
- [<TestCase(738, ExpectedResult = false)>]
26
- [<TestCase(8739567, ExpectedResult = true)>]
27
- let ``Number is valid when checksum mod 10 is zero`` (number) =
28
- valid number
29
-
30
- [<Test>]
31
- [<Ignore("Remove to run test")>]
32
- let ``Luhn can create simple numbers with valid check digit`` () =
33
- Assert.That(create 123L, Is.EqualTo(1230))
34
-
35
- [<Test>]
36
- [<Ignore("Remove to run test")>]
37
- let ``Luhn can create larger numbers with valid check digit`` () =
38
- Assert.That(create 873956L, Is.EqualTo(8739567))
39
-
40
- [<Test>]
41
- [<Ignore("Remove to run test")>]
42
- let ``Luhn can create huge numbers with valid check digit`` () =
43
- Assert.That(create 837263756L, Is.EqualTo(8372637564L))
6
+ [<TestCase("1", ExpectedResult = false)>] // single digit strings can not be valid
7
+ [<TestCase("0", ExpectedResult = false, Ignore = "Remove to run test")>] // a single zero is invalid
8
+ [<TestCase("046 454 286", ExpectedResult = true, Ignore = "Remove to run test")>] // valid Canadian SIN
9
+ [<TestCase("046 454 287", ExpectedResult = false, Ignore = "Remove to run test")>] // invalid Canadian SIN
10
+ [<TestCase("8273 1232 7352 0569", ExpectedResult = false, Ignore = "Remove to run test")>] // invalid credit card
11
+ [<TestCase("827a 1232 7352 0569", ExpectedResult = false, Ignore = "Remove to run test")>] // strings that contain non-digits are not valid
12
+ let ``Validate checksum`` number =
13
+ valid number
@@ -54,6 +54,7 @@
54
54
  "custom-set",
55
55
  "wordy",
56
56
  "palindrome-products",
57
+ "twelve-days",
57
58
  "sublist"
58
59
  ],
59
60
  "exercises": [
@@ -307,6 +308,11 @@
307
308
  "difficulty": 1,
308
309
  "topics": []
309
310
  },
311
+ {
312
+ "slug": "twelve-days",
313
+ "difficulty": 1,
314
+ "topics": []
315
+ },
310
316
  {
311
317
  "slug": "sublist",
312
318
  "difficulty": 1,
@@ -52,3 +52,5 @@ include 'triangle'
52
52
  include 'trinary'
53
53
  include 'word-count'
54
54
  include 'wordy'
55
+ include 'twelve-days'
56
+
@@ -0,0 +1,17 @@
1
+ apply plugin: "java"
2
+ apply plugin: "eclipse"
3
+ apply plugin: "idea"
4
+
5
+ repositories {
6
+ mavenCentral()
7
+ }
8
+
9
+ dependencies {
10
+ testCompile "junit:junit:4.12"
11
+ }
12
+ test {
13
+ testLogging {
14
+ exceptionFormat = 'full'
15
+ events = ["passed", "failed", "skipped"]
16
+ }
17
+ }
@@ -0,0 +1,46 @@
1
+ public class TwelveDays {
2
+ private static String[] days = new String[] {"first", "second", "third", "fourth", "fifth", "sixth", "seventh",
3
+ "eighth", "ninth", "tenth", "eleventh", "twelfth"};
4
+ private static String[] gifts = new String[] {
5
+ "a Partridge in a Pear Tree.",
6
+ "two Turtle Doves, ",
7
+ "three French Hens, ",
8
+ "four Calling Birds, ",
9
+ "five Gold Rings, ",
10
+ "six Geese-a-Laying, ",
11
+ "seven Swans-a-Swimming, ",
12
+ "eight Maids-a-Milking, ",
13
+ "nine Ladies Dancing, ",
14
+ "ten Lords-a-Leaping, ",
15
+ "eleven Pipers Piping, ",
16
+ "twelve Drummers Drumming, "
17
+ };
18
+
19
+ public static String verse(int verseNumber) {
20
+ return constructVerse(verseNumber);
21
+ }
22
+
23
+ public static String verses(int verseNumberStart, int verseNumberEnd) {
24
+ StringBuilder stringBuilder = new StringBuilder(constructVerse(verseNumberStart));
25
+ for (int i = verseNumberStart + 1; i <= verseNumberEnd; i++) {
26
+ stringBuilder.append("\n");
27
+ stringBuilder.append(constructVerse(i));
28
+ }
29
+ return stringBuilder.toString();
30
+ }
31
+
32
+ public static String sing() {
33
+ return verses(1, 12);
34
+ }
35
+
36
+ private static String constructVerse(int verseNumber) {
37
+ StringBuilder stringBuilder = new StringBuilder("On the " + days[verseNumber - 1]
38
+ + " day of Christmas my true love gave to me, ");
39
+ for (int i = verseNumber; i > 0; i--) {
40
+ if (verseNumber != 1 && i == 1) stringBuilder.append("and ");
41
+ stringBuilder.append(gifts[i - 1]);
42
+ }
43
+ stringBuilder.append("\n");
44
+ return stringBuilder.toString();
45
+ }
46
+ }
@@ -0,0 +1,172 @@
1
+ import org.junit.Ignore;
2
+ import org.junit.Test;
3
+
4
+ import static org.junit.Assert.assertEquals;
5
+
6
+ public class TwelveDaysTest {
7
+
8
+ @Test
9
+ public void testVerseOne() {
10
+ String expectedVerseOne = "On the first day of Christmas my true love gave to me, " +
11
+ "a Partridge in a Pear Tree.\n";
12
+ assertEquals(expectedVerseOne, TwelveDays.verse(1));
13
+ }
14
+
15
+ @Ignore
16
+ @Test
17
+ public void testVerseTwo() {
18
+ String expectedVerseTwo = "On the second day of Christmas my true love gave to me, two Turtle Doves, " +
19
+ "and a Partridge in a Pear Tree.\n";
20
+ assertEquals(expectedVerseTwo, TwelveDays.verse(2));
21
+ }
22
+
23
+ @Ignore
24
+ @Test
25
+ public void testVerseThree() {
26
+ String expectedVerseThree = "On the third day of Christmas my true love gave to me, three French Hens, " +
27
+ "two Turtle Doves, and a Partridge in a Pear Tree.\n";
28
+ assertEquals(expectedVerseThree, TwelveDays.verse(3));
29
+ }
30
+
31
+ @Ignore
32
+ @Test
33
+ public void testVerseFour() {
34
+ String expectedVerseFour = "On the fourth day of Christmas my true love gave to me, four Calling Birds, " +
35
+ "three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n";
36
+ assertEquals(expectedVerseFour, TwelveDays.verse(4));
37
+ }
38
+
39
+ @Ignore
40
+ @Test
41
+ public void testVerseFive() {
42
+ String expectedVerseFive = "On the fifth day of Christmas my true love gave to me, five Gold Rings, " +
43
+ "four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n";
44
+ assertEquals(expectedVerseFive, TwelveDays.verse(5));
45
+ }
46
+
47
+ @Ignore
48
+ @Test
49
+ public void testVerseSix() {
50
+ String expectedVerseSix = "On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, " +
51
+ "five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, " +
52
+ "and a Partridge in a Pear Tree.\n";
53
+ assertEquals(expectedVerseSix, TwelveDays.verse(6));
54
+ }
55
+
56
+ @Ignore
57
+ @Test
58
+ public void testVerseSeven() {
59
+ String expectedVerseSeven = "On the seventh day of Christmas my true love gave to me, " +
60
+ "seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, " +
61
+ "two Turtle Doves, and a Partridge in a Pear Tree.\n";
62
+ assertEquals(expectedVerseSeven, TwelveDays.verse(7));
63
+ }
64
+
65
+ @Ignore
66
+ @Test
67
+ public void testVerseEight() {
68
+ String expectedVerseEight = "On the eighth day of Christmas my true love gave to me, eight Maids-a-Milking," +
69
+ " seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, " +
70
+ "three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n";
71
+ assertEquals(expectedVerseEight, TwelveDays.verse(8));
72
+ }
73
+
74
+ @Ignore
75
+ @Test
76
+ public void testVerseNine() {
77
+ String expectedVerseNine = "On the ninth day of Christmas my true love gave to me, nine Ladies Dancing, " +
78
+ "eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, " +
79
+ "four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n";
80
+ assertEquals(expectedVerseNine, TwelveDays.verse(9));
81
+ }
82
+
83
+ @Ignore
84
+ @Test
85
+ public void testVerseTen() {
86
+ String expectedVerseTen = "On the tenth day of Christmas my true love gave to me, ten Lords-a-Leaping, " +
87
+ "nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, " +
88
+ "five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, " +
89
+ "and a Partridge in a Pear Tree.\n";
90
+ assertEquals(expectedVerseTen, TwelveDays.verse(10));
91
+ }
92
+
93
+ @Ignore
94
+ @Test
95
+ public void testVerseEleven() {
96
+ String expectedVerseEleven = "On the eleventh day of Christmas my true love gave to me, " +
97
+ "eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, " +
98
+ "seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, " +
99
+ "three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n";
100
+ assertEquals(expectedVerseEleven, TwelveDays.verse(11));
101
+ }
102
+
103
+ @Ignore
104
+ @Test
105
+ public void testVerseTwelve() {
106
+ String expectedVerseTwelve = "On the twelfth day of Christmas my true love gave to me, " +
107
+ "twelve Drummers Drumming, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, " +
108
+ "eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, " +
109
+ "four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n";
110
+ assertEquals(expectedVerseTwelve, TwelveDays.verse(12));
111
+ }
112
+
113
+ @Ignore
114
+ @Test
115
+ public void testMultipleVerses() {
116
+ String expectedVerseOneToThree = "On the first day of Christmas my true love gave to me, " +
117
+ "a Partridge in a Pear Tree.\n\n" +
118
+ "On the second day of Christmas my true love gave to me, two Turtle Doves, " +
119
+ "and a Partridge in a Pear Tree.\n\n" +
120
+ "On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, " +
121
+ "and a Partridge in a Pear Tree.\n";
122
+ assertEquals(expectedVerseOneToThree, TwelveDays.verses(1, 3));
123
+ }
124
+
125
+ @Ignore
126
+ @Test
127
+ public void testSingWholeSong() {
128
+ String expectedSong = "On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.\n" +
129
+ "\n" +
130
+ "On the second day of Christmas my true love gave to me, two Turtle Doves, " +
131
+ "and a Partridge in a Pear Tree.\n" +
132
+ "\n" +
133
+ "On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, " +
134
+ "and a Partridge in a Pear Tree.\n" +
135
+ "\n" +
136
+ "On the fourth day of Christmas my true love gave to me, four Calling Birds, three French Hens, " +
137
+ "two Turtle Doves, and a Partridge in a Pear Tree.\n" +
138
+ "\n" +
139
+ "On the fifth day of Christmas my true love gave to me, five Gold Rings, four Calling Birds, " +
140
+ "three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n" +
141
+ "\n" +
142
+ "On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, " +
143
+ "four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n" +
144
+ "\n" +
145
+ "On the seventh day of Christmas my true love gave to me, seven Swans-a-Swimming, " +
146
+ "six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, " +
147
+ "and a Partridge in a Pear Tree.\n" +
148
+ "\n" +
149
+ "On the eighth day of Christmas my true love gave to me, eight Maids-a-Milking, " +
150
+ "seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, " +
151
+ "three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n" +
152
+ "\n" +
153
+ "On the ninth day of Christmas my true love gave to me, nine Ladies Dancing, eight Maids-a-Milking," +
154
+ " seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, " +
155
+ "three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n" +
156
+ "\n" +
157
+ "On the tenth day of Christmas my true love gave to me, ten Lords-a-Leaping, nine Ladies Dancing," +
158
+ " eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, " +
159
+ "four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n" +
160
+ "\n" +
161
+ "On the eleventh day of Christmas my true love gave to me, eleven Pipers Piping, " +
162
+ "ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, " +
163
+ "six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, " +
164
+ "and a Partridge in a Pear Tree.\n" +
165
+ "\n" +
166
+ "On the twelfth day of Christmas my true love gave to me, twelve Drummers Drumming, " +
167
+ "eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, " +
168
+ "seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, " +
169
+ "three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.\n";
170
+ assertEquals(expectedSong, TwelveDays.sing());
171
+ }
172
+ }
@@ -28,7 +28,7 @@ let generate_code ~(slug: string) ~(template_file: content) ~(canonical_data_fil
28
28
  let fill_in_template = fill_in_template edit_expected edit_parameters in
29
29
  let open Result.Monad_infix in
30
30
  Result.of_option template ("cannot recognize file for " ^ slug ^ " as a template") >>= fun template ->
31
- parse_json_text canonical_data_file (expected_key_name slug)
31
+ parse_json_text canonical_data_file (expected_key_name slug) (cases_name slug)
32
32
  |> Result.map_error ~f:show_error >>= (function
33
33
  | Single cases ->
34
34
  fill_in_template template.template slug cases
@@ -60,7 +60,7 @@ let check_canonical_data canonical_data_folder =
60
60
  let canonical_data_files = List.sort canonical_data_files ~cmp:(fun (s1, _) (s2, _) -> String.compare s1 s2) in
61
61
  let total_count = List.length canonical_data_files in
62
62
  List.iter canonical_data_files ~f:(fun (slug, text) ->
63
- match parse_json_text text (expected_key_name slug) with
63
+ match parse_json_text text (expected_key_name slug) (cases_name slug) with
64
64
  | Error e -> print_endline @@ slug ^ ": " ^ (show_error e)
65
65
  | _ -> ok_count := !ok_count + 1
66
66
  );
@@ -55,45 +55,45 @@ let parse_case (expected_key: string) (s: json): (case, error) Result.t = match
55
55
  | `Assoc assoc -> parse_case_assoc assoc expected_key
56
56
  | _ -> Error ExpectingMapForCase
57
57
 
58
- let parse_cases (text: string): (json, error) Result.t =
59
- match from_string text |> member "cases" with
58
+ let parse_cases (text: string) (cases_key: string): (json, error) Result.t =
59
+ match from_string text |> member cases_key with
60
60
  | `Null -> Error (TestMustHaveKeyCalledCases "xx")
61
61
  | json -> Ok json
62
62
 
63
- let parse_single (text: string) (expected_key: string): (tests, error) Result.t =
63
+ let parse_single (text: string) (expected_key: string) (cases_key: string): (tests, error) Result.t =
64
64
  let open Result.Monad_infix in
65
- parse_cases text >>=
65
+ parse_cases text cases_key >>=
66
66
  to_list_note ExpectingListOfCases >>=
67
67
  (sequence >> (List.map ~f:(parse_case expected_key))) >>= fun ts ->
68
68
  Result.return (Single ts)
69
69
 
70
- let is_suite (json: json) =
70
+ let is_suite (json: json) (cases_key: string) =
71
71
  let keys = List.filter (keys json) ~f:(fun k -> k <> "methods") in
72
72
  let keys = List.sort keys ~cmp:String.compare in
73
- not (List.is_empty keys || keys = ["cases"] || keys = ["#"; "cases"])
73
+ not (List.is_empty keys || keys = [cases_key] || keys = ["#"; cases_key])
74
74
 
75
75
  let merge_result = function
76
76
  | (_, Error x) -> Error x
77
77
  | (n, Ok c) -> Ok {name = n; cases = c}
78
78
 
79
- let parse_cases_from_suite name suite expected_key =
79
+ let parse_cases_from_suite name suite expected_key cases_key =
80
80
  let open Result.Monad_infix in
81
- member_note (TestMustHaveKeyCalledCases name) "cases" suite >>=
81
+ member_note (TestMustHaveKeyCalledCases name) cases_key suite >>=
82
82
  to_list_note ExpectingListOfCases >>= fun tests ->
83
83
  List.map tests ~f:(parse_case expected_key) |> sequence
84
84
 
85
- let parse_json_text (text: string) (expected_key: string): (tests, error) Result.t =
85
+ let parse_json_text (text: string) (expected_key: string) (cases_key: string): (tests, error) Result.t =
86
86
  let open Result.Monad_infix in
87
87
  let json = from_string text in
88
- if is_suite json
88
+ if is_suite json cases_key
89
89
  then
90
90
  to_assoc_note UnrecognizedJson json >>= fun tests ->
91
91
  let tests = List.filter tests ~f:(fun (n, _) -> n <> "#") in
92
- let tests = List.map tests ~f:(fun (name, suite) -> merge_result (name, parse_cases_from_suite name suite expected_key)) in
92
+ let tests = List.map tests ~f:(fun (name, suite) -> merge_result (name, parse_cases_from_suite name suite expected_key cases_key)) in
93
93
  sequence tests >>= fun tests ->
94
94
  Ok (Suite tests)
95
95
  else
96
- parse_single text expected_key
96
+ parse_single text expected_key cases_key
97
97
 
98
98
  let show_error = function
99
99
  | TestMustHaveKeyCalledCases name -> "Test named '" ^ name ^ "' is expected to have an object with a key: 'cases'"
@@ -59,3 +59,7 @@ let edit_parameters ~(slug: string) (parameters: (string * string) list) = match
59
59
  let expected_key_name slug = match slug with
60
60
  | "dominoes" -> "can_chain"
61
61
  | _ -> "expected"
62
+
63
+ let cases_name slug = match slug with
64
+ | "luhn" -> "valid"
65
+ | _ -> "cases"
@@ -0,0 +1,16 @@
1
+ open Core.Std
2
+ open OUnit2
3
+ open Luhn
4
+
5
+ let assert_valid expected input _test_ctxt =
6
+ assert_equal ~printer:Bool.to_string expected (valid input)
7
+
8
+ let tests = [
9
+ (* TEST
10
+ "$description" >::
11
+ assert_valid $expected "$input";
12
+ END TEST *)
13
+ ]
14
+
15
+ let () =
16
+ run_test_tt_main ("luhn tests" >::: tests)
@@ -12,11 +12,11 @@ let ae exp got _test_ctxt = assert_equal exp got ~printer:show_cases
12
12
 
13
13
  let single x = Ok (Single x)
14
14
 
15
- let call_parser json = parse_json_text json "expected"
15
+ let call_parser json = parse_json_text json "expected" "cases"
16
16
 
17
17
  let parser_tests = [
18
18
  "parses empty json as empty list" >::
19
- ae (single []) (call_parser "{\"cases\" : []}");
19
+ ae (single []) (parse_json_text "{\"test-cases\" : []}" "expected" "test-cases");
20
20
 
21
21
  "gives an error with a json map that does not have the key cases in" >::
22
22
  ae (Error (TestMustHaveKeyCalledCases "case"))
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "slug": "pascal",
3
- "language": "Pascal",
3
+ "language": "Object Pascal",
4
4
  "repository": "https://github.com/exercism/xpascal",
5
5
  "active": false,
6
6
  "exercises": [
@@ -9,13 +9,12 @@ type
9
9
  HelloWorldTest = class(TObject)
10
10
  public
11
11
  [Test]
12
- // [Ignore]
13
12
  procedure test_no_name;
14
13
  [Test]
15
- // [Ignore]
14
+ [Ignore('Comment this line to run this test')]
16
15
  procedure test_sample_name;
17
16
  [Test]
18
- // [Ignore]
17
+ [Ignore('Comment this line to run this test')]
19
18
  procedure test_other_sample_name;
20
19
  end;
21
20
 
@@ -349,18 +349,27 @@
349
349
  "slug": "pascals-triangle",
350
350
  "difficulty": 1,
351
351
  "topics": [
352
+ "Control-flow (loops)",
353
+ "Lists",
354
+ "Mathematics"
352
355
  ]
353
356
  },
354
357
  {
355
358
  "slug": "pig-latin",
356
359
  "difficulty": 1,
357
360
  "topics": [
361
+ "Strings",
362
+ "Transforming"
358
363
  ]
359
364
  },
360
365
  {
361
366
  "slug": "pythagorean-triplet",
362
367
  "difficulty": 1,
363
368
  "topics": [
369
+ "Integers",
370
+ "Mathematics",
371
+ "Sequences",
372
+ "Tuples"
364
373
  ]
365
374
  },
366
375
  {
@@ -1,3 +1,3 @@
1
- scalaVersion := "2.11.7"
1
+ scalaVersion := "2.12.1"
2
2
 
3
- libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.5" % "test"
3
+ libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
@@ -1,3 +1,3 @@
1
- scalaVersion := "2.11.7"
1
+ scalaVersion := "2.12.1"
2
2
 
3
- libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.5" % "test"
3
+ libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
@@ -1,3 +1,4 @@
1
- scalaVersion := "2.11.7"
1
+ scalaVersion := "2.12.1"
2
+
3
+ libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
2
4
 
3
- libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.5" % "test"
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.0.6.8
4
+ version: 2.0.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katrina Owen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-10 00:00:00.000000000 Z
11
+ date: 2017-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -3756,6 +3756,10 @@ files:
3756
3756
  - tracks/java/exercises/trinary/src/example/java/Trinary.java
3757
3757
  - tracks/java/exercises/trinary/src/main/java/.keep
3758
3758
  - tracks/java/exercises/trinary/src/test/java/TrinaryTest.java
3759
+ - tracks/java/exercises/twelve-days/build.gradle
3760
+ - tracks/java/exercises/twelve-days/src/example/java/TwelveDays.java
3761
+ - tracks/java/exercises/twelve-days/src/main/java/.keep
3762
+ - tracks/java/exercises/twelve-days/src/test/java/TwelveDaysTest.java
3759
3763
  - tracks/java/exercises/word-count/build.gradle
3760
3764
  - tracks/java/exercises/word-count/src/example/java/WordCount.java
3761
3765
  - tracks/java/exercises/word-count/src/main/java/.keep
@@ -5058,6 +5062,7 @@ files:
5058
5062
  - tracks/ocaml/tools/test-generator/templates/hamming/template.ml
5059
5063
  - tracks/ocaml/tools/test-generator/templates/hello-world/template.ml
5060
5064
  - tracks/ocaml/tools/test-generator/templates/leap/template.ml
5065
+ - tracks/ocaml/tools/test-generator/templates/luhn/template.ml
5061
5066
  - tracks/ocaml/tools/test-generator/templates/minesweeper/template.ml
5062
5067
  - tracks/ocaml/tools/test-generator/templates/raindrops/template.ml
5063
5068
  - tracks/ocaml/tools/test-generator/templates/say/template.ml