trackler 2.0.1.0 → 2.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/isogram/canonical-data.json +42 -31
  3. data/common/exercises/leap/canonical-data.json +7 -7
  4. data/common/exercises/matrix/description.md +3 -3
  5. data/common/exercises/minesweeper/canonical-data.json +54 -2
  6. data/common/exercises/pangram/canonical-data.json +5 -0
  7. data/lib/trackler/version.rb +1 -1
  8. data/tracks/clojure/config.json +5 -0
  9. data/tracks/clojure/exercises/acronym/project.clj +4 -0
  10. data/tracks/clojure/exercises/acronym/src/example.clj +8 -0
  11. data/tracks/clojure/exercises/acronym/test/acronym_test.clj +12 -0
  12. data/tracks/crystal/config.json +6 -0
  13. data/tracks/crystal/exercises/binary/spec/binary_spec.cr +76 -0
  14. data/tracks/crystal/exercises/binary/src/example.cr +18 -0
  15. data/tracks/crystal/src/generator/exercises/binary.cr +42 -0
  16. data/tracks/csharp/docs/TESTS.md +6 -2
  17. data/tracks/go/config.json +5 -0
  18. data/tracks/go/exercises/perfect-numbers/example.go +41 -0
  19. data/tracks/go/exercises/perfect-numbers/perfect_numbers_test.go +41 -0
  20. data/tracks/groovy/.gitignore +1 -0
  21. data/tracks/groovy/SETUP.md +6 -54
  22. data/tracks/groovy/exercises/difference-of-squares/Example.groovy +17 -15
  23. data/tracks/groovy/exercises/difference-of-squares/SquaresSpec.groovy +42 -0
  24. data/tracks/groovy/exercises/gigasecond/Example.groovy +9 -7
  25. data/tracks/groovy/exercises/gigasecond/Gigasecond.groovy +5 -2
  26. data/tracks/groovy/exercises/gigasecond/GigasecondSpec.groovy +38 -0
  27. data/tracks/groovy/exercises/hamming/Example.groovy +7 -5
  28. data/tracks/groovy/exercises/hamming/HammingSpec.groovy +50 -0
  29. data/tracks/groovy/exercises/hello-world/Example.groovy +5 -3
  30. data/tracks/groovy/exercises/hello-world/HelloWorld.groovy +5 -3
  31. data/tracks/groovy/exercises/hello-world/HelloWorldSpec.groovy +23 -0
  32. data/tracks/groovy/exercises/raindrops/Example.groovy +8 -8
  33. data/tracks/groovy/exercises/raindrops/RaindropsSpec.groovy +98 -0
  34. data/tracks/groovy/exercises/rna-transcription/ComplementSpec.groovy +51 -0
  35. data/tracks/groovy/exercises/rna-transcription/Example.groovy +19 -14
  36. data/tracks/haskell/.travis.yml +1 -1
  37. data/tracks/haskell/common/stack.yaml +1 -0
  38. data/tracks/haskell/config.json +1 -0
  39. data/tracks/haskell/exercises/pov/stack.yaml +1 -0
  40. data/tracks/haskell/exercises/robot-name/examples/success-standard/src/Robot.hs +1 -1
  41. data/tracks/java/bin/journey-test.sh +9 -4
  42. data/tracks/objective-c/Dangerfile +0 -2
  43. data/tracks/ocaml/exercises/hello-world/test.ml +6 -9
  44. data/tracks/ocaml/tools/test-generator/.merlin +1 -0
  45. data/tracks/ocaml/tools/test-generator/Makefile +4 -4
  46. data/tracks/ocaml/tools/test-generator/{src → interfaces}/codegen.mli +5 -1
  47. data/tracks/ocaml/tools/test-generator/{src → interfaces}/parser.mli +0 -0
  48. data/tracks/ocaml/tools/test-generator/interfaces/special_cases.mli +7 -0
  49. data/tracks/ocaml/tools/test-generator/interfaces/template.mli +11 -0
  50. data/tracks/ocaml/tools/test-generator/interfaces/test_generator.mli +3 -0
  51. data/tracks/ocaml/tools/test-generator/{src → interfaces}/utils.mli +0 -0
  52. data/tracks/ocaml/tools/test-generator/src/codegen.ml +6 -6
  53. data/tracks/ocaml/tools/test-generator/src/template.ml +24 -0
  54. data/tracks/ocaml/tools/test-generator/src/test_generator.ml +10 -26
  55. data/tracks/ocaml/tools/test-generator/test/all_tests.ml +2 -2
  56. data/tracks/ocaml/tools/test-generator/test/codegen_test.ml +1 -1
  57. data/tracks/ocaml/tools/test-generator/test/sample_template.txt +14 -0
  58. data/tracks/ocaml/tools/test-generator/test/template_test.ml +26 -0
  59. data/tracks/perl6/exercises/binary/binary.t +1 -1
  60. data/tracks/perl6/exercises/raindrops/Example.pm +2 -2
  61. data/tracks/perl6/exercises/raindrops/raindrops.t +19 -24
  62. data/tracks/php/.travis.yml +1 -0
  63. data/tracks/php/Makefile +26 -15
  64. data/tracks/php/README.md +19 -0
  65. data/tracks/ruby/README.md +10 -0
  66. data/tracks/rust/config.json +1 -0
  67. data/tracks/rust/exercises/alphametics/Cargo-example.toml +7 -0
  68. data/tracks/rust/exercises/alphametics/Cargo.lock +4 -0
  69. data/tracks/rust/exercises/alphametics/Cargo.toml +3 -0
  70. data/tracks/rust/exercises/alphametics/example.rs +76 -0
  71. data/tracks/rust/exercises/alphametics/src/lib.rs +5 -0
  72. data/tracks/rust/exercises/alphametics/tests/alphametics.rs +62 -0
  73. data/tracks/rust/problems.md +1 -0
  74. data/tracks/scala/exercises/dominoes/src/test/scala/DominoesSuite.scala +1 -1
  75. data/tracks/swift/Dangerfile +0 -2
  76. metadata +32 -39
  77. data/tracks/groovy/exercises/difference-of-squares/SquaresTest.groovy +0 -49
  78. data/tracks/groovy/exercises/gigasecond/GigasecondTest.groovy +0 -29
  79. data/tracks/groovy/exercises/hamming/HammingTest.groovy +0 -56
  80. data/tracks/groovy/exercises/hello-world/HelloWorldTest.groovy +0 -19
  81. data/tracks/groovy/exercises/raindrops/RaindropsTest.groovy +0 -21
  82. data/tracks/groovy/exercises/rna-transcription/ComplementTest.groovy +0 -55
  83. data/tracks/haskell/exercises/pov/stack.yaml +0 -1
  84. data/tracks/java/exercises/anagram/src/main/java/.keep +0 -0
  85. data/tracks/java/exercises/beer-song/src/example/java/.keep +0 -0
  86. data/tracks/java/exercises/beer-song/src/main/java/.keep +0 -0
  87. data/tracks/java/exercises/beer-song/src/test/java/.keep +0 -0
  88. data/tracks/java/exercises/difference-of-squares/src/example/java/.keep +0 -0
  89. data/tracks/java/exercises/difference-of-squares/src/main/java/.keep +0 -0
  90. data/tracks/java/exercises/etl/src/main/java/.keep +0 -0
  91. data/tracks/java/exercises/etl/src/test/java/.keep +0 -0
  92. data/tracks/java/exercises/grade-school/src/test/java/.keep +0 -0
  93. data/tracks/java/exercises/hamming/src/main/java/.keep +0 -0
  94. data/tracks/java/exercises/hello-world/src/main/java/.keep +0 -0
  95. data/tracks/java/exercises/hexadecimal/src/test/java/.keep +0 -0
  96. data/tracks/java/exercises/linked-list/src/example/java/.keep +0 -0
  97. data/tracks/java/exercises/linked-list/src/test/java/.keep +0 -0
  98. data/tracks/java/exercises/meetup/src/main/java/.keep +0 -0
  99. data/tracks/java/exercises/meetup/src/test/java/.keep +0 -0
  100. data/tracks/java/exercises/nth-prime/src/example/java/.keep +0 -0
  101. data/tracks/java/exercises/nth-prime/src/test/java/.keep +0 -0
  102. data/tracks/java/exercises/nucleotide-count/src/main/java/.keep +0 -0
  103. data/tracks/java/exercises/nucleotide-count/src/test/java/.keep +0 -0
  104. data/tracks/java/exercises/pangram/src/test/java/.keep +0 -0
  105. data/tracks/java/exercises/pascals-triangle/src/test/java/.keep +0 -0
  106. data/tracks/java/exercises/series/src/main/java/.keep +0 -0
  107. data/tracks/java/exercises/series/src/test/java/.keep +0 -0
  108. data/tracks/java/exercises/triangle/src/main/java/.keep +0 -0
  109. data/tracks/ocaml/tools/test-generator/src/special_cases.mli +0 -13
  110. data/tracks/ocaml/tools/test-generator/src/test_generator.mli +0 -6
  111. data/tracks/ocaml/tools/test-generator/test/test_generator_test.ml +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 81ae3637f5f3d42296e823f94812c81668d7810c
