trackler 2.2.1.2 → 2.2.1.3
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/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
|