trackler 2.0.8.34 → 2.0.8.35

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/c/exercises/phone-number/src/example.c +6 -6
  4. data/tracks/c/exercises/phone-number/test/test_phone_number.c +50 -5
  5. data/tracks/csharp/exercises/beer-song/BeerSong.cs +2 -2
  6. data/tracks/csharp/exercises/beer-song/BeerSongTest.cs +390 -0
  7. data/tracks/csharp/exercises/beer-song/Example.cs +3 -8
  8. data/tracks/csharp/exercises/wordy/Example.cs +3 -3
  9. data/tracks/csharp/exercises/wordy/Wordy.cs +2 -2
  10. data/tracks/csharp/exercises/wordy/WordyTest.cs +35 -35
  11. data/tracks/csharp/generators/Data/CanonicalDataValue.cs +17 -3
  12. data/tracks/csharp/generators/Exercises/BeerSongExercise.cs +33 -0
  13. data/tracks/csharp/generators/Exercises/EqualityExercise.cs +6 -1
  14. data/tracks/csharp/generators/Exercises/FoodChainExercise.cs +1 -1
  15. data/tracks/csharp/generators/Exercises/HelloWorldExercise.cs +9 -0
  16. data/tracks/csharp/generators/Exercises/NthPrimeExercise.cs +7 -8
  17. data/tracks/csharp/generators/Exercises/WordyExercise.cs +20 -0
  18. data/tracks/csharp/generators/Methods/TestMethodOptions.cs +1 -0
  19. data/tracks/elixir/README.md +1 -1
  20. data/tracks/go/config.json +9 -0
  21. data/tracks/go/exercises/accumulate/accumulate.go +5 -0
  22. data/tracks/go/exercises/change/cases_test.go +83 -0
  23. data/tracks/go/exercises/change/change_test.go +48 -0
  24. data/tracks/go/exercises/change/example.go +153 -0
  25. data/tracks/go/exercises/change/example_gen.go +96 -0
  26. data/tracks/java/exercises/beer-song/src/example/java/BeerSong.java +4 -7
  27. data/tracks/java/exercises/beer-song/src/test/java/BeerSongTest.java +15 -7
  28. data/tracks/julia/img/icon.png +0 -0
  29. data/tracks/julia/img/icon.svg +49 -11
  30. data/tracks/objective-c/exercises/bracket-push/BracketPushExample.h +0 -1
  31. data/tracks/objective-c/exercises/bracket-push/BracketPushExample.m +41 -379
  32. data/tracks/objective-c/exercises/bracket-push/BracketPushTest.m +12 -32
  33. data/tracks/objective-c/exercises/sublist/SublistExample.h +8 -1
  34. data/tracks/objective-c/exercises/sublist/SublistExample.m +27 -42
  35. data/tracks/objective-c/exercises/sublist/SublistTest.m +17 -20
  36. data/tracks/python/exercises/say/say_test.py +16 -11
  37. data/tracks/scala/exercises/pangram/src/test/scala/PangramTest.scala +6 -5
  38. data/tracks/swift/exercises/bob/Sources/BobExample.swift +2 -2
  39. data/tracks/swift/exercises/bob/Tests/BobTests/BobTests.swift +8 -8
  40. metadata +11 -3
  41. data/tracks/csharp/exercises/beer-song/BeerTest.cs +0 -22
