trackler 2.0.6.14 → 2.0.6.15

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/ceylon/.travis.yml +1 -0
  4. data/tracks/ceylon/bin/compile-all-stubs +16 -0
  5. data/tracks/ceylon/config.json +11 -0
  6. data/tracks/ceylon/exercises/react/example/Reactor.ceylon +96 -0
  7. data/tracks/ceylon/exercises/react/example/module.ceylon +4 -0
  8. data/tracks/ceylon/exercises/react/source/react/Reactor.ceylon +29 -0
  9. data/tracks/ceylon/exercises/react/source/react/ReactorTest.ceylon +195 -0
  10. data/tracks/ceylon/exercises/react/source/react/module.ceylon +3 -0
  11. data/tracks/csharp/config.json +9 -0
  12. data/tracks/csharp/exercises/pov/Example.cs +17 -17
  13. data/tracks/csharp/exercises/zipper/Example.cs +137 -0
  14. data/tracks/csharp/exercises/zipper/ZipperTest.cs +83 -0
  15. data/tracks/go/config.json +9 -0
  16. data/tracks/go/exercises/transpose/cases_test.go +247 -0
  17. data/tracks/go/exercises/transpose/example.go +25 -0
  18. data/tracks/go/exercises/transpose/example_gen.go +54 -0
  19. data/tracks/go/exercises/transpose/transpose_test.go +39 -0
  20. data/tracks/go/exercises/triangle/triangle.go +1 -1
  21. data/tracks/haskell/.travis.yml +2 -2
  22. data/tracks/haskell/common/stack.yaml +1 -1
  23. data/tracks/haskell/exercises/accumulate/stack.yaml +1 -1
  24. data/tracks/haskell/exercises/all-your-base/stack.yaml +1 -1
  25. data/tracks/haskell/exercises/allergies/stack.yaml +1 -1
  26. data/tracks/haskell/exercises/alphametics/stack.yaml +1 -1
  27. data/tracks/haskell/exercises/anagram/stack.yaml +1 -1
  28. data/tracks/haskell/exercises/atbash-cipher/stack.yaml +1 -1
  29. data/tracks/haskell/exercises/bank-account/stack.yaml +1 -1
  30. data/tracks/haskell/exercises/beer-song/stack.yaml +1 -1
  31. data/tracks/haskell/exercises/binary-search-tree/stack.yaml +1 -1
  32. data/tracks/haskell/exercises/binary/stack.yaml +1 -1
  33. data/tracks/haskell/exercises/bob/stack.yaml +1 -1
  34. data/tracks/haskell/exercises/bowling/stack.yaml +1 -1
  35. data/tracks/haskell/exercises/change/stack.yaml +1 -1
  36. data/tracks/haskell/exercises/clock/stack.yaml +1 -1
  37. data/tracks/haskell/exercises/connect/stack.yaml +1 -1
  38. data/tracks/haskell/exercises/crypto-square/stack.yaml +1 -1
  39. data/tracks/haskell/exercises/custom-set/stack.yaml +1 -1
  40. data/tracks/haskell/exercises/difference-of-squares/stack.yaml +1 -1
  41. data/tracks/haskell/exercises/dominoes/stack.yaml +1 -1
  42. data/tracks/haskell/exercises/etl/stack.yaml +1 -1
  43. data/tracks/haskell/exercises/food-chain/stack.yaml +1 -1
  44. data/tracks/haskell/exercises/forth/stack.yaml +1 -1
  45. data/tracks/haskell/exercises/gigasecond/stack.yaml +1 -1
  46. data/tracks/haskell/exercises/go-counting/stack.yaml +1 -1
  47. data/tracks/haskell/exercises/grade-school/stack.yaml +1 -1
  48. data/tracks/haskell/exercises/grains/stack.yaml +1 -1
  49. data/tracks/haskell/exercises/hamming/stack.yaml +1 -1
  50. data/tracks/haskell/exercises/hexadecimal/stack.yaml +1 -1
  51. data/tracks/haskell/exercises/house/stack.yaml +1 -1
  52. data/tracks/haskell/exercises/kindergarten-garden/stack.yaml +1 -1
  53. data/tracks/haskell/exercises/largest-series-product/stack.yaml +1 -1
  54. data/tracks/haskell/exercises/leap/stack.yaml +1 -1
  55. data/tracks/haskell/exercises/lens-person/stack.yaml +1 -1
  56. data/tracks/haskell/exercises/linked-list/stack.yaml +1 -1
  57. data/tracks/haskell/exercises/list-ops/stack.yaml +1 -1
  58. data/tracks/haskell/exercises/luhn/stack.yaml +1 -1
  59. data/tracks/haskell/exercises/matrix/stack.yaml +1 -1
  60. data/tracks/haskell/exercises/meetup/stack.yaml +1 -1
  61. data/tracks/haskell/exercises/minesweeper/stack.yaml +1 -1
  62. data/tracks/haskell/exercises/nth-prime/stack.yaml +1 -1
  63. data/tracks/haskell/exercises/nucleotide-count/stack.yaml +1 -1
  64. data/tracks/haskell/exercises/ocr-numbers/stack.yaml +1 -1
  65. data/tracks/haskell/exercises/octal/stack.yaml +1 -1
  66. data/tracks/haskell/exercises/palindrome-products/stack.yaml +1 -1
  67. data/tracks/haskell/exercises/parallel-letter-frequency/stack.yaml +1 -1
  68. data/tracks/haskell/exercises/pascals-triangle/stack.yaml +1 -1
  69. data/tracks/haskell/exercises/phone-number/stack.yaml +1 -1
  70. data/tracks/haskell/exercises/pig-latin/stack.yaml +1 -1
  71. data/tracks/haskell/exercises/pov/stack.yaml +1 -1
  72. data/tracks/haskell/exercises/prime-factors/stack.yaml +1 -1
  73. data/tracks/haskell/exercises/pythagorean-triplet/stack.yaml +1 -1
  74. data/tracks/haskell/exercises/queen-attack/stack.yaml +1 -1
  75. data/tracks/haskell/exercises/raindrops/stack.yaml +1 -1
  76. data/tracks/haskell/exercises/rna-transcription/stack.yaml +1 -1
  77. data/tracks/haskell/exercises/robot-name/stack.yaml +1 -1
  78. data/tracks/haskell/exercises/robot-simulator/stack.yaml +1 -1
  79. data/tracks/haskell/exercises/roman-numerals/stack.yaml +1 -1
  80. data/tracks/haskell/exercises/run-length-encoding/stack.yaml +1 -1
  81. data/tracks/haskell/exercises/saddle-points/stack.yaml +1 -1
  82. data/tracks/haskell/exercises/say/stack.yaml +1 -1
  83. data/tracks/haskell/exercises/scrabble-score/stack.yaml +1 -1
  84. data/tracks/haskell/exercises/secret-handshake/stack.yaml +1 -1
  85. data/tracks/haskell/exercises/series/stack.yaml +1 -1
  86. data/tracks/haskell/exercises/sgf-parsing/stack.yaml +1 -1
  87. data/tracks/haskell/exercises/sieve/stack.yaml +1 -1
  88. data/tracks/haskell/exercises/simple-cipher/stack.yaml +1 -1
  89. data/tracks/haskell/exercises/simple-linked-list/stack.yaml +1 -1
  90. data/tracks/haskell/exercises/space-age/stack.yaml +1 -1
  91. data/tracks/haskell/exercises/strain/stack.yaml +1 -1
  92. data/tracks/haskell/exercises/sublist/stack.yaml +1 -1
  93. data/tracks/haskell/exercises/sum-of-multiples/stack.yaml +1 -1
  94. data/tracks/haskell/exercises/triangle/stack.yaml +1 -1
  95. data/tracks/haskell/exercises/trinary/stack.yaml +1 -1
  96. data/tracks/haskell/exercises/word-count/stack.yaml +1 -1
  97. data/tracks/haskell/exercises/wordy/stack.yaml +1 -1
  98. data/tracks/haskell/exercises/zebra-puzzle/stack.yaml +1 -1
  99. data/tracks/haskell/exercises/zipper/stack.yaml +1 -1
  100. data/tracks/lua/exercises/list-ops/list-ops_spec.lua +1 -1
  101. data/tracks/objective-c/config.json +9 -0
  102. data/tracks/objective-c/exercises/beer-song/BeerSongExample.h +7 -0
  103. data/tracks/objective-c/exercises/beer-song/BeerSongExample.m +56 -0
  104. data/tracks/objective-c/exercises/beer-song/BeerSongTest.m +51 -0
  105. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +23 -1
  106. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/xcshareddata/xcschemes/OCLint.xcscheme +1 -1
  107. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/xcshareddata/xcschemes/xobjectivecTest.xcscheme +1 -1
  108. data/tracks/perl6/config.json +5 -0
  109. data/tracks/perl6/exercises/grade-school/Example.pm +17 -0
  110. data/tracks/perl6/exercises/grade-school/grade-school.t +32 -0
  111. data/tracks/scala/config.json +6 -0
  112. data/tracks/scala/exercises/rna-transcription/build.sbt +2 -2
  113. data/tracks/scala/exercises/sublist/build.sbt +2 -2
  114. data/tracks/scala/exercises/sublist/src/test/scala/SublistTest.scala +1 -1
  115. metadata +19 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b4773a317ee74fec5189add40d22bdb0810d4d5b