4
- data.tar.gz: 9651d8a472651fb84914d1893efe32be4e02b9a7
3
+ metadata.gz: e0668847547af08df3e6296f50d8ee7b1acb6d86
4
+ data.tar.gz: 3733aa995d8e62eaa5d97e224f39f74fbb186974
5
5
  SHA512:
6
- metadata.gz: ba199ee4d48f9df1a6c3fab44aff5560ff56cb8b7ebcfb25cacb77c687700736328e2259f3408e6445b89e4817c32d71988c0ccbc6d2f21f5e72248656f67ea2
7
- data.tar.gz: 3e0d68d8cb59b2a26266664ed358b7b1fbc26b5fd69c71b630dd5268da82f0cfe4e2a0d6dc25c594abffb589b45270e00c347b43337be90cd12fd5b76821ca45
6
+ metadata.gz: f80278c35da0397606227fd884ec94a4e5b325e0983da69bd82a6b8039e776729d1b696357f3efe56b9c809e599219a6568cf50a705881582d64c696a018fef8
7
+ data.tar.gz: 176cdc2e4a3b5a58ff89a07a9261215e293723b963af269a3cc02858be676e622a1e3adc7c646c2ae5a04d812b4c57b0a1cbf089f7b86106284ba5fe63ede4d7
@@ -1,33 +1,44 @@
1
1
  {
2
- "cases": [{
3
- "input": "duplicates",
4
- "expected": true
5
- }, {
6
- "input": "eleven",
7
- "expected": false
8
- }, {
9
- "input": "subdermatoglyphic",
10
- "expected": true
11
- }, {
12
- "input": "Alphabet",
13
- "expected": false
14
- }, {
15
- "input": "thumbscrew-japingly",
16
- "expected": true
17
- }, {
18
- "input": "Hjelmqvist-Gryb-Zock-Pfund-Wax",
19
- "expected": true
20
- }, {
21
- "input": "Heizölrückstoßabdämpfung",
22
- "expected": true
23
- }, {
24
- "input": "the quick brown fox",
25
- "expected": false
26
- }, {
27
- "input": "Emily Jung Schwartzkopf",
28
- "expected": true
29
- }, {
30
- "input": "éléphant",
31
- "expected": false
32
- }]
2
+ "cases": [
3
+ {
4
+ "description": "empty string",
5
+ "input": "",
6
+ "expected": true
7
+ },
8
+ {
9
+ "description": "isogram with only lower case characters",
10
+ "input": "isogram",
11
+ "expected": true
12
+ },
13
+ {
14
+ "description": "word with one duplicated character",
15
+ "input": "eleven",
16
+ "expected": false
17
+ },
18
+ {
19
+ "description": "longest reported english isogram",
20
+ "input": "subdermatoglyphic",
21
+ "expected": true
22
+ },
23
+ {
24
+ "description": "word with duplicated character in mixed case",
25
+ "input": "Alphabet",
26
+ "expected": false
27
+ },
28
+ {
29
+ "description": "hypothetical isogrammic word with hyphen",
30
+ "input": "thumbscrew-japingly",
31
+ "expected": true
32
+ },
33
+ {
34
+ "description": "isogram with duplicated non letter character",
35
+ "input": "Hjelmqvist-Gryb-Zock-Pfund-Wax",
36
+ "expected": true
37
+ },
38
+ {
39
+ "description": "made-up name that is an isogram",
40
+ "input": "Emily Jung Schwartzkopf",
41
+ "expected": true
42
+ }
43
+ ]
33
44
  }