@@ -0,0 +1,48 @@
1
+ package change
2
+
3
+ import (
4
+ "reflect"
5
+ "testing"
6
+ )
7
+
8
+ const targetTestVersion = 1
9
+
10
+ func TestTestVersion(t *testing.T) {
11
+ if testVersion != targetTestVersion {
12
+ t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
13
+ }
14
+ }
15
+
16
+ func TestChange(t *testing.T) {
17
+ for _, tc := range testCases {
18
+ actual, err := Change(tc.coins, tc.target)
19
+ if tc.valid {
20
+ if err != nil {
21
+ t.Fatalf("%s : Change(%v, %d): expected %v, got error %s",
22
+ tc.description, tc.coins, tc.target, tc.expectedChange, err)
23
+ } else {
24
+ if !reflect.DeepEqual(actual, tc.expectedChange) {
25
+ t.Fatalf("%s : Change(%v, %d): expected %v, actual %v",
26
+ tc.description, tc.coins, tc.target, tc.expectedChange, actual)
27
+ } else {
28
+ t.Logf("PASS: %s", tc.description)
29
+ }
30
+ }
31
+ } else {
32
+ if err == nil {
33
+ t.Fatalf("%s : Change(%v, %d): expected error, got %v",
34
+ tc.description, tc.coins, tc.target, actual)
35
+ } else {
36
+ t.Logf("PASS: %s", tc.description)
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ func BenchmarkChange(b *testing.B) {
43
+ for _, tc := range testCases {
44
+ for i := 0; i < b.N; i++ {
45
+ Change(tc.coins, tc.target)
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,153 @@
1
+ // Package change demonstrates making change with fewest number of coins.
2
+ package change
3
+
4
+ import (
5
+ "errors"
6
+ "sort"
7
+ )
8
+
9
+ const testVersion = 1
10
+
11
+ var (
12
+ ErrNoSolutionFound = errors.New("No solution")
13
+ ErrNegativeTarget = errors.New("Negative Target")
14
+ )
15
+
16
+ // Change returns a list of coins in increasing value order to make
17
+ // change for target amount from the coins given; an infinite supply of coins is assumed.
18
+ func Change(coins []int, target int) ([]int, error) {
19
+ var solution []int
20
+ if target == 0 {
21
+ // No change needed for 0.
22
+ return []int{}, nil
23
+ }
24
+ if target < 0 {
25
+ // No change possible for negative.
26
+ return nil, ErrNegativeTarget
27
+ }
28
+ findSolution(coins, target, &solution)
29
+ if len(solution) == 0 {
30
+ // No solution possible with coins given.
31
+ return nil, ErrNoSolutionFound
32
+ }
33
+ return solution, nil
34
+ }
35
+
36
+ // findSolution attempts to find a change solution for target amount
37
+ // from the coins given.
38
+ func findSolution(coins []int, target int, s *[]int) {
39
+ // Find the coins to consider, less than the target change amount.
40
+ last := len(coins) - 1
41
+ for ; last >= 0; last-- {
42
+ if coins[last] == target {
43
+ // Perfect single coin solution, so done!
44
+ *s = []int{target}
45
+ return
46
+ }
47
+ if coins[last] > target {
48
+ // Cannot use this too large coin.
49
+ continue
50
+ }
51
+ // Now, 0 .. last are the coins to consider.
52
+ break
53
+ }
54
+ if last < 0 {
55
+ // All coins larger than target.
56
+ return
57
+ }
58
+
59
+ bestsize := target + 1 // an initial "worst" bestsize
60
+ findUsingPartialSolution(nil, coins[0:last+1], target, s, &bestsize)
61
+ }
62
+
63
+ // updateSolution updates solution with newsolution if no prior solution
64
+ // or when length of newsolution is better.
65
+ func updateSolution(newsolution []int, solution *[]int, bestsize *int) {
66
+ if len(*solution) == 0 || len(newsolution) < len(*solution) {
67
+ *bestsize = len(newsolution)
68
+ *solution = make([]int, len(newsolution))
69
+ copy(*solution, newsolution)
70
+ sort.Ints(*solution)
71
+ }
72
+ }
73
+
74
+ // findUsingPartialSolution takes a partial solution, and coin list c looking to meet target
75
+ // while updating solution s to include partial plus the coins meeting target.
76
+ func findUsingPartialSolution(partial []int, c []int, target int, s *[]int, bestsize *int) {
77
+ // We want to consider coins in c in largest to smallest order.
78
+ sort.Sort(sort.Reverse(sort.IntSlice(c)))
79
+
80
+ for e, coin := range c {
81
+ // Find n, which is highest number of coin that could be used in change.
82
+ n := target / coin
83
+
84
+ // Try n, n-1 ... 1
85
+ for k := n; k >= 1; k-- {
86
+ if (k * coin) == target {
87
+ // k coin(s) completes a solution.
88
+ if (len(partial) + k) < *bestsize {
89
+ list := append(partial, nCoins(k, coin)...)
90
+ updateSolution(list, s, bestsize)
91
+ }
92
+ // No need to consider smaller k for coin, so exit this loop.
93
+ break
94
+ }
95
+ if len(c) > 1 {
96
+ // k coin(s) might be potential partial solution.
97
+ newtarget := target - (k * coin)
98
+ // Use a heuristic estimate of whether a partial solution
99
+ // might be worth it: if the larget coin in c not yet used
100
+ // in an already found solution allows the new solution
101
+ // to be smaller, then it would be worth pursuing.
102
+
103
+ // Find the largest coin in c not yet used in *s solution
104
+ // omitting coin, since it is used in this partial solution.
105
+ largest := largestNotUsed(c, *s, coin)
106
+ // It will take at least the partial, plus k coins plus 1 more.
107
+ if (len(partial) + k + 1) < *bestsize {
108
+ // Calculate the minimum potential size of a solution
109
+ // which doesn't include this coin.
110
+ potentialSize := len(partial) + k + (newtarget / largest)
111
+ if (newtarget % largest) != 0 {
112
+ potentialSize++
113
+ }
114
+ if potentialSize < *bestsize {
115
+ // Put k instances of coin in a new partial solution.
116
+ newPartial := append(partial, nCoins(k, coin)...)
117
+ d := append(append([]int{}, c[:e]...), c[e+1:]...)
118
+ // Now look for solution meeting *new* target.
119
+ findUsingPartialSolution(newPartial, d, newtarget, s, bestsize)
120
+ }
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ // Find the largest coin in coins not yet used in solution, not including coin 'omit'.
128
+ // The coins are in largest to smallest order.
129
+ func largestNotUsed(coins []int, solution []int, omit int) int {
130
+ coinLoop:
131
+ for _, coin := range coins {
132
+ if coin == omit {
133
+ continue
134
+ }
135
+ for _, used := range solution {
136
+ if coin == used {
137
+ continue coinLoop
138
+ }
139
+ }
140
+ return coin
141
+ }
142
+ // Should not get here. But unity is safe return value.
143
+ return 1
144
+ }
145
+
146
+ // nCoins returns a list(slice) of length n of a specific coin value.
147
+ func nCoins(n int, coin int) []int {
148
+ coins := make([]int, n)
149
+ for i := 0; i < n; i++ {
150
+ coins[i] = coin
151
+ }
152
+ return coins
153
+ }
@@ -0,0 +1,96 @@
1
+ // +build ignore
2
+
3
+ package main
4
+
5
+ import (
6
+ "log"
7
+ "text/template"
8
+
9
+ "../../gen"
10
+ )
11
+
12
+ func main() {
13
+ t, err := template.New("").Parse(tmpl)
14
+ if err != nil {
15
+ log.Fatal(err)
16
+ }
17
+ var j js
18
+ if err := gen.Gen("change", &j, t); err != nil {
19
+ log.Fatal(err)
20
+ }
21
+ }
22
+
23
+ // The JSON structure we expect to be able to unmarshal into
24
+ type js struct {
25
+ Exercise string
26
+ Version string
27
+ Comments []string
28
+ Cases []OneCase
29
+ }
30
+
31
+ // template applied to above data structure generates the Go test cases
32
+
33
+ type OneCase struct {
34
+ Description string
35
+ Property string
36
+ Coins []int
37
+ Target int
38
+ Expected interface{}
39
+ }
40
+
41
+ func (c OneCase) Valid() bool {
42
+ valid, _ := determineExpected(c.Expected)
43
+ return valid
44
+ }
45
+
46
+ func (c OneCase) IntSlice() []int {
47
+ _, list := determineExpected(c.Expected)
48
+ return list
49
+ }
50
+
51
+ // determineExpected examines an .Expected interface{} object and determines
52
+ // whether an error is indicated by an int value (actually -1) in the JSON,
53
+ // or whether .Expected is a slice of integer coins.
54
+ func determineExpected(expected interface{}) (valid bool, list []int) {
55
+ _, ok := expected.(int)
56
+ if ok {
57
+ return false, nil
58
+ }
59
+ ilist, ok := expected.([]interface{})
60
+ if !ok {
61
+ return false, nil
62
+ }
63
+ list = make([]int, 0)
64
+ for _, iv := range ilist {
65
+ // The literals from the JSON are unmarshalled to float64 values,
66
+ // which are converted to int for the template output.
67
+ v, isFloat64 := iv.(float64)
68
+ if isFloat64 {
69
+ list = append(list, int(v))
70
+ }
71
+ }
72
+ return true, list
73
+ }
74
+
75
+ var tmpl = `package change
76
+
77
+ // Source: {{.Ori}}
78
+ {{if .Commit}}// Commit: {{.Commit}}
79
+ {{end}}
80
+
81
+ var testCases = []struct {
82
+ description string
83
+ coins []int
84
+ target int
85
+ valid bool // true => no error, false => error expected
86
+ expectedChange []int // when .valid == true, the expected change coins
87
+ }{
88
+ {{range .J.Cases}}{
89
+ {{printf "%q" .Description}},
90
+ {{printf "%#v" .Coins}},
91
+ {{printf "%d" .Target}},
92
+ {{printf "%v" .Valid}},
93
+ {{printf "%#v" .IntSlice}},
94
+ },
95
+ {{end}}}
96
+ `
@@ -1,8 +1,6 @@
1
1
  public class BeerSong {
2
- public static String verse(int number)
3
- {
4
- switch (number)
5
- {
2
+ public String verse(int number) {
3
+ switch (number) {
6
4
  case 0:
7
5
  return "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n\n";
8
6
  case 1:
@@ -14,8 +12,7 @@ public class BeerSong {
14
12
  }
15
13
  }
16
14
 
17
- public static String sing(int start, int stop)
18
- {
15
+ public String sing(int start, int stop) {
19
16
  StringBuilder songOutput = new StringBuilder();
20
17
 
21
18
  for (int i=start; i>=stop; i--) {
@@ -25,7 +22,7 @@ public class BeerSong {
25
22
  return songOutput.toString();
26
23
  }
27
24
 
28
- public static String singSong() {
25
+ public String singSong() {
29
26
  return sing(99,0);
30
27
  }
31
28
  }
@@ -1,15 +1,23 @@
1
1
  import org.junit.Test;
2
2
  import org.junit.Ignore;
3
+ import org.junit.Before;
3
4
 
4
5
  import static org.junit.Assert.assertEquals;
5
6
 
6
7
  public class BeerSongTest {
7
8
 
9
+ private BeerSong beerSong;
10
+
11
+ @Before
12
+ public void setup(){
13
+ beerSong = new BeerSong();
14
+ }
15
+
8
16
  @Test
9
17
  public void singFirstVerse() {
10
18
  assertEquals("99 bottles of beer on the wall, 99 bottles of beer.\n" +
11
19
  "Take one down and pass it around, 98 bottles of beer on the wall.\n\n",
12
- BeerSong.verse(99));
20
+ beerSong.verse(99));
13
21
  }
14
22
 
15
23
  @Ignore
@@ -17,7 +25,7 @@ public class BeerSongTest {
17
25
  public void singMiddleVerse() {
18
26
  assertEquals("44 bottles of beer on the wall, 44 bottles of beer.\n" +
19
27
  "Take one down and pass it around, 43 bottles of beer on the wall.\n\n",
20
- BeerSong.verse(44));
28
+ beerSong.verse(44));
21
29
  }
22
30
 
23
31
  @Ignore
@@ -25,7 +33,7 @@ public class BeerSongTest {
25
33
  public void singThirdToLastVerse() {
26
34
  assertEquals("2 bottles of beer on the wall, 2 bottles of beer.\n" +
27
35
  "Take one down and pass it around, 1 bottle of beer on the wall.\n\n",
28
- BeerSong.verse(2));
36
+ beerSong.verse(2));
29
37
  }
30
38
 
31
39
  @Ignore
@@ -33,7 +41,7 @@ public class BeerSongTest {
33
41
  public void singPenultimateVerse() {
34
42
  assertEquals("1 bottle of beer on the wall, 1 bottle of beer.\n" +
35
43
  "Take it down and pass it around, no more bottles of beer on the wall.\n\n",
36
- BeerSong.verse(1));
44
+ beerSong.verse(1));
37
45
  }
38
46
 
39
47
  @Ignore
@@ -41,7 +49,7 @@ public class BeerSongTest {
41
49
  public void singLastVerse() {
42
50
  assertEquals("No more bottles of beer on the wall, no more bottles of beer.\n" +
43
51
  "Go to the store and buy some more, 99 bottles of beer on the wall.\n\n",
44
- BeerSong.verse(0));
52
+ beerSong.verse(0));
45
53
  }
46
54
 
47
55
  @Ignore
@@ -55,7 +63,7 @@ public class BeerSongTest {
55
63
  "Take it down and pass it around, no more bottles of beer on the wall.\n\n" +
56
64
  "No more bottles of beer on the wall, no more bottles of beer.\n" +
57
65
  "Go to the store and buy some more, 99 bottles of beer on the wall.\n\n",
58
- BeerSong.sing(3,0));
66
+ beerSong.sing(3,0));
59
67
  }
60
68
 
61
69
  @Ignore
@@ -161,7 +169,7 @@ public class BeerSongTest {
161
169
  "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n" +
162
170
  "1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n\n" +
163
171
  "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n\n",
164
- BeerSong.singSong());
172
+ beerSong.singSong());
165
173
  }
166
174
 
167
175
  }
Binary file
@@ -1,11 +1,49 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
- <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
- width="612px" height="792px" viewBox="0 0 612 792" enable-background="new 0 0 612 792" xml:space="preserve">
6
- <circle fill="#FFFFFF" stroke="#212121" stroke-width="12" stroke-miterlimit="10" cx="287.849" cy="338.754" r="219.026"/>
7
- <circle fill="#D71D4F" stroke="#212121" stroke-width="12" stroke-miterlimit="10" cx="180.973" cy="398.638" r="82.743"/>
8
- <circle fill="#FFFFFF" stroke="#212121" stroke-width="12" stroke-miterlimit="10" cx="287.849" cy="216.338" r="82.743"/>
9
- <circle fill="#212121" stroke="#212121" stroke-width="12" stroke-miterlimit="10" cx="393.733" cy="398.639" r="82.743"/>
10
- <circle fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" cx="393.733" cy="398.639" r="76.548"/>
11
- </svg>
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+ <svg
5
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+ xmlns:cc="http://creativecommons.org/ns#"
7
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8
+ xmlns:svg="http://www.w3.org/2000/svg"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ version="1.1"
11
+ width="450.052"
12
+ height="450.052"
13
+ viewBox="0 0 450.052 450.052"
14
+ id="Layer_1"
15
+ xml:space="preserve"><metadata
16
+ id="metadata17"><rdf:RDF><cc:Work
17
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
18
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
19
+ id="defs15" /><circle
20
+ cx="287.849"
21
+ cy="338.754"
22
+ r="219.026"
23
+ transform="translate(-62.822998,-113.728)"
24
+ id="circle3"
25
+ style="fill:#ffffff;fill-opacity:1;stroke:#212121;stroke-width:12;stroke-miterlimit:10" /><circle
26
+ cx="180.97301"
27
+ cy="398.638"
28
+ r="82.742996"
29
+ transform="translate(-62.822998,-113.728)"
30
+ id="circle5"
31
+ style="fill:#d71d4f;stroke:#212121;stroke-width:12;stroke-miterlimit:10" /><circle
32
+ cx="287.849"
33
+ cy="216.338"
34
+ r="82.742996"
35
+ transform="translate(-62.822998,-113.728)"
36
+ id="circle7"
37
+ style="fill:#ffffff;stroke:#212121;stroke-width:12;stroke-miterlimit:10" /><circle
38
+ cx="393.733"
39
+ cy="398.63901"
40
+ r="82.742996"
41
+ transform="translate(-62.822998,-113.728)"
42
+ id="circle9"
43
+ style="fill:#212121;stroke:#212121;stroke-width:12;stroke-miterlimit:10" /><circle
44
+ cx="393.733"
45
+ cy="398.63901"
46
+ r="76.547997"
47
+ transform="matrix(0.97336202,0,0,0.95144158,-52.334748,-94.370717)"
48
+ id="circle11"
49
+ style="fill:none;stroke:#ffffff;stroke-width:3.0999999;stroke-miterlimit:10;stroke-dasharray:none" /></svg>