trackler 2.0.6.8 → 2.0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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