trackler 2.0.6.14 → 2.0.6.15

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