@@ -1,37 +1,37 @@
1
1
  {
2
2
  "cases": [
3
3
  {
4
- "description": "leap year",
4
+ "description": "leap year in twentieth century",
5
5
  "input": 1996,
6
6
  "expected": true
7
7
  },
8
8
  {
9
- "description": "standard and odd year",
9
+ "description": "odd standard year in twentieth century",
10
10
  "input": 1997,
11
11
  "expected": false
12
12
  },
13
13
  {
14
- "description": "standard even year",
14
+ "description": "even standard year in twentieth century",
15
15
  "input": 1998,
16
16
  "expected": false
17
17
  },
18
18
  {
19
- "description": "standard nineteenth century",
19
+ "description": "standard year in nineteenth century",
20
20
  "input": 1900,
21
21
  "expected": false
22
22
  },
23
23
  {
24
- "description": "standard eighteenth century",
24
+ "description": "standard year in eighteenth century",
25
25
  "input": 1800,
26
26
  "expected": false
27
27
  },
28
28
  {
29
- "description": "leap twenty fourth century",
29
+ "description": "leap year twenty four hundred",
30
30
  "input": 2400,
31
31
  "expected": true
32
32
  },
33
33
  {
34
- "description": "leap y2k",
34
+ "description": "leap year two thousand",
35
35
  "input": 2000,
36
36
  "expected": true
37
37
  }
@@ -1,8 +1,8 @@
1
1
  So given a string with embedded newlines like:
2
2
 
3
- > 9 8 7
4
- > 5 3 2
5
- > 6 6 7
3
+ > 9 8 7
4
+ > 5 3 2
5
+ > 6 6 7
6
6
 
7
7
  representing this matrix:
8
8
 
@@ -1,20 +1,26 @@
1
1
  {
2
2
  "#": [
3
3
  "The expected outputs are represented as arrays of strings to improve readability in this JSON file.",
4
- "Your track may choose whether to present the input as a single string (concatenating all the lines) or as the list.",
5
- "The inputs are NOT separately provided, as they are simply generated by removing all numbers from the expected outputs."
4
+ "Your track may choose whether to present the input as a single string (concatenating all the lines) or as the list."
6
5
  ],
7
6
  "cases": [
8
7
  {
9
8
  "description": "no rows",
9
+ "input" : [],
10
10
  "expected": []
11
11
  },
12
12
  {
13
13
  "description": "no columns",
14
+ "input" : [""],
14
15
  "expected": [""]
15
16
  },
16
17
  {
17
18
  "description": "no mines",
19
+ "input": [
20
+ " ",
21
+ " ",
22
+ " "
23
+ ],
18
24
  "expected": [
19
25
  " ",
20
26
  " ",
@@ -23,6 +29,11 @@
23
29
  },
24
30
  {
25
31
  "description": "board with only mines",
32
+ "input": [
33
+ "***",
34
+ "***",
35
+ "***"
36
+ ],
26
37
  "expected": [
27
38
  "***",
28
39
  "***",
@@ -31,6 +42,11 @@
31
42
  },
32
43
  {
33
44
  "description": "mine surrounded by spaces",
45
+ "input": [
46
+ " ",
47
+ " * ",
48
+ " "
49
+ ],
34
50
  "expected": [
35
51
  "111",
36
52
  "1*1",
@@ -39,6 +55,11 @@
39
55
  },
40
56
  {
41
57
  "description": "space surrounded by mines",
58
+ "input": [
59
+ " ",
60
+ " 8 ",
61
+ " "
62
+ ],
42
63
  "expected": [
43
64
  "***",
44
65
  "*8*",
@@ -47,14 +68,23 @@
47
68
  },
48
69
  {
49
70
  "description": "horizontal line",
71
+ "input": [" * * "],
50
72
  "expected": ["1*2*1"]
51
73
  },
52
74
  {
53
75
  "description": "horizontal line, mines at edges",
76
+ "input": ["* *"],
54
77
  "expected": ["*1 1*"]
55
78
  },
56
79
  {
57
80
  "description": "vertical line",
81
+ "input": [
82
+ " ",
83
+ "*",
84
+ " ",
85
+ "*",
86
+ " "
87
+ ],
58
88
  "expected": [
59
89
  "1",
60
90
  "*",
@@ -65,6 +95,13 @@
65
95
  },
66
96
  {
67
97
  "description": "vertical line, mines at edges",
98
+ "input": [
99
+ "*",
100
+ " ",
101
+ " ",
102
+ " ",
103
+ "*"
104
+ ],
68
105
  "expected": [
69
106
  "*",
70
107
  "1",
@@ -75,6 +112,13 @@
75
112
  },
76
113
  {
77
114
  "description": "cross",
115
+ "input": [
116
+ " * ",
117
+ " * ",
118
+ "*****",
119
+ " * ",
120
+ " * "
121
+ ],
78
122
  "expected": [
79
123
  " 2*2 ",
80
124
  "25*52",
@@ -85,6 +129,14 @@
85
129
  },
86
130
  {
87
131
  "description": "large board",
132
+ "input": [
133
+ " * * ",
134
+ " * ",
135
+ " * ",
136
+ " * *",
137
+ " * * ",
138
+ " "
139
+ ],
88
140
  "expected": [
89
141
  "1*22*1",
90
142
  "12*322",
@@ -39,6 +39,11 @@
39
39
  "description": "pangram with mixed case and punctuation",
40
40
  "input": "\"Five quacking Zephyrs jolt my wax bed.\"",
41
41
  "expected": true
42
+ },
43
+ {
44
+ "description": "upper and lower case versions of the same character should not be counted separately",
45
+ "input": "the quick brown fox jumped over the lazy FOX",
46
+ "expected": false
42
47
  }
43
48
  ]
44
49
  }
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.1.0"
2
+ VERSION = "2.0.1.1"
3
3
  end
@@ -281,6 +281,11 @@
281
281
  "slug": "isogram",
282
282
  "topics": []
283
283
  },
284
+ {
285
+ "difficulty": 1,
286
+ "slug": "acronym",
287
+ "topics": []
288
+ },
284
289
  {
285
290
  "difficulty": 1,
286
291
  "slug": "pig-latin",
@@ -0,0 +1,4 @@
1
+ (defproject acronym "0.1.0-SNAPSHOT"
2
+ :description "acronym exercise."
3
+ :url "https://github.com/exercism/xclojure/tree/master/exercises/acronym"
4
+ :dependencies [[org.clojure/clojure "1.8.0"]])
@@ -0,0 +1,8 @@
1
+ (ns acronym
2
+ (:require [clojure.string :as str]))
3
+
4
+ (defn acronym [text]
5
+ (->> (re-seq #"[A-Z]+[a-z]*|[a-z]+" text)
6
+ (map first)
7
+ (apply str)
8
+ str/upper-case))
@@ -0,0 +1,12 @@
1
+ (ns acronym-test
2
+ (:require [clojure.test :refer [deftest is]]
3
+ acronym))
4
+
5
+ (deftest test-acronym
6
+ (is (= "" (acronym/acronym "")))
7
+ (is (= "PNG" (acronym/acronym "Portable Network Graphics")))
8
+ (is (= "ROR" (acronym/acronym "Ruby on Rails")))
9
+ (is (= "HTML" (acronym/acronym "HyperText Markup Language")))
10
+ (is (= "FIFO" (acronym/acronym "First In, First Out")))
11
+ (is (= "PHP" (acronym/acronym "PHP: Hypertext Preprocessor")))
12
+ (is (= "CMOS" (acronym/acronym "Complementary metal-oxide semiconductor"))))
@@ -119,6 +119,12 @@
119
119
  "topics": [
120
120
  ]
121
121
  },
122
+ {
123
+ "slug": "binary",
124
+ "difficulty": 1,
125
+ "topics": [
126
+ ]
127
+ },
122
128
  {
123
129
  "slug": "forth",
124
130
  "difficulty": 3,
@@ -0,0 +1,76 @@
1
+ require "spec"
2
+ require "../src/*"
3
+
4
+ describe "Binary" do
5
+ it "binary 0 is decimal 0" do
6
+ Binary.to_decimal("0").should eq(0)
7
+ end
8
+
9
+ pending "binary 1 is decimal 1" do
10
+ Binary.to_decimal("1").should eq(1)
11
+ end
12
+
13
+ pending "binary 10 is decimal 2" do
14
+ Binary.to_decimal("10").should eq(2)
15
+ end
16
+
17
+ pending "binary 11 is decimal 3" do
18
+ Binary.to_decimal("11").should eq(3)
19
+ end
20
+
21
+ pending "binary 100 is decimal 4" do
22
+ Binary.to_decimal("100").should eq(4)
23
+ end
24
+
25
+ pending "binary 1001 is decimal 9" do
26
+ Binary.to_decimal("1001").should eq(9)
27
+ end
28
+
29
+ pending "binary 11010 is decimal 26" do
30
+ Binary.to_decimal("11010").should eq(26)
31
+ end
32
+
33
+ pending "binary 10001101000 is decimal 1128" do
34
+ Binary.to_decimal("10001101000").should eq(1128)
35
+ end
36
+
37
+ pending "binary ignores leading zeros" do
38
+ Binary.to_decimal("000011111").should eq(31)
39
+ end
40
+
41
+ pending "2 is not a valid binary digit" do
42
+ expect_raises do
43
+ Binary.to_decimal("2")
44
+ end
45
+ end
46
+
47
+ pending "a number containing a non-binary digit is invalid" do
48
+ expect_raises do
49
+ Binary.to_decimal("01201")
50
+ end
51
+ end
52
+
53
+ pending "a number with trailing non-binary characters is invalid" do
54
+ expect_raises do
55
+ Binary.to_decimal("10nope")
56
+ end
57
+ end
58
+
59
+ pending "a number with leading non-binary characters is invalid" do
60
+ expect_raises do
61
+ Binary.to_decimal("nope10")
62
+ end
63
+ end
64
+
65
+ pending "a number with internal non-binary characters is invalid" do
66
+ expect_raises do
67
+ Binary.to_decimal("10nope10")
68
+ end
69
+ end
70
+
71
+ pending "a number and a word whitespace spearated is invalid" do
72
+ expect_raises do
73
+ Binary.to_decimal("001 nope")
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,18 @@
1
+ class Binary
2
+ def self.to_decimal(binary)
3
+ new(binary).to_decimal
4
+ end
5
+
6
+ def initialize(binary)
7
+ raise ArgumentError.new if binary.match(/[^0-1]/)
8
+ @binary = binary
9
+ end
10
+
11
+ def to_decimal
12
+ binary.chars.reduce(0) do |decimal, char|
13
+ (decimal * 2) + char.to_i
14
+ end
15
+ end
16
+
17
+ private getter binary : String
18
+ end
@@ -0,0 +1,42 @@
1
+ require "./exercise_generator"
2
+ require "./exercise_test_case"
3
+
4
+ class BinaryGenerator < ExerciseGenerator
5
+ def exercise_name
6
+ "binary"
7
+ end
8
+
9
+ def test_cases
10
+ JSON.parse(data)["decimal"].map do |test_case|
11
+ BinaryTestCase.new(test_case)
12
+ end
13
+ end
14
+ end
15
+
16
+ class BinaryTestCase < ExerciseTestCase
17
+ private getter binary : JSON::Any
18
+ private getter description : JSON::Any
19
+ private getter expected : JSON::Any
20
+
21
+ def initialize(test_case)
22
+ @binary = test_case["binary"]
23
+ @description = test_case["description"]
24
+ @expected = test_case["expected"]
25
+ end
26
+
27
+ def workload
28
+ if !(expected == nil)
29
+ "Binary.to_decimal(\"#{binary}\").should eq(#{expected})"
30
+ else
31
+ <<-WL
32
+ expect_raises do
33
+ Binary.to_decimal(\"#{binary}\")
34
+ end
35
+ WL
36
+ end
37
+ end
38
+
39
+ def test_name
40
+ description
41
+ end
42
+ end
@@ -1,9 +1,9 @@
1
1
  ### Windows
2
2
  All tests have been ignored except the first one for you to work on. To continue, just remove the ```[Ignore]``` attribute on the test to start working on it.
3
3
 
4
- Make sure [NUnit](http://nunit.org/?p=download) version 3.x is installed, if not already installed from the setup from above.
4
+ Make sure [NUnit](http://nunit.org/?p=download) version 3.x is installed, if not already installed from the setup above.
5
5
 
6
- This installation should include the NUnit-Gui executable. Run this and, after compiling, open the assembly from the Gui and you are able to run the tests.
6
+ This installation should include the NUnit-Gui executable. Run this, and after compiling, open the assembly from the Gui and you are able to run the tests.
7
7
 
8
8
  **Note:** You may need to include the nunit-framework.dll in the same directory as the source code you're compiling if you get an error saying it can't find the ```nunit.framework.dll```.
9
9
 
@@ -19,6 +19,10 @@ Once you have been able to compile the code it will create a DLL in the ```\bin\
19
19
 
20
20
  The NUnit runner will automatically reload the DLL if it has been updated.
21
21
 
22
+ ##### Visual Studio Integration
23
+
24
+ Another alternative to running the tests with NUnit-Gui is to run them directly in Visual Studio, which is very convenient if that's your IDE of choice. While the support is natively built in to Visual Studio 2015, for older versions you'll need to install the [NUnit Test Adapter](http://www.nunit.org/index.php?p=vsTestAdapter&r=2.6.2).
25
+
22
26
  ### Mac
23
27
  Xamarin Studio also ships with NUnit. To set the tests up you will have to add an NUnit library project to your solution, name it correctly and set a reference to your solution.
24
28
 
@@ -181,6 +181,11 @@
181
181
  "slug": "protein-translation",
182
182
  "topics": []
183
183
  },
184
+ {
185
+ "difficulty": 1,
186
+ "slug": "perfect-numbers",
187
+ "topics": []
188
+ },
184
189
  {
185
190
  "difficulty": 1,
186
191
  "slug": "bracket-push",
@@ -0,0 +1,41 @@
1
+ package perfect
2
+
3
+ import "errors"
4
+
5
+ const testVersion = 1
6
+
7
+ // Classification is the category devised by Greek Mathematician Nicomachus
8
+ type Classification string
9
+
10
+ // Defined categories
11
+ const (
12
+ ClassificationDeficient Classification = "deficient"
13
+ ClassificationPerfect Classification = "perfect"
14
+ ClassificationAbundant Classification = "abundant"
15
+ )
16
+
17
+ // Errors
18
+ var (
19
+ ErrOnlyPositive = errors.New("Positive number is required")
20
+ )
21
+
22
+ // Classify finds the category of given natural number
23
+ func Classify(n uint64) (Classification, error) {
24
+ if n == 0 {
25
+ return "", ErrOnlyPositive
26
+ }
27
+ var sum uint64
28
+ for i := uint64(1); i < n; i++ {
29
+ if n%i == 0 {
30
+ if sum = sum + i; sum > n {
31
+ return ClassificationAbundant, nil
32
+ }
33
+ }
34
+ }
35
+ if sum == n {
36
+ return ClassificationPerfect, nil
37
+ } else if sum < n {
38
+ return ClassificationDeficient, nil
39
+ }
40
+ return ClassificationAbundant, nil
41
+ }
@@ -0,0 +1,41 @@
1
+ package perfect
2
+
3
+ import "testing"
4
+
5
+ var _ error = ErrOnlyPositive
6
+
7
+ func TestGivesPositiveRequiredError(t *testing.T) {
8
+ if _, err := Classify(0); err != ErrOnlyPositive {
9
+ t.Errorf("Expected error %q but got %q", ErrOnlyPositive, err)
10
+ }
11
+ }
12
+
13
+ func TestClassifiesCorrectly(t *testing.T) {
14
+ cases := []struct {
15
+ input uint64
16
+ expected Classification
17
+ }{
18
+ {1, ClassificationDeficient},
19
+ {13, ClassificationDeficient},
20
+ {12, ClassificationAbundant},
21
+ {6, ClassificationPerfect},
22
+ {28, ClassificationPerfect},
23
+ {496, ClassificationPerfect},
24
+ {8128, ClassificationPerfect},
25
+ }
26
+ for _, c := range cases {
27
+ if cat, err := Classify(c.input); err != nil {
28
+ t.Errorf("%d: Expected no error but got %s", c.input, err)
29
+ } else if cat != c.expected {
30
+ t.Errorf("%d: Expected %q, got %q", c.input, c.expected, cat)
31
+ }
32
+ }
33
+ }
34
+
35
+ const targetTestVersion = 1
36
+
37
+ func TestTestVersion(t *testing.T) {
38
+ if testVersion != targetTestVersion {
39
+ t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
40
+ }
41
+ }
@@ -1,5 +1,6 @@
1
1
  *.swp
2
2
  *.beam
3
+ .project
3
4
  .DS_Store
4
5
  tmp
5
6
  bin/configlet