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.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/ceylon/.travis.yml +1 -0
- data/tracks/ceylon/bin/compile-all-stubs +16 -0
- data/tracks/ceylon/config.json +11 -0
- data/tracks/ceylon/exercises/react/example/Reactor.ceylon +96 -0
- data/tracks/ceylon/exercises/react/example/module.ceylon +4 -0
- data/tracks/ceylon/exercises/react/source/react/Reactor.ceylon +29 -0
- data/tracks/ceylon/exercises/react/source/react/ReactorTest.ceylon +195 -0
- data/tracks/ceylon/exercises/react/source/react/module.ceylon +3 -0
- data/tracks/csharp/config.json +9 -0
- data/tracks/csharp/exercises/pov/Example.cs +17 -17
- data/tracks/csharp/exercises/zipper/Example.cs +137 -0
- data/tracks/csharp/exercises/zipper/ZipperTest.cs +83 -0
- data/tracks/go/config.json +9 -0
- data/tracks/go/exercises/transpose/cases_test.go +247 -0
- data/tracks/go/exercises/transpose/example.go +25 -0
- data/tracks/go/exercises/transpose/example_gen.go +54 -0
- data/tracks/go/exercises/transpose/transpose_test.go +39 -0
- data/tracks/go/exercises/triangle/triangle.go +1 -1
- data/tracks/haskell/.travis.yml +2 -2
- data/tracks/haskell/common/stack.yaml +1 -1
- data/tracks/haskell/exercises/accumulate/stack.yaml +1 -1
- data/tracks/haskell/exercises/all-your-base/stack.yaml +1 -1
- data/tracks/haskell/exercises/allergies/stack.yaml +1 -1
- data/tracks/haskell/exercises/alphametics/stack.yaml +1 -1
- data/tracks/haskell/exercises/anagram/stack.yaml +1 -1
- data/tracks/haskell/exercises/atbash-cipher/stack.yaml +1 -1
- data/tracks/haskell/exercises/bank-account/stack.yaml +1 -1
- data/tracks/haskell/exercises/beer-song/stack.yaml +1 -1
- data/tracks/haskell/exercises/binary-search-tree/stack.yaml +1 -1
- data/tracks/haskell/exercises/binary/stack.yaml +1 -1
- data/tracks/haskell/exercises/bob/stack.yaml +1 -1
- data/tracks/haskell/exercises/bowling/stack.yaml +1 -1
- data/tracks/haskell/exercises/change/stack.yaml +1 -1
- data/tracks/haskell/exercises/clock/stack.yaml +1 -1
- data/tracks/haskell/exercises/connect/stack.yaml +1 -1
- data/tracks/haskell/exercises/crypto-square/stack.yaml +1 -1
- data/tracks/haskell/exercises/custom-set/stack.yaml +1 -1
- data/tracks/haskell/exercises/difference-of-squares/stack.yaml +1 -1
- data/tracks/haskell/exercises/dominoes/stack.yaml +1 -1
- data/tracks/haskell/exercises/etl/stack.yaml +1 -1
- data/tracks/haskell/exercises/food-chain/stack.yaml +1 -1
- data/tracks/haskell/exercises/forth/stack.yaml +1 -1
- data/tracks/haskell/exercises/gigasecond/stack.yaml +1 -1
- data/tracks/haskell/exercises/go-counting/stack.yaml +1 -1
- data/tracks/haskell/exercises/grade-school/stack.yaml +1 -1
- data/tracks/haskell/exercises/grains/stack.yaml +1 -1
- data/tracks/haskell/exercises/hamming/stack.yaml +1 -1
- data/tracks/haskell/exercises/hexadecimal/stack.yaml +1 -1
- data/tracks/haskell/exercises/house/stack.yaml +1 -1
- data/tracks/haskell/exercises/kindergarten-garden/stack.yaml +1 -1
- data/tracks/haskell/exercises/largest-series-product/stack.yaml +1 -1
- data/tracks/haskell/exercises/leap/stack.yaml +1 -1
- data/tracks/haskell/exercises/lens-person/stack.yaml +1 -1
- data/tracks/haskell/exercises/linked-list/stack.yaml +1 -1
- data/tracks/haskell/exercises/list-ops/stack.yaml +1 -1
- data/tracks/haskell/exercises/luhn/stack.yaml +1 -1
- data/tracks/haskell/exercises/matrix/stack.yaml +1 -1
- data/tracks/haskell/exercises/meetup/stack.yaml +1 -1
- data/tracks/haskell/exercises/minesweeper/stack.yaml +1 -1
- data/tracks/haskell/exercises/nth-prime/stack.yaml +1 -1
- data/tracks/haskell/exercises/nucleotide-count/stack.yaml +1 -1
- data/tracks/haskell/exercises/ocr-numbers/stack.yaml +1 -1
- data/tracks/haskell/exercises/octal/stack.yaml +1 -1
- data/tracks/haskell/exercises/palindrome-products/stack.yaml +1 -1
- data/tracks/haskell/exercises/parallel-letter-frequency/stack.yaml +1 -1
- data/tracks/haskell/exercises/pascals-triangle/stack.yaml +1 -1
- data/tracks/haskell/exercises/phone-number/stack.yaml +1 -1
- data/tracks/haskell/exercises/pig-latin/stack.yaml +1 -1
- data/tracks/haskell/exercises/pov/stack.yaml +1 -1
- data/tracks/haskell/exercises/prime-factors/stack.yaml +1 -1
- data/tracks/haskell/exercises/pythagorean-triplet/stack.yaml +1 -1
- data/tracks/haskell/exercises/queen-attack/stack.yaml +1 -1
- data/tracks/haskell/exercises/raindrops/stack.yaml +1 -1
- data/tracks/haskell/exercises/rna-transcription/stack.yaml +1 -1
- data/tracks/haskell/exercises/robot-name/stack.yaml +1 -1
- data/tracks/haskell/exercises/robot-simulator/stack.yaml +1 -1
- data/tracks/haskell/exercises/roman-numerals/stack.yaml +1 -1
- data/tracks/haskell/exercises/run-length-encoding/stack.yaml +1 -1
- data/tracks/haskell/exercises/saddle-points/stack.yaml +1 -1
- data/tracks/haskell/exercises/say/stack.yaml +1 -1
- data/tracks/haskell/exercises/scrabble-score/stack.yaml +1 -1
- data/tracks/haskell/exercises/secret-handshake/stack.yaml +1 -1
- data/tracks/haskell/exercises/series/stack.yaml +1 -1
- data/tracks/haskell/exercises/sgf-parsing/stack.yaml +1 -1
- data/tracks/haskell/exercises/sieve/stack.yaml +1 -1
- data/tracks/haskell/exercises/simple-cipher/stack.yaml +1 -1
- data/tracks/haskell/exercises/simple-linked-list/stack.yaml +1 -1
- data/tracks/haskell/exercises/space-age/stack.yaml +1 -1
- data/tracks/haskell/exercises/strain/stack.yaml +1 -1
- data/tracks/haskell/exercises/sublist/stack.yaml +1 -1
- data/tracks/haskell/exercises/sum-of-multiples/stack.yaml +1 -1
- data/tracks/haskell/exercises/triangle/stack.yaml +1 -1
- data/tracks/haskell/exercises/trinary/stack.yaml +1 -1
- data/tracks/haskell/exercises/word-count/stack.yaml +1 -1
- data/tracks/haskell/exercises/wordy/stack.yaml +1 -1
- data/tracks/haskell/exercises/zebra-puzzle/stack.yaml +1 -1
- data/tracks/haskell/exercises/zipper/stack.yaml +1 -1
- data/tracks/lua/exercises/list-ops/list-ops_spec.lua +1 -1
- data/tracks/objective-c/config.json +9 -0
- data/tracks/objective-c/exercises/beer-song/BeerSongExample.h +7 -0
- data/tracks/objective-c/exercises/beer-song/BeerSongExample.m +56 -0
- data/tracks/objective-c/exercises/beer-song/BeerSongTest.m +51 -0
- data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +23 -1
- data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/xcshareddata/xcschemes/OCLint.xcscheme +1 -1
- data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/xcshareddata/xcschemes/xobjectivecTest.xcscheme +1 -1
- data/tracks/perl6/config.json +5 -0
- data/tracks/perl6/exercises/grade-school/Example.pm +17 -0
- data/tracks/perl6/exercises/grade-school/grade-school.t +32 -0
- data/tracks/scala/config.json +6 -0
- data/tracks/scala/exercises/rna-transcription/build.sbt +2 -2
- data/tracks/scala/exercises/sublist/build.sbt +2 -2
- data/tracks/scala/exercises/sublist/src/test/scala/SublistTest.scala +1 -1
- metadata +19 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d2be37cbc31136941811e051179467879b92babc
|
|
4
|
+
data.tar.gz: 14dfc0634c8eacfb96344447eb05bc63dfaafe3d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f9e6fcb733742f7201eca5aff89b7e19de23e040ff3809a77aff1459483226f59b2bab528e70b862149656512677e018025f367be6233c23dfb2e8769b6f9ed5
|
|
7
|
+
data.tar.gz: b39e788481896ab1b612425a7922dd249defb2c7b6c30091c15b9deeca895ecfc421372d2023c11bfde097ec4297166b9e5917949774a83697ddba7c8d0ea40c
|
data/lib/trackler/version.rb
CHANGED
data/tracks/ceylon/.travis.yml
CHANGED
data/tracks/ceylon/config.json
CHANGED
|
@@ -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,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
|
+
}
|
data/tracks/csharp/config.json
CHANGED
|
@@ -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
|
|
20
|
+
public class GraphCrumb<T>
|
|
21
21
|
{
|
|
22
|
-
public
|
|
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
|
|
34
|
+
public class GraphZipper<T>
|
|
35
35
|
{
|
|
36
|
-
public
|
|
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<
|
|
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
|
|
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
|
|
62
|
+
return new GraphZipper<T>(graph, Enumerable.Empty<GraphCrumb<T>>());
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
private static IEnumerable<T> ZipperToPath<T>(
|
|
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
|
|
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
|
|
81
|
+
var newCrumb = new GraphCrumb<T>(focus.Value, Enumerable.Empty<Graph<T>>(), children.Skip(1));
|
|
82
82
|
|
|
83
|
-
return new
|
|
83
|
+
return new GraphZipper<T>(children.First(), new[] { newCrumb }.Concat(zipper.Crumbs));
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
private static
|
|
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
|
|
94
|
+
var newCrumb = new GraphCrumb<T>(firstCrumb.Value, firstCrumb.Left.Concat(new[] { zipper.Focus }), firstCrumb.Right.Skip(1));
|
|
95
95
|
|
|
96
|
-
return new
|
|
96
|
+
return new GraphZipper<T>(firstCrumb.Right.First(), new[] { newCrumb }.Concat(crumbs.Skip(1)));
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
private static
|
|
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>(
|
|
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
|
|
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 });
|