4
- data.tar.gz: efb405ccd313b9bd85d8e49a64f95e73685465a0
3
+ metadata.gz: d2be37cbc31136941811e051179467879b92babc
4
+ data.tar.gz: 14dfc0634c8eacfb96344447eb05bc63dfaafe3d
5
5
  SHA512:
6
- metadata.gz: df8a85473aed5805295b688533608f1bf7018764f6a030987c4a94805266c2996ea55764a039ae12f8dad321455d085af0ea5fbbf6b45f5e7b2f4756916c8506
7
- data.tar.gz: a832b5beb59c5e7f4c2f72b8d6e7b0ddd681cca16fcb814d9372e98f055f36d0a8bba906e86eb97772de95ce7fab6306d8df3fcf11425d4a9b38dc58e356d9fa
6
+ metadata.gz: f9e6fcb733742f7201eca5aff89b7e19de23e040ff3809a77aff1459483226f59b2bab528e70b862149656512677e018025f367be6233c23dfb2e8769b6f9ed5
7
+ data.tar.gz: b39e788481896ab1b612425a7922dd249defb2c7b6c30091c15b9deeca895ecfc421372d2023c11bfde097ec4297166b9e5917949774a83697ddba7c8d0ea40c
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.6.14"
2
+ VERSION = "2.0.6.15"
3
3
  end
