trackler 2.0.8.34 → 2.0.8.35

Sign up to get free protection for your applications and to get access to all the features.
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>