trackler 2.2.1.2 → 2.2.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/go/config.json +45 -24
- data/tracks/haskell/config/maintainers.json +4 -14
- data/tracks/python/config.json +12 -0
- data/tracks/python/exercises/change/change.py +2 -0
- data/tracks/python/exercises/change/change_test.py +43 -0
- data/tracks/python/exercises/change/example.py +25 -0
- data/tracks/scala/config.json +0 -2
- data/tracks/scala/exercises/largest-series-product/example.scala +15 -8
- data/tracks/scala/exercises/largest-series-product/src/test/scala/SeriesTest.scala +70 -21
- data/tracks/scala/exercises/prime-factors/example.scala +1 -1
- data/tracks/scala/exercises/prime-factors/src/test/scala/PrimefactorsTest.scala +18 -37
- data/tracks/scala/testgen/src/main/scala/PrimeFactorsTestGenerator.scala +55 -0
- data/tracks/scala/testgen/src/main/scala/SeriesTestGenerator.scala +44 -0
- data/tracks/scala/testgen/src/main/scala/testgen/TestSuiteBuilder.scala +6 -4
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2d3bdebe9f23b4e4bd76015bdf93718291556cd
|
4
|
+
data.tar.gz: 663c332d00958e9c5e98dbbf5a39b8b1860bea20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98a6ee04e6e779216a3d1edb522674cde1a6d6b537cbff42a48fd4ec09ea78fe155dbdb346dbea5f9e39caaa35300648ac851d0c193e940593c967f4ca2ec247
|
7
|
+
data.tar.gz: f19ff52e7647ce38e231d8145703fe95d51ca3c664bc82e562d1b54342cad092e3fe51eb81b50b2e5ea1c45c78f95de7f10c8feab32fe2e2047943fafe3aeb08
|
data/lib/trackler/version.rb
CHANGED
data/tracks/go/config.json
CHANGED
@@ -377,9 +377,13 @@
|
|
377
377
|
"slug": "sieve",
|
378
378
|
"core": false,
|
379
379
|
"unlocked_by": null,
|
380
|
-
"difficulty":
|
380
|
+
"difficulty": 3,
|
381
381
|
"topics": [
|
382
|
-
|
382
|
+
"Algorithms",
|
383
|
+
"Integers",
|
384
|
+
"Mathematics",
|
385
|
+
"Sorting",
|
386
|
+
"Control-flow (loops)"
|
383
387
|
]
|
384
388
|
},
|
385
389
|
{
|
@@ -387,9 +391,10 @@
|
|
387
391
|
"slug": "palindrome-products",
|
388
392
|
"core": false,
|
389
393
|
"unlocked_by": null,
|
390
|
-
"difficulty":
|
394
|
+
"difficulty": 6,
|
391
395
|
"topics": [
|
392
|
-
|
396
|
+
"Mathematics",
|
397
|
+
"Algorithms"
|
393
398
|
]
|
394
399
|
},
|
395
400
|
{
|
@@ -397,9 +402,11 @@
|
|
397
402
|
"slug": "protein-translation",
|
398
403
|
"core": false,
|
399
404
|
"unlocked_by": null,
|
400
|
-
"difficulty":
|
405
|
+
"difficulty": 3,
|
401
406
|
"topics": [
|
402
|
-
|
407
|
+
"Filtering",
|
408
|
+
"Maps",
|
409
|
+
"Sequences"
|
403
410
|
]
|
404
411
|
},
|
405
412
|
{
|
@@ -407,9 +414,12 @@
|
|
407
414
|
"slug": "perfect-numbers",
|
408
415
|
"core": false,
|
409
416
|
"unlocked_by": null,
|
410
|
-
"difficulty":
|
417
|
+
"difficulty": 4,
|
411
418
|
"topics": [
|
412
|
-
|
419
|
+
"Integers",
|
420
|
+
"Algorithms",
|
421
|
+
"Mathematics",
|
422
|
+
"Filtering"
|
413
423
|
]
|
414
424
|
},
|
415
425
|
{
|
@@ -417,9 +427,10 @@
|
|
417
427
|
"slug": "bracket-push",
|
418
428
|
"core": false,
|
419
429
|
"unlocked_by": null,
|
420
|
-
"difficulty":
|
430
|
+
"difficulty": 7,
|
421
431
|
"topics": [
|
422
|
-
|
432
|
+
"Parsing",
|
433
|
+
"Strings"
|
423
434
|
]
|
424
435
|
},
|
425
436
|
{
|
@@ -427,9 +438,11 @@
|
|
427
438
|
"slug": "anagram",
|
428
439
|
"core": false,
|
429
440
|
"unlocked_by": null,
|
430
|
-
"difficulty":
|
441
|
+
"difficulty": 3,
|
431
442
|
"topics": [
|
432
|
-
|
443
|
+
"Strings",
|
444
|
+
"Parsing",
|
445
|
+
"Filtering"
|
433
446
|
]
|
434
447
|
},
|
435
448
|
{
|
@@ -437,9 +450,10 @@
|
|
437
450
|
"slug": "word-count",
|
438
451
|
"core": false,
|
439
452
|
"unlocked_by": null,
|
440
|
-
"difficulty":
|
453
|
+
"difficulty": 3,
|
441
454
|
"topics": [
|
442
|
-
|
455
|
+
"Strings",
|
456
|
+
"Sorting"
|
443
457
|
]
|
444
458
|
},
|
445
459
|
{
|
@@ -447,9 +461,10 @@
|
|
447
461
|
"slug": "allergies",
|
448
462
|
"core": false,
|
449
463
|
"unlocked_by": null,
|
450
|
-
"difficulty":
|
464
|
+
"difficulty": 4,
|
451
465
|
"topics": [
|
452
|
-
|
466
|
+
"Enumeration",
|
467
|
+
"Bitwise operations"
|
453
468
|
]
|
454
469
|
},
|
455
470
|
{
|
@@ -457,9 +472,10 @@
|
|
457
472
|
"slug": "rna-transcription",
|
458
473
|
"core": false,
|
459
474
|
"unlocked_by": null,
|
460
|
-
"difficulty":
|
475
|
+
"difficulty": 2,
|
461
476
|
"topics": [
|
462
|
-
|
477
|
+
"Maps",
|
478
|
+
"Transforming"
|
463
479
|
]
|
464
480
|
},
|
465
481
|
{
|
@@ -467,9 +483,10 @@
|
|
467
483
|
"slug": "roman-numerals",
|
468
484
|
"core": false,
|
469
485
|
"unlocked_by": null,
|
470
|
-
"difficulty":
|
486
|
+
"difficulty": 2,
|
471
487
|
"topics": [
|
472
|
-
|
488
|
+
"Numbers",
|
489
|
+
"Transforming"
|
473
490
|
]
|
474
491
|
},
|
475
492
|
{
|
@@ -477,9 +494,12 @@
|
|
477
494
|
"slug": "say",
|
478
495
|
"core": false,
|
479
496
|
"unlocked_by": null,
|
480
|
-
"difficulty":
|
497
|
+
"difficulty": 7,
|
481
498
|
"topics": [
|
482
|
-
|
499
|
+
"Numbers",
|
500
|
+
"Strings",
|
501
|
+
"Transforming",
|
502
|
+
"Text Formatting"
|
483
503
|
]
|
484
504
|
},
|
485
505
|
{
|
@@ -487,9 +507,10 @@
|
|
487
507
|
"slug": "circular-buffer",
|
488
508
|
"core": false,
|
489
509
|
"unlocked_by": null,
|
490
|
-
"difficulty":
|
510
|
+
"difficulty": 5,
|
491
511
|
"topics": [
|
492
|
-
|
512
|
+
"Queues",
|
513
|
+
"Structs"
|
493
514
|
]
|
494
515
|
},
|
495
516
|
{
|
@@ -3,12 +3,7 @@
|
|
3
3
|
{
|
4
4
|
"github_username": "etrepum",
|
5
5
|
"show_on_website": false,
|
6
|
-
"alumnus": true
|
7
|
-
"name": null,
|
8
|
-
"bio": null,
|
9
|
-
"link_text": null,
|
10
|
-
"link_url": null,
|
11
|
-
"avatar_url": null
|
6
|
+
"alumnus": true
|
12
7
|
},
|
13
8
|
{
|
14
9
|
"github_username": "petertseng",
|
@@ -23,19 +18,14 @@
|
|
23
18
|
{
|
24
19
|
"github_username": "abo64",
|
25
20
|
"show_on_website": false,
|
26
|
-
"alumnus":
|
27
|
-
"name": null,
|
28
|
-
"bio": null,
|
29
|
-
"link_text": null,
|
30
|
-
"link_url": null,
|
31
|
-
"avatar_url": null
|
21
|
+
"alumnus": true
|
32
22
|
},
|
33
23
|
{
|
34
24
|
"github_username": "rbasso",
|
35
|
-
"show_on_website":
|
25
|
+
"show_on_website": true,
|
36
26
|
"alumnus": false,
|
37
27
|
"name": null,
|
38
|
-
"bio":
|
28
|
+
"bio": "In a world plagued by mutability, where side-effects scorch the land, a hobbyist programmer joins a fellowship of coders to save The Source.",
|
39
29
|
"link_text": null,
|
40
30
|
"link_url": null,
|
41
31
|
"avatar_url": null
|
data/tracks/python/config.json
CHANGED
@@ -789,6 +789,18 @@
|
|
789
789
|
"pattern matching"
|
790
790
|
]
|
791
791
|
},
|
792
|
+
{
|
793
|
+
"uuid": "889df88a-767d-490f-92c4-552d8ec9de34",
|
794
|
+
"slug": "change",
|
795
|
+
"core": false,
|
796
|
+
"unlocked_by": null,
|
797
|
+
"difficulty": 4,
|
798
|
+
"topics": [
|
799
|
+
"Control-flow (loops)",
|
800
|
+
"Arrays",
|
801
|
+
"Algorithms"
|
802
|
+
]
|
803
|
+
},
|
792
804
|
{
|
793
805
|
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
|
794
806
|
"slug": "accumulate",
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import unittest
|
2
|
+
|
3
|
+
from change import find_minimum_coins
|
4
|
+
|
5
|
+
|
6
|
+
class ChangeTest(unittest.TestCase):
|
7
|
+
def test_single_coin_change(self):
|
8
|
+
self.assertEqual(find_minimum_coins(25, [1, 5, 10, 25, 100]), [25])
|
9
|
+
|
10
|
+
def test_multiple_coin_change(self):
|
11
|
+
self.assertEqual(find_minimum_coins(15, [1, 5, 10, 25, 100]), [5, 10])
|
12
|
+
|
13
|
+
def test_change_with_Lilliputian_Coins(self):
|
14
|
+
self.assertEqual(find_minimum_coins(23, [1, 4, 15, 20, 50]),
|
15
|
+
[4, 4, 15])
|
16
|
+
|
17
|
+
def test_change_with_Lower_Elbonia_Coins(self):
|
18
|
+
self.assertEqual(find_minimum_coins(63, [1, 5, 10, 21, 25]),
|
19
|
+
[21, 21, 21])
|
20
|
+
|
21
|
+
def test_large_target_values(self):
|
22
|
+
self.assertEqual(find_minimum_coins(21, [2, 5, 10, 20, 50]),
|
23
|
+
[2, 2, 2, 5, 10])
|
24
|
+
|
25
|
+
def test_possible_change_without_unit_coins_available(self):
|
26
|
+
self.assertEqual(find_minimum_coins(21, [2, 5, 10, 20, 50]),
|
27
|
+
[2, 2, 2, 5, 10])
|
28
|
+
|
29
|
+
def test_no_coins_make_0_change(self):
|
30
|
+
self.assertEqual(find_minimum_coins(0, [1, 5, 10, 21, 25]), [])
|
31
|
+
|
32
|
+
def test_error_testing_for_change_smaller_than_smallest_coin(self):
|
33
|
+
self.assertEqual(find_minimum_coins(3, [5, 10]), -1)
|
34
|
+
|
35
|
+
def test_error_if_no_combination_can_add_up_to_target(self):
|
36
|
+
self.assertEqual(find_minimum_coins(94, [5, 10]), -1)
|
37
|
+
|
38
|
+
def test_cannot_find_negative_change_values(self):
|
39
|
+
self.assertEqual(find_minimum_coins(-5, [1, 2, 5]), -1)
|
40
|
+
|
41
|
+
|
42
|
+
if __name__ == "__main__":
|
43
|
+
unittest.main()
|
@@ -0,0 +1,25 @@
|
|
1
|
+
def find_minimum_coins(total_change, coins):
|
2
|
+
if total_change < 0:
|
3
|
+
return -1
|
4
|
+
min_coins_required = [1e9] * (total_change + 1)
|
5
|
+
last_coin = [0]*(total_change + 1)
|
6
|
+
min_coins_required[0] = 0
|
7
|
+
last_coin[0] = -1
|
8
|
+
for change in range(1, total_change + 1):
|
9
|
+
final_result = min_coins_required[change]
|
10
|
+
for coin in coins:
|
11
|
+
if coin <= change:
|
12
|
+
result = min_coins_required[change - coin] + 1
|
13
|
+
if result < final_result:
|
14
|
+
final_result = result
|
15
|
+
last_coin[change] = change - coin
|
16
|
+
min_coins_required[change] = final_result
|
17
|
+
if min_coins_required[total_change] == 1e9:
|
18
|
+
return -1
|
19
|
+
else:
|
20
|
+
last_coin_value = total_change
|
21
|
+
array = []
|
22
|
+
while(last_coin[last_coin_value] != -1):
|
23
|
+
array.append(last_coin_value-last_coin[last_coin_value])
|
24
|
+
last_coin_value = last_coin[last_coin_value]
|
25
|
+
return array
|
data/tracks/scala/config.json
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
object Series {
|
2
|
-
private def digits(s: String): List[Int] = s.map(
|
2
|
+
private def digits(s: String): List[Int] = s.filter(_.isDigit).map(_.asDigit).toList
|
3
3
|
|
4
|
-
private def slices(n: Int,
|
5
|
-
|
6
|
-
digits(s).tails.filter(xs => xs.length >= n).map(xs => xs.take(n)).toList
|
7
|
-
}
|
4
|
+
private def slices(n: Int, digits: List[Int]): List[List[Int]] =
|
5
|
+
digits.tails.filter(xs => xs.length >= n).map(_.take(n)).toList
|
8
6
|
|
9
7
|
def largestProduct(n: Int, s: String): Option[Int] =
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
if (n < 0)
|
9
|
+
None
|
10
|
+
else {
|
11
|
+
val ds = digits(s)
|
12
|
+
if (ds.length < s.length)
|
13
|
+
None
|
14
|
+
else {
|
15
|
+
slices(n, ds) match {
|
16
|
+
case Nil => None
|
17
|
+
case xs => Some(xs.map(_.product).max)
|
18
|
+
}
|
19
|
+
}
|
13
20
|
}
|
14
21
|
}
|
@@ -1,30 +1,79 @@
|
|
1
|
-
import org.scalatest.{Matchers,
|
1
|
+
import org.scalatest.{Matchers, FunSuite}
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
Series.largestProduct(2, "
|
8
|
-
|
9
|
-
|
3
|
+
/** @version 1.0.0 */
|
4
|
+
class LargestSeriesProductTest extends FunSuite with Matchers {
|
5
|
+
|
6
|
+
test("finds the largest product if span equals length") {
|
7
|
+
Series.largestProduct(2, "29") should be (Some(18))
|
8
|
+
}
|
9
|
+
|
10
|
+
test("can find the largest product of 2 with numbers in order") {
|
11
|
+
pending
|
12
|
+
Series.largestProduct(2, "0123456789") should be (Some(72))
|
13
|
+
}
|
14
|
+
|
15
|
+
test("can find the largest product of 2") {
|
16
|
+
pending
|
17
|
+
Series.largestProduct(2, "576802143") should be (Some(48))
|
18
|
+
}
|
19
|
+
|
20
|
+
test("can find the largest product of 3 with numbers in order") {
|
21
|
+
pending
|
22
|
+
Series.largestProduct(3, "0123456789") should be (Some(504))
|
23
|
+
}
|
24
|
+
|
25
|
+
test("can find the largest product of 3") {
|
26
|
+
pending
|
27
|
+
Series.largestProduct(3, "1027839564") should be (Some(270))
|
28
|
+
}
|
29
|
+
|
30
|
+
test("can find the largest product of 5 with numbers in order") {
|
31
|
+
pending
|
32
|
+
Series.largestProduct(5, "0123456789") should be (Some(15120))
|
33
|
+
}
|
34
|
+
|
35
|
+
test("can get the largest product of a big number") {
|
36
|
+
pending
|
37
|
+
Series.largestProduct(6, "73167176531330624919225119674426574742355349194934") should be (Some(23520))
|
38
|
+
}
|
39
|
+
|
40
|
+
test("reports zero if the only digits are zero") {
|
41
|
+
pending
|
42
|
+
Series.largestProduct(2, "0000") should be (Some(0))
|
43
|
+
}
|
44
|
+
|
45
|
+
test("reports zero if all spans include zero") {
|
46
|
+
pending
|
47
|
+
Series.largestProduct(3, "99099") should be (Some(0))
|
48
|
+
}
|
49
|
+
|
50
|
+
test("rejects span longer than string length") {
|
51
|
+
pending
|
52
|
+
Series.largestProduct(4, "123") should be (None)
|
10
53
|
}
|
11
54
|
|
12
|
-
|
55
|
+
test("reports 1 for empty string and empty product (0 span)") {
|
13
56
|
pending
|
14
|
-
Series.largestProduct(
|
15
|
-
"73167176531330624919225119674426574742355349194934") should equal(Some(23520))
|
16
|
-
Series.largestProduct(6,
|
17
|
-
"52677741234314237566414902593461595376319419139427") should equal(Some(28350))
|
57
|
+
Series.largestProduct(0, "") should be (Some(1))
|
18
58
|
}
|
19
59
|
|
20
|
-
|
60
|
+
test("reports 1 for nonempty string and empty product (0 span)") {
|
21
61
|
pending
|
22
|
-
Series.largestProduct(0, "") should
|
23
|
-
Series.largestProduct(0, "123") should equal(Some(1))
|
24
|
-
Series.largestProduct(1, "") should equal(None)
|
25
|
-
Series.largestProduct(4, "123") should equal(None)
|
26
|
-
Series.largestProduct(2, "00") should equal(Some(0))
|
27
|
-
Series.largestProduct(3, "99099") should equal(Some(0))
|
62
|
+
Series.largestProduct(0, "123") should be (Some(1))
|
28
63
|
}
|
29
|
-
}
|
30
64
|
|
65
|
+
test("rejects empty string and nonzero span") {
|
66
|
+
pending
|
67
|
+
Series.largestProduct(1, "") should be (None)
|
68
|
+
}
|
69
|
+
|
70
|
+
test("rejects invalid character in digits") {
|
71
|
+
pending
|
72
|
+
Series.largestProduct(2, "1234a5") should be (None)
|
73
|
+
}
|
74
|
+
|
75
|
+
test("rejects negative span") {
|
76
|
+
pending
|
77
|
+
Series.largestProduct(-1, "12345") should be (None)
|
78
|
+
}
|
79
|
+
}
|
@@ -2,7 +2,7 @@ import scala.annotation.tailrec
|
|
2
2
|
|
3
3
|
// Algorithm from - http://fldit-www.cs.uni-dortmund.de/~peter/PS07/HR.pdf
|
4
4
|
object PrimeFactors {
|
5
|
-
def
|
5
|
+
def factors(n: Long): List[Long] = {
|
6
6
|
assert(n >= 1, "Argument must be positive")
|
7
7
|
|
8
8
|
@tailrec
|
@@ -1,58 +1,39 @@
|
|
1
|
-
import org.scalatest.{
|
1
|
+
import org.scalatest.{Matchers, FunSuite}
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
PrimeFactors.forNumber(1) should be (List())
|
6
|
-
}
|
7
|
-
|
8
|
-
it should "calc prime factors of 2" in {
|
9
|
-
pending
|
10
|
-
PrimeFactors.forNumber(2) should be (List(2))
|
11
|
-
}
|
12
|
-
|
13
|
-
it should "calc prime factors of 3" in {
|
14
|
-
pending
|
15
|
-
PrimeFactors.forNumber(3) should be (List(3))
|
16
|
-
}
|
17
|
-
|
18
|
-
it should "calc prime factors of 4" in {
|
19
|
-
pending
|
20
|
-
PrimeFactors.forNumber(4) should be (List(2, 2))
|
21
|
-
}
|
3
|
+
/** @version 1.0.0 */
|
4
|
+
class PrimeFactorsTest extends FunSuite with Matchers {
|
22
5
|
|
23
|
-
|
24
|
-
|
25
|
-
PrimeFactors.forNumber(6) should be (List(2, 3))
|
6
|
+
test("no factors") {
|
7
|
+
PrimeFactors.factors(1) should be (List())
|
26
8
|
}
|
27
9
|
|
28
|
-
|
10
|
+
test("prime number") {
|
29
11
|
pending
|
30
|
-
PrimeFactors.
|
12
|
+
PrimeFactors.factors(2) should be (List(2))
|
31
13
|
}
|
32
14
|
|
33
|
-
|
15
|
+
test("square of a prime") {
|
34
16
|
pending
|
35
|
-
PrimeFactors.
|
17
|
+
PrimeFactors.factors(9) should be (List(3, 3))
|
36
18
|
}
|
37
19
|
|
38
|
-
|
20
|
+
test("cube of a prime") {
|
39
21
|
pending
|
40
|
-
PrimeFactors.
|
22
|
+
PrimeFactors.factors(8) should be (List(2, 2, 2))
|
41
23
|
}
|
42
24
|
|
43
|
-
|
25
|
+
test("product of primes and non-primes") {
|
44
26
|
pending
|
45
|
-
PrimeFactors.
|
27
|
+
PrimeFactors.factors(12) should be (List(2, 2, 3))
|
46
28
|
}
|
47
29
|
|
48
|
-
|
30
|
+
test("product of primes") {
|
49
31
|
pending
|
50
|
-
PrimeFactors.
|
32
|
+
PrimeFactors.factors(901255) should be (List(5, 17, 23, 461))
|
51
33
|
}
|
52
34
|
|
53
|
-
|
35
|
+
test("factors include a large prime") {
|
54
36
|
pending
|
55
|
-
PrimeFactors.
|
37
|
+
PrimeFactors.factors(93819012551l) should be (List(11, 9539, 894119))
|
56
38
|
}
|
57
|
-
}
|
58
|
-
|
39
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import java.io.File
|
2
|
+
|
3
|
+
import testgen.TestSuiteBuilder.{toString, _}
|
4
|
+
import testgen.{CanonicalDataParser, TestCaseData, TestSuiteBuilder}
|
5
|
+
|
6
|
+
object PrimeFactorsTestGenerator {
|
7
|
+
def main(args: Array[String]): Unit = {
|
8
|
+
val file = new File("src/main/resources/prime-factors.json")
|
9
|
+
|
10
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest("input"))
|
11
|
+
println(s"-------------")
|
12
|
+
println(code)
|
13
|
+
println(s"-------------")
|
14
|
+
}
|
15
|
+
|
16
|
+
private def fromLabeledTest(argNames: String*): ToTestCaseData =
|
17
|
+
withLabeledTest { sut =>
|
18
|
+
labeledTest =>
|
19
|
+
val sutFunction = labeledTest.property
|
20
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
21
|
+
val sutCall = s"$sut.$sutFunction($args)"
|
22
|
+
val expected = toString(labeledTest.expected)
|
23
|
+
|
24
|
+
TestCaseData(labeledTest.description, sutCall, expected)
|
25
|
+
}
|
26
|
+
|
27
|
+
def sutArgs(parseResult: CanonicalDataParser.ParseResult, argNames: String*): String =
|
28
|
+
argNames map (name => toString(parseResult(name))) mkString ", "
|
29
|
+
|
30
|
+
def toString(expected: CanonicalDataParser.Expected): String = {
|
31
|
+
expected match {
|
32
|
+
case Left(error) => throw new IllegalStateException("Unexpected Left")
|
33
|
+
case Right(exp) => s"${toString(exp)}"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
private def toString(any: Any): String = {
|
38
|
+
def quote(str: String): String =
|
39
|
+
if ("\"\n" exists (str.contains(_:Char))) "\"\"\"" else "\""
|
40
|
+
|
41
|
+
System.out.println(any.getClass)
|
42
|
+
|
43
|
+
any match {
|
44
|
+
case list: List[_] =>
|
45
|
+
val vals = list.map(s => toString(s)).mkString(", ")
|
46
|
+
s"List($vals)"
|
47
|
+
case str: String =>
|
48
|
+
val quot = quote(str)
|
49
|
+
s"$quot$str$quot"
|
50
|
+
case dbl: Double =>
|
51
|
+
dbl.asInstanceOf[Long].toString + "l"
|
52
|
+
case _ => any.toString
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import java.io.File
|
2
|
+
|
3
|
+
import testgen.TestSuiteBuilder._
|
4
|
+
import testgen._
|
5
|
+
|
6
|
+
object SeriesTestGenerator {
|
7
|
+
def main(args: Array[String]): Unit = {
|
8
|
+
val file = new File("src/main/resources/largest-series-product.json")
|
9
|
+
|
10
|
+
def toExpected(any: Any): String = {
|
11
|
+
any match {
|
12
|
+
case -1 => "None"
|
13
|
+
case i: Int => s"Some($i)"
|
14
|
+
case s: String =>
|
15
|
+
val quot = quote(s)
|
16
|
+
s"$quot$s$quot"
|
17
|
+
case _ => throw new IllegalStateException("Invalid expected val -" + any)
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
def toString(expected: CanonicalDataParser.Expected): String = {
|
22
|
+
expected match {
|
23
|
+
case Left(error) => s"None"
|
24
|
+
case Right(exp) => toExpected(exp)
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
def fromLabeledTest(argNames: String*): ToTestCaseData =
|
29
|
+
withLabeledTest { sut =>
|
30
|
+
labeledTest =>
|
31
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
32
|
+
val property = labeledTest.property
|
33
|
+
val sutCall =
|
34
|
+
s"""Series.$property($args)"""
|
35
|
+
val expected = toString(labeledTest.expected)
|
36
|
+
TestCaseData(labeledTest.description, sutCall, expected)
|
37
|
+
}
|
38
|
+
|
39
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest("span", "digits"))
|
40
|
+
println(s"-------------")
|
41
|
+
println(code)
|
42
|
+
println(s"-------------")
|
43
|
+
}
|
44
|
+
}
|
@@ -70,7 +70,7 @@ object TestSuiteBuilder {
|
|
70
70
|
}
|
71
71
|
|
72
72
|
def sutName(exerciseName: String) =
|
73
|
-
|
73
|
+
exerciseName split "-" map (_.capitalize) mkString
|
74
74
|
def testSuiteName(exerciseName: String): String =
|
75
75
|
sutName(exerciseName) + "Test"
|
76
76
|
|
@@ -86,10 +86,10 @@ object TestSuiteBuilder {
|
|
86
86
|
private def toString(expected: CanonicalDataParser.Expected): String =
|
87
87
|
expected.fold(error => s"Left(${toString(error)})", toString)
|
88
88
|
|
89
|
-
def
|
90
|
-
|
91
|
-
if ("\"\n" exists (str.contains(_:Char))) "\"\"\"" else "\""
|
89
|
+
def quote(str: String): String =
|
90
|
+
if ("\"\n" exists (str.contains(_:Char))) "\"\"\"" else "\""
|
92
91
|
|
92
|
+
def toString(any: Any): String = {
|
93
93
|
any match {
|
94
94
|
case list: List[_] =>
|
95
95
|
val vals = list.map(s => toString(s)).mkString(", ")
|
@@ -97,6 +97,8 @@ object TestSuiteBuilder {
|
|
97
97
|
case str: String =>
|
98
98
|
val quot = quote(str)
|
99
99
|
s"$quot$str$quot"
|
100
|
+
case lstr: Long =>
|
101
|
+
lstr.toString + "l"
|
100
102
|
case _ => any.toString
|
101
103
|
}
|
102
104
|
}
|
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.2.1.
|
4
|
+
version: 2.2.1.3
|
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-07-
|
11
|
+
date: 2017-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -8753,6 +8753,9 @@ files:
|
|
8753
8753
|
- tracks/python/exercises/bracket-push/bracket_push.py
|
8754
8754
|
- tracks/python/exercises/bracket-push/bracket_push_test.py
|
8755
8755
|
- tracks/python/exercises/bracket-push/example.py
|
8756
|
+
- tracks/python/exercises/change/change.py
|
8757
|
+
- tracks/python/exercises/change/change_test.py
|
8758
|
+
- tracks/python/exercises/change/example.py
|
8756
8759
|
- tracks/python/exercises/circular-buffer/README.md
|
8757
8760
|
- tracks/python/exercises/circular-buffer/circular_buffer.py
|
8758
8761
|
- tracks/python/exercises/circular-buffer/circular_buffer_test.py
|
@@ -10620,11 +10623,13 @@ files:
|
|
10620
10623
|
- tracks/scala/testgen/src/main/scala/PangramsTestGenerator.scala
|
10621
10624
|
- tracks/scala/testgen/src/main/scala/PerfectNumbersTestGenerator.scala
|
10622
10625
|
- tracks/scala/testgen/src/main/scala/PhoneNumberTestGenerator.scala
|
10626
|
+
- tracks/scala/testgen/src/main/scala/PrimeFactorsTestGenerator.scala
|
10623
10627
|
- tracks/scala/testgen/src/main/scala/RailFenceCipherTestGenerator.scala
|
10624
10628
|
- tracks/scala/testgen/src/main/scala/RaindropsTestGenerator.scala
|
10625
10629
|
- tracks/scala/testgen/src/main/scala/RnaTranscriptionTestGenerator.scala
|
10626
10630
|
- tracks/scala/testgen/src/main/scala/ScrabbleScoreTestGenerator.scala
|
10627
10631
|
- tracks/scala/testgen/src/main/scala/SecretHandshakeTestGenerator.scala
|
10632
|
+
- tracks/scala/testgen/src/main/scala/SeriesTestGenerator.scala
|
10628
10633
|
- tracks/scala/testgen/src/main/scala/SieveTestGenerator.scala
|
10629
10634
|
- tracks/scala/testgen/src/main/scala/SpiralMatrixTestGenerator.scala
|
10630
10635
|
- tracks/scala/testgen/src/main/scala/SumOfMultiplesTestGenerator.scala
|