@@ -7,4 +7,5 @@ install:
7
7
  - sdk install ceylon
8
8
  script:
9
9
  - bin/configlet .
10
+ - bin/compile-all-stubs
10
11
  - bin/test-all-exercises
@@ -0,0 +1,16 @@
1
+ #!/bin/sh
2
+
3
+ exercises=$(dirname $(dirname $0))/exercises
4
+ status=0
5
+
6
+ dir=$(pwd)
7
+
8
+ for d in $exercises/*/; do
9
+ cd $d
10
+ if ! ceylon compile; then
11
+ status=1
12
+ fi
13
+ cd $dir
14
+ done
15
+
16
+ exit $status
@@ -44,6 +44,17 @@
44
44
  "Stacks",
45
45
  "Strings"
46
46
  ]
47
+ },
48
+ {
49
+ "slug": "react",
50
+ "difficulty": 10,
51
+ "topics": [
52
+ "Reactive programming",
53
+ "Generics",
54
+ "Classes",
55
+ "Member classes",
56
+ "Callable"
57
+ ]
47
58
  }
48
59
  ],
49
60
  "deprecated": [
@@ -0,0 +1,96 @@
1
+ import ceylon.collection { HashMap, MutableMap }
2
+
3
+ class Reactor<Element>() given Element satisfies Object {
4
+ shared abstract class Cell() {
5
+ shared formal Element currentValue;
6
+ variable ComputeCell.Inner[] dependents = [];
7
+ shared default void addDependent(ComputeCell.Inner c) {
8
+ dependents = dependents.withTrailing(c);
9
+ }
10
+ shared void eachDependent(Anything(ComputeCell.Inner) f) {
11
+ for (dep in dependents) {
12
+ f(dep);
13
+ }
14
+ }
15
+ }
16
+
17
+ shared class InputCell(Element initialValue) extends Cell() {
18
+ variable Element currentValue_ = initialValue;
19
+ shared actual Element currentValue => currentValue_;
20
+ assign currentValue {
21
+ currentValue_ = currentValue;
22
+ eachDependent((d) => d.propagate());
23
+ eachDependent((d) => d.fireCallbacks());
24
+ }
25
+ }
26
+
27
+ shared class ComputeCell extends Cell {
28
+ shared alias Callback => Anything(Element);
29
+
30
+ shared interface Subscription {
31
+ shared formal void cancel();
32
+ }
33
+
34
+ shared class Inner(Element() newValue) extends Cell() {
35
+ variable Element currentValue_ = newValue();
36
+ shared actual Element currentValue => currentValue_;
37
+ variable Element lastCallbackValue = currentValue_;
38
+
39
+ variable Integer callbacksIssued = 0;
40
+ variable MutableMap<Integer, Callback> activeCallbacks = HashMap<Integer, Callback>();
41
+
42
+ shared Subscription addCallback(Callback f) {
43
+ value id = callbacksIssued;
44
+ callbacksIssued++;
45
+ activeCallbacks.put(id, f);
46
+ return object satisfies Subscription {
47
+ cancel() => activeCallbacks.remove(id);
48
+ };
49
+ }
50
+
51
+ shared void propagate() {
52
+ Element nv = newValue();
53
+ if (nv != currentValue) {
54
+ currentValue_ = nv;
55
+ eachDependent((d) => d.propagate());
56
+ }
57
+ }
58
+
59
+ shared void fireCallbacks() {
60
+ if (lastCallbackValue == currentValue) {
61
+ return;
62
+ }
63
+ lastCallbackValue = currentValue;
64
+ for (cb in activeCallbacks.items) {
65
+ cb(currentValue);
66
+ }
67
+ eachDependent((d) => d.fireCallbacks());
68
+ }
69
+ }
70
+
71
+ Inner inner;
72
+
73
+ shared new single(Cell c, Element(Element) f) extends Cell() {
74
+ // Since `c.addDependent(this)` is illegal, we have to create an inner cell.
75
+ inner = Inner(() => f(c.currentValue));
76
+ c.addDependent(inner);
77
+ }
78
+
79
+ shared new double(Cell c1, Cell c2, Element(Element, Element) f) extends Cell() {
80
+ // Since `c.addDependent(this)` is illegal, we have to create an inner cell.
81
+ inner = Inner(() => f(c1.currentValue, c2.currentValue));
82
+ c1.addDependent(inner);
83
+ c2.addDependent(inner);
84
+ }
85
+
86
+ shared actual Element currentValue => inner.currentValue;
87
+
88
+ shared Subscription addCallback(Callback f) {
89
+ return inner.addCallback(f);
90
+ }
91
+
92
+ shared actual void addDependent(ComputeCell.Inner c) {
93
+ inner.addDependent(c);
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,4 @@
1
+ module react "1.0" {
2
+ import "ceylon.collection" "1.3.1";
3
+ import "ceylon.test" "1.3.1";
4
+ }
@@ -0,0 +1,29 @@
1
+ class Reactor<Element>() given Element satisfies Object {
2
+ shared abstract class Cell() {
3
+ shared formal Element currentValue;
4
+ }
5
+
6
+ shared class InputCell(Element initialValue) extends Cell() {
7
+ shared actual variable Element currentValue = nothing;
8
+ }
9
+
10
+ shared class ComputeCell extends Cell {
11
+ shared new single(Cell c, Element(Element) f) extends Cell() {
12
+ }
13
+
14
+ shared new double(Cell c1, Cell c2, Element(Element, Element) f) extends Cell() {
15
+ }
16
+
17
+ shared alias Callback => Anything(Element);
18
+
19
+ shared actual Element currentValue = nothing;
20
+
21
+ shared interface Subscription {
22
+ shared formal void cancel();
23
+ }
24
+
25
+ shared Subscription addCallback(Callback f) {
26
+ return nothing;
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,195 @@
1
+ import ceylon.test { ... }
2
+
3
+ test
4
+ void inputCellsHaveValue() {
5
+ value r = Reactor<Integer>();
6
+ value input = r.InputCell(10);
7
+ assertEquals(input.currentValue, 10);
8
+ }
9
+
10
+ test
11
+ void inputCellsCanHaveValuesSet() {
12
+ value r = Reactor<Integer>();
13
+ value input = r.InputCell(4);
14
+ input.currentValue = 20;
15
+ assertEquals(input.currentValue, 20);
16
+ }
17
+
18
+ test
19
+ void computeCellsCalculateInitialValue() {
20
+ value r = Reactor<Integer>();
21
+ value input = r.InputCell(1);
22
+ value output = r.ComputeCell.single(input, (Integer x) => x + 1);
23
+ assertEquals(output.currentValue, 2);
24
+ }
25
+
26
+ test
27
+ void computeCellsTakeInputInRightOrder() {
28
+ value r = Reactor<Integer>();
29
+ value one = r.InputCell(1);
30
+ value two = r.InputCell(2);
31
+ value output = r.ComputeCell.double(one, two, (Integer x, Integer y) => x + y * 10);
32
+ assertEquals(output.currentValue, 21);
33
+ }
34
+
35
+ test
36
+ void computeCellsUpdateValueWhenDependenciesChange() {
37
+ value r = Reactor<Integer>();
38
+ value input = r.InputCell(1);
39
+ value output = r.ComputeCell.single(input, (Integer x) => x + 1);
40
+ input.currentValue = 3;
41
+ assertEquals(output.currentValue, 4);
42
+ }
43
+
44
+ test
45
+ void computeCellsCanDependOnOtherComputeCells() {
46
+ value r = Reactor<Integer>();
47
+ value input = r.InputCell(1);
48
+ value timesTwo = r.ComputeCell.single(input, (Integer x) => x * 2);
49
+ value timesThirty = r.ComputeCell.single(input, (Integer x) => x * 30);
50
+ value output = r.ComputeCell.double(timesTwo, timesThirty, (Integer x, Integer y) => x + y);
51
+
52
+ assertEquals(output.currentValue, 32);
53
+ input.currentValue = 3;
54
+ assertEquals(output.currentValue, 96);
55
+ }
56
+
57
+ test
58
+ void computeCellsFireCallbacks() {
59
+ value r = Reactor<Integer>();
60
+ value input = r.InputCell(1);
61
+ value output = r.ComputeCell.single(input, (Integer x) => x + 1);
62
+
63
+ variable Integer[] vals = [];
64
+ output.addCallback((x) => vals = vals.withTrailing(x));
65
+
66
+ input.currentValue = 3;
67
+ assertEquals(vals, [4]);
68
+ }
69
+
70
+ test
71
+ void callbacksOnlyFireOnChange() {
72
+ value r = Reactor<Integer>();
73
+ value input = r.InputCell(1);
74
+ value output = r.ComputeCell.single(input, (Integer x) => if (x < 3) then 111 else 222);
75
+
76
+ variable Integer[] vals = [];
77
+ output.addCallback((x) => vals = vals.withTrailing(x));
78
+
79
+ input.currentValue = 2;
80
+ assertEquals(vals, []);
81
+
82
+ input.currentValue = 4;
83
+ assertEquals(vals, [222]);
84
+ }
85
+
86
+ test
87
+ void callbacksCanBeAddedAndRemoved() {
88
+ value r = Reactor<Integer>();
89
+ value input = r.InputCell(11);
90
+ value output = r.ComputeCell.single(input, (Integer x) => x + 1);
91
+
92
+ variable Integer[] vals1 = [];
93
+ value sub1 = output.addCallback((x) => vals1 = vals1.withTrailing(x));
94
+ variable Integer[] vals2 = [];
95
+ output.addCallback((x) => vals2 = vals2.withTrailing(x));
96
+
97
+ input.currentValue = 31;
98
+
99
+ sub1.cancel();
100
+ variable Integer[] vals3 = [];
101
+ output.addCallback((x) => vals3 = vals3.withTrailing(x));
102
+
103
+ input.currentValue = 41;
104
+
105
+ assertEquals(vals1, [32]);
106
+ assertEquals(vals2, [32, 42]);
107
+ assertEquals(vals3, [42]);
108
+ }
109
+
110
+ test
111
+ void removingCallbackMultipleTimesDoesntInterfereWithOtherCallbacks() {
112
+ value r = Reactor<Integer>();
113
+ value input = r.InputCell(1);
114
+ value output = r.ComputeCell.single(input, (Integer x) => x + 1);
115
+
116
+ variable Integer[] vals1 = [];
117
+ value sub1 = output.addCallback((x) => vals1 = vals1.withTrailing(x));
118
+ variable Integer[] vals2 = [];
119
+ output.addCallback((x) => vals2 = vals2.withTrailing(x));
120
+
121
+ for (i in 1..10) {
122
+ sub1.cancel();
123
+ }
124
+
125
+ input.currentValue = 2;
126
+ assertEquals(vals1, []);
127
+ assertEquals(vals2, [3]);
128
+ }
129
+
130
+ test
131
+ void callbacksAreOnlyCalledOnceEvenIfMultipleDependenciesChange() {
132
+ value r = Reactor<Integer>();
133
+ value input = r.InputCell(1);
134
+ value plusOne = r.ComputeCell.single(input, (Integer x) => x + 1);
135
+ value minusOne1 = r.ComputeCell.single(input, (Integer x) => x - 1);
136
+ value minusOne2 = r.ComputeCell.single(minusOne1, (Integer x) => x - 1);
137
+ value output = r.ComputeCell.double(plusOne, minusOne2, (Integer x, Integer y) => x * y);
138
+
139
+ variable Integer[] vals = [];
140
+ output.addCallback((x) => vals = vals.withTrailing(x));
141
+
142
+ input.currentValue = 4;
143
+ assertEquals(vals, [10]);
144
+ }
145
+
146
+ test
147
+ void callbacksAreNotCalledIfDependenciesChangeButOutputValueDoesntChange() {
148
+ value r = Reactor<Integer>();
149
+ value input = r.InputCell(1);
150
+ value plusOne = r.ComputeCell.single(input, (Integer x) => x + 1);
151
+ value minusOne = r.ComputeCell.single(input, (Integer x) => x - 1);
152
+ value alwaysTwo = r.ComputeCell.double(plusOne, minusOne, (Integer x, Integer y) => x - y);
153
+
154
+ variable Integer[] vals = [];
155
+ alwaysTwo.addCallback((x) => vals = vals.withTrailing(x));
156
+
157
+ for (i in 1..10) {
158
+ input.currentValue = i;
159
+ }
160
+ assertEquals(vals, []);
161
+ }
162
+
163
+ {[Boolean, Boolean, Boolean, Boolean, Boolean]*} adderCases => {
164
+ [false, false, false, false, false],
165
+ [false, false, true, false, true],
166
+ [false, true, false, false, true],
167
+ [false, true, true, true, false],
168
+ [true, false, false, false, true],
169
+ [true, false, true, true, false],
170
+ [true, true, false, true, false],
171
+ [true, true, true, true, true]
172
+ };
173
+
174
+ test
175
+ parameters(`value adderCases`)
176
+ // This is a digital logic circuit called an adder:
177
+ // https://en.wikipedia.org/wiki/Adder_(electronics)
178
+ void testAdder(Boolean aval, Boolean bval, Boolean cinval, Boolean expectCout, Boolean expectSum) {
179
+ value r = Reactor<Boolean>();
180
+ value a = r.InputCell(aval);
181
+ value b = r.InputCell(bval);
182
+ value carryIn = r.InputCell(cinval);
183
+
184
+ value aXorB = r.ComputeCell.double(a, b, (Boolean a, Boolean b) => a != b);
185
+ value sum = r.ComputeCell.double(aXorB, carryIn, (Boolean axorb, Boolean cin) => axorb != cin);
186
+
187
+ value aXorBAndCin = r.ComputeCell.double(aXorB, carryIn, (Boolean axorb, Boolean cin) => axorb && cin);
188
+ value aAndB = r.ComputeCell.double(a, b, (Boolean a, Boolean b) => a && b);
189
+ value carryOut = r.ComputeCell.double(aXorBAndCin, aAndB, (Boolean a, Boolean b) => a || b);
190
+
191
+ // Test them both at once so if they fail we get to see both values.
192
+ [Boolean, Boolean] expected = [expectSum, expectCout];
193
+ [Boolean, Boolean] observed = [sum.currentValue, carryOut.currentValue];
194
+ assertEquals(expected, observed);
195
+ }
@@ -0,0 +1,3 @@
1
+ module react "1.0" {
2
+ import "ceylon.test" "1.3.1";
3
+ }
@@ -814,6 +814,15 @@
814
814
  "Transforming"
815
815
  ]
816
816
  },
817
+ {
818
+ "slug": "zipper",
819
+ "difficulty": 10,
820
+ "topics": [
821
+ "Trees",
822
+ "Recursion",
823
+ "Searching"
824
+ ]
825
+ },
817
826
  {
818
827
  "slug": "alphametics",
819
828
  "difficulty": 10,
@@ -17,9 +17,9 @@ public class Graph<T> : IEquatable<Graph<T>>
17
17
  Value.Equals(other.Value) && Children.SequenceEqual(other.Children);
18
18
  }
19
19
 
20
- public class Crumb<T>
20
+ public class GraphCrumb<T>
21
21
  {
22
- public Crumb(T value, IEnumerable<Graph<T>> left, IEnumerable<Graph<T>> right)
22
+ public GraphCrumb(T value, IEnumerable<Graph<T>> left, IEnumerable<Graph<T>> right)
23
23
  {
24
24
  Value = value;
25
25
  Left = left;
@@ -31,16 +31,16 @@ public class Crumb<T>
31
31
  public IEnumerable<Graph<T>> Right { get; }
32
32
  }
33
33
 
34
- public class Zipper<T>
34
+ public class GraphZipper<T>
35
35
  {
36
- public Zipper(Graph<T> focus, IEnumerable<Crumb<T>> crumbs)
36
+ public GraphZipper(Graph<T> focus, IEnumerable<GraphCrumb<T>> crumbs)
37
37
  {
38
38
  Focus = focus;
39
39
  Crumbs = crumbs;
40
40
  }
41
41
 
42
42
  public Graph<T> Focus { get; }
43
- public IEnumerable<Crumb<T>> Crumbs { get; }
43
+ public IEnumerable<GraphCrumb<T>> Crumbs { get; }
44
44
  }
45
45
 
46
46
  public static class Pov
@@ -54,15 +54,15 @@ public static class Pov
54
54
  public static IEnumerable<T> TracePathBetween<T>(T value1, T value2, Graph<T> graph) where T : IComparable
55
55
  => ZipperToPath(FindNode(value2, GraphToZipper(FromPOV(value1, graph))));
56
56
 
57
- private static Zipper<T> GraphToZipper<T>(Graph<T> graph)
57
+ private static GraphZipper<T> GraphToZipper<T>(Graph<T> graph)
58
58
  {
59
59
  if (graph == null)
60
60
  return null;
61
61
 
62
- return new Zipper<T>(graph, Enumerable.Empty<Crumb<T>>());
62
+ return new GraphZipper<T>(graph, Enumerable.Empty<GraphCrumb<T>>());
63
63
  }
64
64
 
65
- private static IEnumerable<T> ZipperToPath<T>(Zipper<T> zipper)
65
+ private static IEnumerable<T> ZipperToPath<T>(GraphZipper<T> zipper)
66
66
  {
67
67
  if (zipper == null)
68
68
  return null;
@@ -70,7 +70,7 @@ public static class Pov
70
70
  return zipper.Crumbs.Select(c => c.Value).Reverse().Concat(new[] { zipper.Focus.Value });
71
71
  }
72
72
 
73
- private static Zipper<T> GoDown<T>(Zipper<T> zipper)
73
+ private static GraphZipper<T> GoDown<T>(GraphZipper<T> zipper)
74
74
  {
75
75
  if (zipper == null || !zipper.Focus.Children.Any())
76
76
  return null;
@@ -78,12 +78,12 @@ public static class Pov
78
78
  var focus = zipper.Focus;
79
79
  var children = focus.Children;
80
80
 
81
- var newCrumb = new Crumb<T>(focus.Value, Enumerable.Empty<Graph<T>>(), children.Skip(1));
81
+ var newCrumb = new GraphCrumb<T>(focus.Value, Enumerable.Empty<Graph<T>>(), children.Skip(1));
82
82
 
83
- return new Zipper<T>(children.First(), new[] { newCrumb }.Concat(zipper.Crumbs));
83
+ return new GraphZipper<T>(children.First(), new[] { newCrumb }.Concat(zipper.Crumbs));
84
84
  }
85
85
 
86
- private static Zipper<T> GoRight<T>(Zipper<T> zipper)
86
+ private static GraphZipper<T> GoRight<T>(GraphZipper<T> zipper)
87
87
  {
88
88
  if (zipper == null || !zipper.Crumbs.Any() || !zipper.Crumbs.First().Right.Any())
89
89
  return null;
@@ -91,12 +91,12 @@ public static class Pov
91
91
  var crumbs = zipper.Crumbs;
92
92
  var firstCrumb = crumbs.First();
93
93
 
94
- var newCrumb = new Crumb<T>(firstCrumb.Value, firstCrumb.Left.Concat(new[] { zipper.Focus }), firstCrumb.Right.Skip(1));
94
+ var newCrumb = new GraphCrumb<T>(firstCrumb.Value, firstCrumb.Left.Concat(new[] { zipper.Focus }), firstCrumb.Right.Skip(1));
95
95
 
96
- return new Zipper<T>(firstCrumb.Right.First(), new[] { newCrumb }.Concat(crumbs.Skip(1)));
96
+ return new GraphZipper<T>(firstCrumb.Right.First(), new[] { newCrumb }.Concat(crumbs.Skip(1)));
97
97
  }
98
98
 
99
- private static Zipper<T> FindNode<T>(T value, Zipper<T> zipper)
99
+ private static GraphZipper<T> FindNode<T>(T value, GraphZipper<T> zipper)
100
100
  where T : IComparable
101
101
  {
102
102
  if (zipper == null || zipper.Focus.Value.CompareTo(value) == 0)
@@ -105,7 +105,7 @@ public static class Pov
105
105
  return FindNode(value, GoDown(zipper)) ?? FindNode(value, GoRight(zipper));
106
106
  }
107
107
 
108
- private static Graph<T> ChangeParent<T>(Zipper<T> zipper)
108
+ private static Graph<T> ChangeParent<T>(GraphZipper<T> zipper)
109
109
  {
110
110
  if (zipper == null)
111
111
  return null;
@@ -116,7 +116,7 @@ public static class Pov
116
116
  var firstCrumb = zipper.Crumbs.First();
117
117
  var focus = zipper.Focus;
118
118
 
119
- var newZipper = new Zipper<T>(CreateGraph(firstCrumb.Value, firstCrumb.Left.Concat(firstCrumb.Right)), zipper.Crumbs.Skip(1));
119
+ var newZipper = new GraphZipper<T>(CreateGraph(firstCrumb.Value, firstCrumb.Left.Concat(firstCrumb.Right)), zipper.Crumbs.Skip(1));
120
120
  var parentGraph = ChangeParent(newZipper);
121
121
 
122
122
  var ys = focus.Children.Concat(new[] { parentGraph });