trackler 2.0.6.10 → 2.0.6.11
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.
- 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
|
}
|