trackler 2.0.6.10 → 2.0.6.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/circular-buffer/canonical-data.json +343 -0
- data/common/exercises/luhn/description.md +4 -1
- data/common/exercises/secret-handshake/canonical-data.json +67 -0
- data/common/exercises/secret-handshake/description.md +6 -8
- data/common/exercises/variable-length-quantity/canonical-data.json +147 -0
- data/lib/trackler/version.rb +1 -1
- data/tracks/ceylon/.gitignore +1 -0
- data/tracks/ceylon/.travis.yml +6 -1
- data/tracks/ceylon/README.md +143 -4
- data/tracks/ceylon/bin/test-all-exercises +13 -0
- data/tracks/ceylon/bin/test-exercise +30 -0
- data/tracks/ceylon/config.json +33 -3
- data/tracks/ceylon/{SETUP.md → exercises/TRACK_HINTS.md} +0 -0
- data/tracks/ceylon/exercises/anagram/example/Anagram.ceylon +8 -0
- data/tracks/ceylon/exercises/anagram/source/anagram/Anagram.ceylon +3 -0
- data/tracks/ceylon/exercises/anagram/source/anagram/AnagramTest.ceylon +47 -0
- data/tracks/ceylon/exercises/anagram/source/anagram/module.ceylon +3 -0
- data/tracks/ceylon/exercises/bracket-push/example/Brackets.ceylon +18 -0
- data/tracks/ceylon/exercises/bracket-push/example/module.ceylon +4 -0
- data/tracks/ceylon/exercises/bracket-push/source/bracketpush/Brackets.ceylon +3 -0
- data/tracks/ceylon/exercises/bracket-push/source/bracketpush/BracketsTest.ceylon +37 -0
- data/tracks/ceylon/exercises/bracket-push/source/bracketpush/module.ceylon +3 -0
- data/tracks/ceylon/exercises/leap/example/Leap.ceylon +3 -0
- data/tracks/ceylon/exercises/leap/source/leap/Leap.ceylon +3 -0
- data/tracks/ceylon/exercises/leap/source/leap/LeapTest.ceylon +10 -0
- data/tracks/ceylon/exercises/leap/source/leap/module.ceylon +3 -0
- data/tracks/ceylon/exercises/sieve/example/Sieve.ceylon +24 -0
- data/tracks/ceylon/exercises/sieve/example/module.ceylon +4 -0
- data/tracks/ceylon/exercises/sieve/source/sieve/Sieve.ceylon +3 -0
- data/tracks/ceylon/exercises/sieve/source/sieve/SieveTest.ceylon +23 -0
- data/tracks/ceylon/exercises/sieve/source/sieve/module.ceylon +3 -0
- data/tracks/csharp/.travis.yml +4 -0
- data/tracks/elm/SETUP.md +5 -4
- data/tracks/fsharp/.travis.yml +4 -0
- data/tracks/go/config.json +6 -2
- data/tracks/go/exercises/luhn/example.go +5 -4
- data/tracks/go/exercises/luhn/luhn_test.go +18 -34
- data/tracks/java/exercises/word-count/src/test/java/WordCountTest.java +10 -13
- data/tracks/lua/docs/ABOUT.md +1 -1
- data/tracks/lua/docs/LEARNING.md +1 -0
- data/tracks/lua/docs/RESOURCES.md +6 -1
- data/tracks/lua/exercises/flatten-array/flatten-array_spec.lua +11 -0
- data/tracks/lua/exercises/luhn/example.lua +11 -27
- data/tracks/lua/exercises/luhn/luhn_spec.lua +12 -39
- data/tracks/ocaml/exercises/all-your-base/all_your_base.mli +0 -2
- data/tracks/ocaml/exercises/bracket-push/bracket_push.mli +0 -2
- data/tracks/ocaml/exercises/luhn/example.ml +12 -16
- data/tracks/ocaml/exercises/luhn/luhn.mli +1 -2
- data/tracks/ocaml/exercises/luhn/test.ml +15 -12
- data/tracks/php/config.json +8 -0
- data/tracks/php/exercises/grains/example.php +63 -0
- data/tracks/php/exercises/grains/grains_test.php +82 -0
- data/tracks/pony/config.json +26 -14
- data/tracks/pony/exercises/anagram/example.pony +17 -73
- data/tracks/pony/exercises/anagram/test.pony +6 -13
- data/tracks/pony/exercises/bob/example.pony +24 -24
- data/tracks/pony/exercises/bob/test.pony +16 -34
- data/tracks/pony/exercises/difference-of-squares/example.pony +13 -25
- data/tracks/pony/exercises/difference-of-squares/test.pony +9 -16
- data/tracks/pony/exercises/hamming/example.pony +8 -23
- data/tracks/pony/exercises/hamming/test.pony +16 -30
- data/tracks/pony/exercises/hello-world/example.pony +3 -9
- data/tracks/pony/exercises/hello-world/test.pony +2 -11
- data/tracks/pony/exercises/leap/example.pony +4 -10
- data/tracks/pony/exercises/leap/test.pony +2 -11
- data/tracks/ruby/lib/generator/command_line.rb +5 -6
- data/tracks/ruby/lib/generator/repository.rb +13 -13
- data/tracks/ruby/lib/tasks/exercise_test_tasks.rb +2 -4
- data/tracks/ruby/lib/tasks/exercise_tests_runner.rb +6 -8
- data/tracks/ruby/test/generator/repository_test.rb +26 -34
- data/tracks/rust/README.md +1 -1
- data/tracks/scheme/config.json +5 -0
- data/tracks/scheme/docs/ABOUT.md +7 -0
- data/tracks/scheme/exercises/scrabble-score/example.scm +16 -0
- data/tracks/scheme/exercises/scrabble-score/scrabble-score-test.scm +57 -0
- data/tracks/scheme/exercises/scrabble-score/scrabble-score.scm +2 -0
- metadata +33 -5
- data/tracks/ceylon/exercises/.keep +0 -0
- data/tracks/ceylon/img/.keep +0 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
import ceylon.collection { ArrayList }
|
2
|
+
|
3
|
+
Map<Character, Character> openFor = map {'}' -> '{', ')' -> '(', ']' -> '['};
|
4
|
+
Set<Character> opens = set(openFor.items);
|
5
|
+
|
6
|
+
Boolean balanced(String brackets) {
|
7
|
+
value expectedOpens = ArrayList<Character>();
|
8
|
+
for (c in brackets) {
|
9
|
+
if (opens.contains(c)) {
|
10
|
+
expectedOpens.push(c);
|
11
|
+
} else if (exists open = openFor[c]) {
|
12
|
+
if ((expectedOpens.pop() else '!') != open) {
|
13
|
+
return false;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
return expectedOpens.empty;
|
18
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import ceylon.test { ... }
|
2
|
+
|
3
|
+
{[String, Boolean]*} cases =>
|
4
|
+
{
|
5
|
+
// paired square brackets
|
6
|
+
["[]", true],
|
7
|
+
// empty string
|
8
|
+
["", true],
|
9
|
+
// unpaired brackets
|
10
|
+
["[[", false],
|
11
|
+
// wrong ordered brackets
|
12
|
+
["}{", false],
|
13
|
+
// paired with whitespace
|
14
|
+
["{ }", true],
|
15
|
+
// simple nested brackets
|
16
|
+
["{[]}", true],
|
17
|
+
// several paired brackets
|
18
|
+
["{}[]", true],
|
19
|
+
// paired and nested brackets
|
20
|
+
["([{}({}[])])", true],
|
21
|
+
// unopened closing brackets
|
22
|
+
["{[)][]}", false],
|
23
|
+
// unpaired and nested brackets
|
24
|
+
["([{])", false],
|
25
|
+
// paired and wrong nested brackets
|
26
|
+
["[({]})", false],
|
27
|
+
// math expression
|
28
|
+
["(((185 + 223.85) * 15) - 543)/2", true],
|
29
|
+
// complex latex expression
|
30
|
+
["\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)", true]
|
31
|
+
};
|
32
|
+
|
33
|
+
test
|
34
|
+
parameters(`value cases`)
|
35
|
+
void testBalanced(String brackets, Boolean expected) {
|
36
|
+
assertEquals(balanced(brackets), expected);
|
37
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import ceylon.numeric.float { sqrt }
|
2
|
+
|
3
|
+
{Integer*} primesUpTo(Integer max) {
|
4
|
+
// if max < 4, sqrt(max) < 2, so 2..sqrt(max) gives decreasing values.
|
5
|
+
// Prevent this by just returning the small primes here:
|
6
|
+
if (max < 4) {
|
7
|
+
return {2, 3}.takeWhile((c) => c <= max);
|
8
|
+
}
|
9
|
+
|
10
|
+
value prime = Array.ofSize(max + 1, true);
|
11
|
+
prime[0] = false;
|
12
|
+
prime[1] = false;
|
13
|
+
|
14
|
+
for (i in 2..(sqrt(max.float).integer)) {
|
15
|
+
if (!(prime[i] else false)) {
|
16
|
+
continue;
|
17
|
+
}
|
18
|
+
|
19
|
+
for (multiple in ((i * i)..max).by(i)) {
|
20
|
+
prime[multiple] = false;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
return { for (i -> p in prime.indexed) if (p) i };
|
24
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import ceylon.test { ... }
|
2
|
+
|
3
|
+
{Integer*} cases => {1, 2, 10, 13, 1000};
|
4
|
+
|
5
|
+
[Integer+] primes1000 = [
|
6
|
+
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
7
|
+
73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
|
8
|
+
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
|
9
|
+
239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
|
10
|
+
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
|
11
|
+
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
|
12
|
+
509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
|
13
|
+
613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
|
14
|
+
709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
|
15
|
+
821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
|
16
|
+
919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997
|
17
|
+
];
|
18
|
+
|
19
|
+
test
|
20
|
+
parameters(`value cases`)
|
21
|
+
void testPrimesUpto(Integer max) {
|
22
|
+
assertEquals([*primesUpTo(max)], [*primes1000.takeWhile((x) => x <= max)]);
|
23
|
+
}
|
data/tracks/csharp/.travis.yml
CHANGED
data/tracks/elm/SETUP.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
## Elm Installation
|
2
2
|
|
3
|
-
Refer to the [
|
4
|
-
resources.
|
3
|
+
Refer to the [Exercism help page](http://exercism.io/languages/elm) for Elm
|
4
|
+
installation and learning resources.
|
5
5
|
|
6
6
|
## Writing the Code
|
7
7
|
|
8
|
-
The first time you start an exercise, you'll need to ensure you have the
|
8
|
+
The first time you start an exercise, you'll need to ensure you have the
|
9
|
+
appropriate dependencies installed.
|
9
10
|
|
10
11
|
```bash
|
11
12
|
$ npm install
|
@@ -15,4 +16,4 @@ Execute the tests with:
|
|
15
16
|
|
16
17
|
```bash
|
17
18
|
$ npm test
|
18
|
-
```
|
19
|
+
```
|
data/tracks/fsharp/.travis.yml
CHANGED
data/tracks/go/config.json
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
package luhn
|
2
2
|
|
3
|
+
const testVersion = 1
|
4
|
+
|
3
5
|
func Valid(n string) bool {
|
6
|
+
if len(n) == 1 {
|
7
|
+
return false
|
8
|
+
}
|
4
9
|
d := extract(n)
|
5
10
|
if len(d) == 0 {
|
6
11
|
return false
|
@@ -33,7 +38,3 @@ func check(d []int) int {
|
|
33
38
|
}
|
34
39
|
return s
|
35
40
|
}
|
36
|
-
|
37
|
-
func AddCheck(raw string) string {
|
38
|
-
return raw + string('0'+(10-check(extract(raw))%10)%10)
|
39
|
-
}
|
@@ -2,41 +2,25 @@ package luhn
|
|
2
2
|
|
3
3
|
import "testing"
|
4
4
|
|
5
|
-
|
6
|
-
n string
|
7
|
-
ok bool
|
8
|
-
}{
|
9
|
-
{"738", false},
|
10
|
-
{"8739567", true},
|
11
|
-
{"1111", false},
|
12
|
-
{"8763", true},
|
13
|
-
{" ", false},
|
14
|
-
{"", false},
|
15
|
-
{"2323 2005 7766 3554", true},
|
16
|
-
}
|
5
|
+
const targetTestVersion = 1
|
17
6
|
|
18
|
-
var
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
7
|
+
var testCases = []struct {
|
8
|
+
input string
|
9
|
+
description string
|
10
|
+
ok bool
|
11
|
+
}{
|
12
|
+
{"1", "single digit strings can not be valid", false},
|
13
|
+
{"0", "a single zero is invalid", false},
|
14
|
+
{"046 454 286", "valid Canadian SIN", true},
|
15
|
+
{"046 454 287", "invalid Canadian SIN", false},
|
16
|
+
{"8273 1232 7352 0569", "invalid credit card", false},
|
17
|
+
{"827a 1232 7352 0569", "strings that contain non-digits are not valid", false},
|
26
18
|
}
|
27
19
|
|
28
20
|
func TestValid(t *testing.T) {
|
29
|
-
for _, test := range
|
30
|
-
if ok := Valid(test.
|
31
|
-
t.Fatalf("Valid(%s)
|
32
|
-
}
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
func TestAddCheck(t *testing.T) {
|
37
|
-
for _, test := range addTests {
|
38
|
-
if luhn := AddCheck(test.raw); luhn != test.luhn {
|
39
|
-
t.Fatalf("AddCheck(%s) = %s, want %s.", test.raw, luhn, test.luhn)
|
21
|
+
for _, test := range testCases {
|
22
|
+
if ok := Valid(test.input); ok != test.ok {
|
23
|
+
t.Fatalf("Valid(%s): %s\n\t Expected: %t\n\t Got: %t", test.input, test.description, ok, test.ok)
|
40
24
|
}
|
41
25
|
}
|
42
26
|
}
|
@@ -47,8 +31,8 @@ func BenchmarkValid(b *testing.B) {
|
|
47
31
|
}
|
48
32
|
}
|
49
33
|
|
50
|
-
func
|
51
|
-
|
52
|
-
|
34
|
+
func TestTestVersion(t *testing.T) {
|
35
|
+
if testVersion != targetTestVersion {
|
36
|
+
t.Errorf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
53
37
|
}
|
54
38
|
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import org.junit.Before;
|
1
2
|
import org.junit.Test;
|
2
3
|
import org.junit.Ignore;
|
3
4
|
|
@@ -10,13 +11,19 @@ import static org.junit.Assert.*;
|
|
10
11
|
|
11
12
|
public class WordCountTest {
|
12
13
|
|
13
|
-
private
|
14
|
+
private WordCount wordCount;
|
15
|
+
private Map<String, Integer> actualWordCount;
|
16
|
+
private Map<String, Integer> expectedWordCount;
|
17
|
+
|
18
|
+
@Before
|
19
|
+
public void setup() {
|
20
|
+
wordCount = new WordCount();
|
21
|
+
expectedWordCount = new HashMap<String, Integer>();
|
22
|
+
}
|
14
23
|
|
15
24
|
|
16
25
|
@Test
|
17
26
|
public void countOneWord() {
|
18
|
-
Map<String, Integer> actualWordCount = new HashMap<String, Integer>();
|
19
|
-
final Map<String, Integer> expectedWordCount = new HashMap<String, Integer>();
|
20
27
|
expectedWordCount.put("word", 1);
|
21
28
|
|
22
29
|
actualWordCount = wordCount.phrase("word");
|
@@ -28,8 +35,6 @@ public class WordCountTest {
|
|
28
35
|
@Ignore
|
29
36
|
@Test
|
30
37
|
public void countOneOfEach() {
|
31
|
-
Map<String, Integer> actualWordCount = new HashMap<String, Integer>();
|
32
|
-
final Map<String, Integer> expectedWordCount = new HashMap<String, Integer>();
|
33
38
|
expectedWordCount.put("one", 1);
|
34
39
|
expectedWordCount.put("of", 1);
|
35
40
|
expectedWordCount.put("each", 1);
|
@@ -43,8 +48,6 @@ public class WordCountTest {
|
|
43
48
|
@Ignore
|
44
49
|
@Test
|
45
50
|
public void countMultipleOccurences() {
|
46
|
-
Map<String, Integer> actualWordCount = new HashMap<String, Integer>();
|
47
|
-
final Map<String, Integer> expectedWordCount = new HashMap<String, Integer>();
|
48
51
|
expectedWordCount.put("one", 1);
|
49
52
|
expectedWordCount.put("fish", 4);
|
50
53
|
expectedWordCount.put("two", 1);
|
@@ -60,8 +63,6 @@ public class WordCountTest {
|
|
60
63
|
@Ignore
|
61
64
|
@Test
|
62
65
|
public void ignorePunctuation() {
|
63
|
-
Map<String, Integer> actualWordCount = new HashMap<String, Integer>();
|
64
|
-
final Map<String, Integer> expectedWordCount = new HashMap<String, Integer>();
|
65
66
|
expectedWordCount.put("car", 1);
|
66
67
|
expectedWordCount.put("carpet", 1);
|
67
68
|
expectedWordCount.put("as", 1);
|
@@ -78,8 +79,6 @@ public class WordCountTest {
|
|
78
79
|
@Ignore
|
79
80
|
@Test
|
80
81
|
public void includeNumbers() {
|
81
|
-
Map<String, Integer> actualWordCount = new HashMap<String, Integer>();
|
82
|
-
final Map<String, Integer> expectedWordCount = new HashMap<String, Integer>();
|
83
82
|
expectedWordCount.put("testing", 2);
|
84
83
|
expectedWordCount.put("1", 1);
|
85
84
|
expectedWordCount.put("2", 1);
|
@@ -93,8 +92,6 @@ public class WordCountTest {
|
|
93
92
|
@Ignore
|
94
93
|
@Test
|
95
94
|
public void normalizeCase() {
|
96
|
-
Map<String, Integer> actualWordCount = new HashMap<String, Integer>();
|
97
|
-
final Map<String, Integer> expectedWordCount = new HashMap<String, Integer>();
|
98
95
|
expectedWordCount.put("go", 3);
|
99
96
|
|
100
97
|
actualWordCount = wordCount.phrase("go Go GO");
|
data/tracks/lua/docs/ABOUT.md
CHANGED
@@ -4,6 +4,6 @@ Lua supports procedural, object-oriented, functional, data-driven programming an
|
|
4
4
|
|
5
5
|
Lua has been used in [many industrial applications](https://sites.google.com/site/marbux/home/where-lua-is-used#8S4UcLlroV5fq8i3WSheIA) with an emphasis on embedded systems and games.
|
6
6
|
|
7
|
-
The home page for Lua is [Lua.org](https://www.lua.org/).
|
7
|
+
The home page for Lua is [Lua.org](https://www.lua.org/). Enjoy!
|
8
8
|
|
9
9
|
(Taken from https://www.lua.org/about.html)
|
@@ -0,0 +1 @@
|
|
1
|
+
Lua is a very small language and you can [learn the basics of the language in 15 minutes](tylerneylon.com/a/learn-lua/). For an exhaustive look at the language, written by the authors of Lua, you can read [Programming in Lua](https://www.lua.org/pil/) (the first edition which covers Lua 5.1 [is available online for free](https://www.lua.org/pil/contents.html)).
|
@@ -1,13 +1,18 @@
|
|
1
1
|
There are many great free online resources for Lua including:
|
2
2
|
|
3
3
|
1. [lua.org][8]
|
4
|
-
2. A highly recommended detailed and authoritative introduction to all aspects of Lua programming by Lua's chief architect: [Programming in Lua
|
4
|
+
2. A highly recommended detailed and authoritative introduction to all aspects of Lua programming by Lua's chief architect: [Programming in Lua, by Roberto Ierusalimschy][6]
|
5
5
|
3. For an official definition of the Lua language, consult the [Lua 5.1 Reference Manual][7], by R. Ierusalimschy, L. H. de Figueiredo, W. Celes.
|
6
6
|
4. [Lua Style Guide][4]
|
7
7
|
5. [Learn Lua in 15 minutes][5]
|
8
|
+
6. [Some][9] [options][10] [for][11] [linting][12]
|
8
9
|
|
9
10
|
[4]: https://github.com/Olivine-Labs/lua-style-guide
|
10
11
|
[5]: http://tylerneylon.com/a/learn-lua/
|
11
12
|
[6]: http://www.lua.org/pil/
|
12
13
|
[7]: http://www.lua.org/manual/5.1/
|
13
14
|
[8]: http://www.lua.org
|
15
|
+
[9]: https://code.google.com/p/lua-checker/
|
16
|
+
[10]: http://lua-users.org/wiki/LuaLint
|
17
|
+
[11]: http://lua-users.org/wiki/LuaInspect
|
18
|
+
[12]: http://lua-users.org/wiki/DetectingUndefinedVariables
|
@@ -1,3 +1,14 @@
|
|
1
|
+
--[[-
|
2
|
+
Note that because ipairs and the length operator work correctly only for sequences
|
3
|
+
in Lua, no arrays with nils are included in these tests. This means that the provided
|
4
|
+
example is not included here:
|
5
|
+
|
6
|
+
input: [1,[2,3,null,4],[null],5]
|
7
|
+
output: [1,2,3,4,5]
|
8
|
+
|
9
|
+
See https://www.lua.org/manual/5.3/manual.html#3.4.7 for more information.
|
10
|
+
]]
|
11
|
+
|
1
12
|
local flatten = require 'flatten-array'
|
2
13
|
|
3
14
|
describe('flatten-array', function()
|
@@ -1,14 +1,7 @@
|
|
1
|
-
local
|
2
|
-
Luhn.__index = Luhn
|
3
|
-
|
4
|
-
function Luhn:check_digit()
|
5
|
-
return tonumber(self.s:sub(-1))
|
6
|
-
end
|
7
|
-
|
8
|
-
function Luhn:addends()
|
1
|
+
local function addends(s)
|
9
2
|
local result = {}
|
10
|
-
for i = #
|
11
|
-
local digit = tonumber(
|
3
|
+
for i = #s, 1, -1 do
|
4
|
+
local digit = tonumber(s:sub(i, i))
|
12
5
|
if #result % 2 > 0 then digit = digit * 2 end
|
13
6
|
if digit > 9 then digit = digit - 9 end
|
14
7
|
table.insert(result, 1, digit)
|
@@ -16,28 +9,19 @@ function Luhn:addends()
|
|
16
9
|
return result
|
17
10
|
end
|
18
11
|
|
19
|
-
function
|
12
|
+
local function checksum(s)
|
20
13
|
local checksum = 0
|
21
|
-
for _, addend in ipairs(
|
14
|
+
for _, addend in ipairs(addends(s)) do
|
22
15
|
checksum = checksum + addend
|
23
16
|
end
|
24
17
|
return checksum
|
25
18
|
end
|
26
19
|
|
27
|
-
function Luhn:valid()
|
28
|
-
return self:checksum() % 10 == 0
|
29
|
-
end
|
30
|
-
|
31
|
-
local function new(s)
|
32
|
-
return setmetatable({ s = s }, Luhn)
|
33
|
-
end
|
34
|
-
|
35
|
-
local function create(s)
|
36
|
-
local checksum = new(s .. '0'):checksum()
|
37
|
-
return s .. tostring((10 - (checksum % 10)) % 10)
|
38
|
-
end
|
39
|
-
|
40
20
|
return {
|
41
|
-
|
42
|
-
|
21
|
+
valid = function(s)
|
22
|
+
s = s:gsub(' ', '')
|
23
|
+
if #s < 2 then return false end
|
24
|
+
if s:find('%D') then return false end
|
25
|
+
return checksum(s) % 10 == 0
|
26
|
+
end
|
43
27
|
}
|