trackler 2.2.1.135 → 2.2.1.136
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/pov/canonical-data.json +33 -1
- data/tracks/c/exercises/acronym/test/test_acronym.c +25 -17
- data/tracks/csharp/exercises/binary-search-tree/BinarySearchTreeTest.cs +37 -28
- data/tracks/csharp/generators/Exercises/BinarySearchTree.cs +69 -0
- data/tracks/haskell/config.json +1 -0
- data/tracks/haskell/exercises/accumulate/package.yaml +1 -1
- data/tracks/haskell/exercises/acronym/package.yaml +1 -1
- data/tracks/haskell/exercises/all-your-base/package.yaml +1 -1
- data/tracks/haskell/exercises/allergies/package.yaml +1 -1
- data/tracks/haskell/exercises/alphametics/package.yaml +1 -1
- data/tracks/haskell/exercises/anagram/package.yaml +1 -1
- data/tracks/haskell/exercises/atbash-cipher/package.yaml +1 -1
- data/tracks/haskell/exercises/bank-account/package.yaml +1 -1
- data/tracks/haskell/exercises/beer-song/package.yaml +1 -1
- data/tracks/haskell/exercises/binary-search-tree/package.yaml +1 -1
- data/tracks/haskell/exercises/binary/package.yaml +1 -1
- data/tracks/haskell/exercises/bob/package.yaml +1 -1
- data/tracks/haskell/exercises/bowling/package.yaml +1 -1
- data/tracks/haskell/exercises/bracket-push/package.yaml +1 -1
- data/tracks/haskell/exercises/change/package.yaml +1 -1
- data/tracks/haskell/exercises/clock/package.yaml +1 -1
- data/tracks/haskell/exercises/collatz-conjecture/package.yaml +1 -1
- data/tracks/haskell/exercises/complex-numbers/package.yaml +1 -1
- data/tracks/haskell/exercises/connect/package.yaml +1 -1
- data/tracks/haskell/exercises/crypto-square/package.yaml +1 -1
- data/tracks/haskell/exercises/custom-set/package.yaml +1 -1
- data/tracks/haskell/exercises/diamond/package.yaml +1 -1
- data/tracks/haskell/exercises/difference-of-squares/package.yaml +1 -1
- data/tracks/haskell/exercises/dominoes/package.yaml +1 -1
- data/tracks/haskell/exercises/etl/package.yaml +1 -1
- data/tracks/haskell/exercises/food-chain/package.yaml +1 -1
- data/tracks/haskell/exercises/forth/package.yaml +1 -1
- data/tracks/haskell/exercises/gigasecond/package.yaml +1 -1
- data/tracks/haskell/exercises/go-counting/package.yaml +1 -1
- data/tracks/haskell/exercises/grade-school/package.yaml +1 -1
- data/tracks/haskell/exercises/grains/package.yaml +1 -1
- data/tracks/haskell/exercises/hamming/package.yaml +1 -1
- data/tracks/haskell/exercises/hello-world/package.yaml +1 -1
- data/tracks/haskell/exercises/hexadecimal/package.yaml +1 -1
- data/tracks/haskell/exercises/house/package.yaml +1 -1
- data/tracks/haskell/exercises/isbn-verifier/package.yaml +1 -1
- data/tracks/haskell/exercises/isogram/package.yaml +1 -1
- data/tracks/haskell/exercises/kindergarten-garden/examples/success-standard/src/Garden.hs +1 -10
- data/tracks/haskell/exercises/kindergarten-garden/package.yaml +2 -3
- data/tracks/haskell/exercises/kindergarten-garden/src/Garden.hs +3 -7
- data/tracks/haskell/exercises/kindergarten-garden/test/Tests.hs +10 -16
- data/tracks/haskell/exercises/largest-series-product/package.yaml +1 -1
- data/tracks/haskell/exercises/leap/package.yaml +1 -1
- data/tracks/haskell/exercises/lens-person/examples/success-standard/package.yaml +0 -1
- data/tracks/haskell/exercises/lens-person/package.yaml +1 -1
- data/tracks/haskell/exercises/linked-list/package.yaml +1 -1
- data/tracks/haskell/exercises/list-ops/package.yaml +1 -1
- data/tracks/haskell/exercises/luhn/package.yaml +1 -1
- data/tracks/haskell/exercises/matrix/package.yaml +1 -1
- data/tracks/haskell/exercises/meetup/package.yaml +1 -1
- data/tracks/haskell/exercises/minesweeper/package.yaml +1 -1
- data/tracks/haskell/exercises/nth-prime/package.yaml +1 -1
- data/tracks/haskell/exercises/nucleotide-count/package.yaml +1 -1
- data/tracks/haskell/exercises/ocr-numbers/package.yaml +1 -1
- data/tracks/haskell/exercises/octal/package.yaml +1 -1
- data/tracks/haskell/exercises/palindrome-products/package.yaml +1 -1
- data/tracks/haskell/exercises/pangram/package.yaml +1 -1
- data/tracks/haskell/exercises/parallel-letter-frequency/package.yaml +1 -1
- data/tracks/haskell/exercises/pascals-triangle/package.yaml +1 -1
- data/tracks/haskell/exercises/perfect-numbers/package.yaml +1 -1
- data/tracks/haskell/exercises/phone-number/package.yaml +1 -1
- data/tracks/haskell/exercises/pig-latin/package.yaml +1 -1
- data/tracks/haskell/exercises/poker/package.yaml +1 -1
- data/tracks/haskell/exercises/pov/package.yaml +2 -2
- data/tracks/haskell/exercises/pov/test/Tests.hs +15 -0
- data/tracks/haskell/exercises/prime-factors/package.yaml +1 -1
- data/tracks/haskell/exercises/protein-translation/package.yaml +1 -1
- data/tracks/haskell/exercises/pythagorean-triplet/package.yaml +1 -1
- data/tracks/haskell/exercises/queen-attack/package.yaml +1 -1
- data/tracks/haskell/exercises/rail-fence-cipher/package.yaml +1 -1
- data/tracks/haskell/exercises/raindrops/package.yaml +1 -1
- data/tracks/haskell/exercises/rna-transcription/package.yaml +1 -1
- data/tracks/haskell/exercises/robot-name/package.yaml +1 -1
- data/tracks/haskell/exercises/robot-simulator/package.yaml +1 -1
- data/tracks/haskell/exercises/roman-numerals/package.yaml +1 -1
- data/tracks/haskell/exercises/rotational-cipher/package.yaml +1 -1
- data/tracks/haskell/exercises/run-length-encoding/package.yaml +1 -1
- data/tracks/haskell/exercises/saddle-points/package.yaml +1 -1
- data/tracks/haskell/exercises/say/package.yaml +1 -1
- data/tracks/haskell/exercises/scrabble-score/package.yaml +1 -1
- data/tracks/haskell/exercises/secret-handshake/package.yaml +1 -1
- data/tracks/haskell/exercises/series/package.yaml +1 -1
- data/tracks/haskell/exercises/sgf-parsing/package.yaml +1 -1
- data/tracks/haskell/exercises/sieve/package.yaml +1 -1
- data/tracks/haskell/exercises/simple-cipher/package.yaml +1 -1
- data/tracks/haskell/exercises/simple-linked-list/package.yaml +1 -1
- data/tracks/haskell/exercises/space-age/package.yaml +1 -1
- data/tracks/haskell/exercises/spiral-matrix/package.yaml +1 -1
- data/tracks/haskell/exercises/strain/package.yaml +1 -1
- data/tracks/haskell/exercises/sublist/package.yaml +1 -1
- data/tracks/haskell/exercises/sum-of-multiples/package.yaml +1 -1
- data/tracks/haskell/exercises/transpose/package.yaml +1 -1
- data/tracks/haskell/exercises/triangle/package.yaml +1 -1
- data/tracks/haskell/exercises/trinary/package.yaml +1 -1
- data/tracks/haskell/exercises/twelve-days/package.yaml +1 -1
- data/tracks/haskell/exercises/word-count/package.yaml +1 -1
- data/tracks/haskell/exercises/wordy/package.yaml +1 -1
- data/tracks/haskell/exercises/zebra-puzzle/package.yaml +1 -1
- data/tracks/haskell/exercises/zipper/package.yaml +1 -1
- data/tracks/java/CONTRIBUTING.md +39 -3
- data/tracks/java/POLICIES.md +68 -3
- data/tracks/java/exercises/crypto-square/README.md +4 -5
- data/tracks/java/exercises/error-handling/README.md +38 -0
- data/tracks/java/exercises/series/README.md +6 -6
- data/tracks/java/exercises/sieve/README.md +5 -3
- data/tracks/java/scripts/canonical_data_check.sh +1 -1
- data/tracks/python/exercises/react/example.py +54 -63
- data/tracks/python/exercises/react/react.py +10 -10
- data/tracks/python/exercises/react/react_test.py +197 -131
- data/tracks/python/exercises/sieve/README.md +5 -3
- data/tracks/rust/exercises/react/example.rs +103 -64
- data/tracks/rust/exercises/react/src/lib.rs +31 -17
- data/tracks/rust/exercises/react/tests/react.rs +52 -61
- data/tracks/swift/config.json +11 -0
- data/tracks/swift/exercises/circular-buffer/Sources/CircularBufferExample.swift +12 -12
- data/tracks/swift/exercises/circular-buffer/Tests/CircularBufferTests/CircularBufferTests.swift +1 -1
- data/tracks/swift/exercises/proverb/Package.swift +5 -0
- data/tracks/swift/exercises/proverb/README.md +25 -0
- data/tracks/swift/exercises/proverb/Sources/Proverb.swift +1 -0
- data/tracks/swift/exercises/proverb/Sources/ProverbExample.swift +28 -0
- data/tracks/swift/exercises/proverb/Tests/LinuxMain.swift +6 -0
- data/tracks/swift/exercises/proverb/Tests/ProverbTests/ProverbTests.swift +61 -0
- data/tracks/typescript/config.json +14 -0
- data/tracks/typescript/exercises/palindrome-products/README.md +65 -0
- data/tracks/typescript/exercises/palindrome-products/package.json +36 -0
- data/tracks/typescript/exercises/palindrome-products/palindrome-products.example.ts +38 -0
- data/tracks/typescript/exercises/palindrome-products/palindrome-products.test.ts +69 -0
- data/tracks/typescript/exercises/palindrome-products/palindrome-products.ts +0 -0
- data/tracks/typescript/exercises/palindrome-products/tsconfig.json +22 -0
- data/tracks/typescript/exercises/palindrome-products/tslint.json +127 -0
- data/tracks/typescript/exercises/palindrome-products/yarn.lock +2624 -0
- metadata +17 -2
@@ -1,12 +1,29 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
pub
|
4
|
-
|
1
|
+
/// `InputCellID` is a unique identifier for an input cell.
|
2
|
+
#[derive(Clone, Copy, Debug, PartialEq)]
|
3
|
+
pub struct InputCellID();
|
4
|
+
/// `ComputeCellID` is a unique identifier for a compute cell.
|
5
|
+
/// Values of type `InputCellID` and `ComputeCellID` should not be mutually assignable,
|
6
|
+
/// demonstrated by the following tests:
|
7
|
+
///
|
8
|
+
/// ```compile_fail
|
9
|
+
/// let mut r = react::Reactor::new();
|
10
|
+
/// let input: react::ComputeCellID = r.create_input(111);
|
11
|
+
/// ```
|
12
|
+
///
|
13
|
+
/// ```compile_fail
|
14
|
+
/// let mut r = react::Reactor::new();
|
15
|
+
/// let input = r.create_input(111);
|
16
|
+
/// let compute: react::InputCellID = r.create_compute(&[react::CellID::Input(input)], |_| 222).unwrap();
|
17
|
+
/// ```
|
18
|
+
#[derive(Clone, Copy, Debug, PartialEq)]
|
19
|
+
pub struct ComputeCellID();
|
20
|
+
#[derive(Clone, Copy, Debug, PartialEq)]
|
21
|
+
pub struct CallbackID();
|
5
22
|
|
6
|
-
#[derive(Debug, PartialEq)]
|
7
|
-
pub enum
|
8
|
-
|
9
|
-
|
23
|
+
#[derive(Clone, Copy, Debug, PartialEq)]
|
24
|
+
pub enum CellID {
|
25
|
+
Input(InputCellID),
|
26
|
+
Compute(ComputeCellID),
|
10
27
|
}
|
11
28
|
|
12
29
|
#[derive(Debug, PartialEq)]
|
@@ -28,7 +45,7 @@ impl <T: Copy + PartialEq> Reactor<T> {
|
|
28
45
|
}
|
29
46
|
|
30
47
|
// Creates an input cell with the specified initial value, returning its ID.
|
31
|
-
pub fn create_input(&mut self, _initial: T) ->
|
48
|
+
pub fn create_input(&mut self, _initial: T) -> InputCellID {
|
32
49
|
unimplemented!()
|
33
50
|
}
|
34
51
|
|
@@ -45,7 +62,7 @@ impl <T: Copy + PartialEq> Reactor<T> {
|
|
45
62
|
// Notice that there is no way to *remove* a cell.
|
46
63
|
// This means that you may assume, without checking, that if the dependencies exist at creation
|
47
64
|
// time they will continue to exist as long as the Reactor exists.
|
48
|
-
pub fn create_compute<F: Fn(&[T]) -> T>(&mut self, _dependencies: &[CellID], _compute_func: F) -> Result<
|
65
|
+
pub fn create_compute<F: Fn(&[T]) -> T>(&mut self, _dependencies: &[CellID], _compute_func: F) -> Result<ComputeCellID, CellID> {
|
49
66
|
unimplemented!()
|
50
67
|
}
|
51
68
|
|
@@ -62,16 +79,13 @@ impl <T: Copy + PartialEq> Reactor<T> {
|
|
62
79
|
|
63
80
|
// Sets the value of the specified input cell.
|
64
81
|
//
|
65
|
-
// Returns
|
66
|
-
// * the cell does not exist
|
67
|
-
// * the specified cell is a compute cell, since compute cells cannot have their values
|
68
|
-
// directly set.
|
82
|
+
// Returns false if the cell does not exist.
|
69
83
|
//
|
70
84
|
// Similarly, you may wonder about `get_mut(&mut self, id: CellID) -> Option<&mut Cell>`, with
|
71
85
|
// a `set_value(&mut self, new_value: T)` method on `Cell`.
|
72
86
|
//
|
73
87
|
// As before, that turned out to add too much extra complexity.
|
74
|
-
pub fn set_value(&mut self, _id:
|
88
|
+
pub fn set_value(&mut self, _id: InputCellID, _new_value: T) -> bool {
|
75
89
|
unimplemented!()
|
76
90
|
}
|
77
91
|
|
@@ -87,7 +101,7 @@ impl <T: Copy + PartialEq> Reactor<T> {
|
|
87
101
|
// * Exactly once if the compute cell's value changed as a result of the set_value call.
|
88
102
|
// The value passed to the callback should be the final value of the compute cell after the
|
89
103
|
// set_value call.
|
90
|
-
pub fn add_callback<F: FnMut(T) -> ()>(&mut self, _id:
|
104
|
+
pub fn add_callback<F: FnMut(T) -> ()>(&mut self, _id: ComputeCellID, _callback: F) -> Option<CallbackID> {
|
91
105
|
unimplemented!()
|
92
106
|
}
|
93
107
|
|
@@ -96,7 +110,7 @@ impl <T: Copy + PartialEq> Reactor<T> {
|
|
96
110
|
// Returns an Err if either the cell or callback does not exist.
|
97
111
|
//
|
98
112
|
// A removed callback should no longer be called.
|
99
|
-
pub fn remove_callback(&mut self, cell:
|
113
|
+
pub fn remove_callback(&mut self, cell: ComputeCellID, callback: CallbackID) -> Result<(), RemoveCallbackError> {
|
100
114
|
unimplemented!(
|
101
115
|
"Remove the callback identified by the CallbackID {:?} from the cell {:?}",
|
102
116
|
callback,
|
@@ -6,7 +6,7 @@ use react::*;
|
|
6
6
|
fn input_cells_have_a_value() {
|
7
7
|
let mut reactor = Reactor::new();
|
8
8
|
let input = reactor.create_input(10);
|
9
|
-
assert_eq!(reactor.value(input), Some(10));
|
9
|
+
assert_eq!(reactor.value(CellID::Input(input)), Some(10));
|
10
10
|
}
|
11
11
|
|
12
12
|
#[test]
|
@@ -14,8 +14,8 @@ fn input_cells_have_a_value() {
|
|
14
14
|
fn an_input_cells_value_can_be_set() {
|
15
15
|
let mut reactor = Reactor::new();
|
16
16
|
let input = reactor.create_input(4);
|
17
|
-
assert!(reactor.set_value(input, 20)
|
18
|
-
assert_eq!(reactor.value(input), Some(20));
|
17
|
+
assert!(reactor.set_value(input, 20));
|
18
|
+
assert_eq!(reactor.value(CellID::Input(input)), Some(20));
|
19
19
|
}
|
20
20
|
|
21
21
|
#[test]
|
@@ -23,7 +23,7 @@ fn an_input_cells_value_can_be_set() {
|
|
23
23
|
fn error_setting_a_nonexistent_input_cell() {
|
24
24
|
let mut dummy_reactor = Reactor::new();
|
25
25
|
let input = dummy_reactor.create_input(1);
|
26
|
-
|
26
|
+
assert!(!Reactor::new().set_value(input, 0));
|
27
27
|
}
|
28
28
|
|
29
29
|
#[test]
|
@@ -31,8 +31,8 @@ fn error_setting_a_nonexistent_input_cell() {
|
|
31
31
|
fn compute_cells_calculate_initial_value() {
|
32
32
|
let mut reactor = Reactor::new();
|
33
33
|
let input = reactor.create_input(1);
|
34
|
-
let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
|
35
|
-
assert_eq!(reactor.value(output), Some(2));
|
34
|
+
let output = reactor.create_compute(&[CellID::Input(input)], |v| v[0] + 1).unwrap();
|
35
|
+
assert_eq!(reactor.value(CellID::Compute(output)), Some(2));
|
36
36
|
}
|
37
37
|
|
38
38
|
#[test]
|
@@ -41,8 +41,8 @@ fn compute_cells_take_inputs_in_the_right_order() {
|
|
41
41
|
let mut reactor = Reactor::new();
|
42
42
|
let one = reactor.create_input(1);
|
43
43
|
let two = reactor.create_input(2);
|
44
|
-
let output = reactor.create_compute(&[one, two], |v| v[0] + v[1] * 10).unwrap();
|
45
|
-
assert_eq!(reactor.value(output), Some(21));
|
44
|
+
let output = reactor.create_compute(&[CellID::Input(one), CellID::Input(two)], |v| v[0] + v[1] * 10).unwrap();
|
45
|
+
assert_eq!(reactor.value(CellID::Compute(output)), Some(21));
|
46
46
|
}
|
47
47
|
|
48
48
|
#[test]
|
@@ -50,7 +50,7 @@ fn compute_cells_take_inputs_in_the_right_order() {
|
|
50
50
|
fn error_creating_compute_cell_if_input_doesnt_exist() {
|
51
51
|
let mut dummy_reactor = Reactor::new();
|
52
52
|
let input = dummy_reactor.create_input(1);
|
53
|
-
assert_eq!(Reactor::new().create_compute(&[input], |_| 0), Err(input));
|
53
|
+
assert_eq!(Reactor::new().create_compute(&[CellID::Input(input)], |_| 0), Err(CellID::Input(input)));
|
54
54
|
}
|
55
55
|
|
56
56
|
#[test]
|
@@ -61,9 +61,9 @@ fn do_not_break_cell_if_creating_compute_cell_with_valid_and_invalid_input() {
|
|
61
61
|
let dummy_cell = dummy_reactor.create_input(2);
|
62
62
|
let mut reactor = Reactor::new();
|
63
63
|
let input = reactor.create_input(1);
|
64
|
-
assert_eq!(reactor.create_compute(&[input, dummy_cell], |_| 0), Err(dummy_cell));
|
65
|
-
assert!(reactor.set_value(input, 5)
|
66
|
-
assert_eq!(reactor.value(input), Some(5));
|
64
|
+
assert_eq!(reactor.create_compute(&[CellID::Input(input), CellID::Input(dummy_cell)], |_| 0), Err(CellID::Input(dummy_cell)));
|
65
|
+
assert!(reactor.set_value(input, 5));
|
66
|
+
assert_eq!(reactor.value(CellID::Input(input)), Some(5));
|
67
67
|
}
|
68
68
|
|
69
69
|
#[test]
|
@@ -71,10 +71,10 @@ fn do_not_break_cell_if_creating_compute_cell_with_valid_and_invalid_input() {
|
|
71
71
|
fn compute_cells_update_value_when_dependencies_are_changed() {
|
72
72
|
let mut reactor = Reactor::new();
|
73
73
|
let input = reactor.create_input(1);
|
74
|
-
let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
|
75
|
-
assert_eq!(reactor.value(output), Some(2));
|
76
|
-
assert!(reactor.set_value(input, 3)
|
77
|
-
assert_eq!(reactor.value(output), Some(4));
|
74
|
+
let output = reactor.create_compute(&[CellID::Input(input)], |v| v[0] + 1).unwrap();
|
75
|
+
assert_eq!(reactor.value(CellID::Compute(output)), Some(2));
|
76
|
+
assert!(reactor.set_value(input, 3));
|
77
|
+
assert_eq!(reactor.value(CellID::Compute(output)), Some(4));
|
78
78
|
}
|
79
79
|
|
80
80
|
#[test]
|
@@ -82,21 +82,12 @@ fn compute_cells_update_value_when_dependencies_are_changed() {
|
|
82
82
|
fn compute_cells_can_depend_on_other_compute_cells() {
|
83
83
|
let mut reactor = Reactor::new();
|
84
84
|
let input = reactor.create_input(1);
|
85
|
-
let times_two = reactor.create_compute(&[input], |v| v[0] * 2).unwrap();
|
86
|
-
let times_thirty = reactor.create_compute(&[input], |v| v[0] * 30).unwrap();
|
87
|
-
let output = reactor.create_compute(&[times_two, times_thirty], |v| v[0] + v[1]).unwrap();
|
88
|
-
assert_eq!(reactor.value(output), Some(32));
|
89
|
-
assert!(reactor.set_value(input, 3)
|
90
|
-
assert_eq!(reactor.value(output), Some(96));
|
91
|
-
}
|
92
|
-
|
93
|
-
#[test]
|
94
|
-
#[ignore]
|
95
|
-
fn error_setting_a_compute_cell() {
|
96
|
-
let mut reactor = Reactor::new();
|
97
|
-
let input = reactor.create_input(1);
|
98
|
-
let output = reactor.create_compute(&[input], |_| 0).unwrap();
|
99
|
-
assert_eq!(reactor.set_value(output, 3), Err(SetValueError::ComputeCell));
|
85
|
+
let times_two = reactor.create_compute(&[CellID::Input(input)], |v| v[0] * 2).unwrap();
|
86
|
+
let times_thirty = reactor.create_compute(&[CellID::Input(input)], |v| v[0] * 30).unwrap();
|
87
|
+
let output = reactor.create_compute(&[CellID::Compute(times_two), CellID::Compute(times_thirty)], |v| v[0] + v[1]).unwrap();
|
88
|
+
assert_eq!(reactor.value(CellID::Compute(output)), Some(32));
|
89
|
+
assert!(reactor.set_value(input, 3));
|
90
|
+
assert_eq!(reactor.value(CellID::Compute(output)), Some(96));
|
100
91
|
}
|
101
92
|
|
102
93
|
/// A CallbackRecorder helps tests whether callbacks get called correctly.
|
@@ -138,9 +129,9 @@ fn compute_cells_fire_callbacks() {
|
|
138
129
|
let cb = CallbackRecorder::new();
|
139
130
|
let mut reactor = Reactor::new();
|
140
131
|
let input = reactor.create_input(1);
|
141
|
-
let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
|
132
|
+
let output = reactor.create_compute(&[CellID::Input(input)], |v| v[0] + 1).unwrap();
|
142
133
|
assert!(reactor.add_callback(output, |v| cb.callback_called(v)).is_some());
|
143
|
-
assert!(reactor.set_value(input, 3)
|
134
|
+
assert!(reactor.set_value(input, 3));
|
144
135
|
cb.expect_to_have_been_called_with(4);
|
145
136
|
}
|
146
137
|
|
@@ -149,7 +140,7 @@ fn compute_cells_fire_callbacks() {
|
|
149
140
|
fn error_adding_callback_to_nonexistent_cell() {
|
150
141
|
let mut dummy_reactor = Reactor::new();
|
151
142
|
let input = dummy_reactor.create_input(1);
|
152
|
-
let output = dummy_reactor.create_compute(&[input], |_| 0).unwrap();
|
143
|
+
let output = dummy_reactor.create_compute(&[CellID::Input(input)], |_| 0).unwrap();
|
153
144
|
assert_eq!(Reactor::new().add_callback(output, |_: usize| println!("hi")), None);
|
154
145
|
}
|
155
146
|
|
@@ -159,12 +150,12 @@ fn callbacks_only_fire_on_change() {
|
|
159
150
|
let cb = CallbackRecorder::new();
|
160
151
|
let mut reactor = Reactor::new();
|
161
152
|
let input = reactor.create_input(1);
|
162
|
-
let output = reactor.create_compute(&[input], |v| if v[0] < 3 { 111 } else { 222 }).unwrap();
|
153
|
+
let output = reactor.create_compute(&[CellID::Input(input)], |v| if v[0] < 3 { 111 } else { 222 }).unwrap();
|
163
154
|
assert!(reactor.add_callback(output, |v| cb.callback_called(v)).is_some());
|
164
155
|
|
165
|
-
assert!(reactor.set_value(input, 2)
|
156
|
+
assert!(reactor.set_value(input, 2));
|
166
157
|
cb.expect_not_to_have_been_called();
|
167
|
-
assert!(reactor.set_value(input, 4)
|
158
|
+
assert!(reactor.set_value(input, 4));
|
168
159
|
cb.expect_to_have_been_called_with(222);
|
169
160
|
}
|
170
161
|
|
@@ -177,19 +168,19 @@ fn callbacks_can_be_added_and_removed() {
|
|
177
168
|
|
178
169
|
let mut reactor = Reactor::new();
|
179
170
|
let input = reactor.create_input(11);
|
180
|
-
let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
|
171
|
+
let output = reactor.create_compute(&[CellID::Input(input)], |v| v[0] + 1).unwrap();
|
181
172
|
|
182
173
|
let callback = reactor.add_callback(output, |v| cb1.callback_called(v)).unwrap();
|
183
174
|
assert!(reactor.add_callback(output, |v| cb2.callback_called(v)).is_some());
|
184
175
|
|
185
|
-
assert!(reactor.set_value(input, 31)
|
176
|
+
assert!(reactor.set_value(input, 31));
|
186
177
|
cb1.expect_to_have_been_called_with(32);
|
187
178
|
cb2.expect_to_have_been_called_with(32);
|
188
179
|
|
189
180
|
assert!(reactor.remove_callback(output, callback).is_ok());
|
190
181
|
assert!(reactor.add_callback(output, |v| cb3.callback_called(v)).is_some());
|
191
182
|
|
192
|
-
assert!(reactor.set_value(input, 41)
|
183
|
+
assert!(reactor.set_value(input, 41));
|
193
184
|
cb1.expect_not_to_have_been_called();
|
194
185
|
cb2.expect_to_have_been_called_with(42);
|
195
186
|
cb3.expect_to_have_been_called_with(42);
|
@@ -203,7 +194,7 @@ fn removing_a_callback_multiple_times_doesnt_interfere_with_other_callbacks() {
|
|
203
194
|
|
204
195
|
let mut reactor = Reactor::new();
|
205
196
|
let input = reactor.create_input(1);
|
206
|
-
let output = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
|
197
|
+
let output = reactor.create_compute(&[CellID::Input(input)], |v| v[0] + 1).unwrap();
|
207
198
|
let callback = reactor.add_callback(output, |v| cb1.callback_called(v)).unwrap();
|
208
199
|
assert!(reactor.add_callback(output, |v| cb2.callback_called(v)).is_some());
|
209
200
|
// We want the first remove to be Ok, but the others should be errors.
|
@@ -212,7 +203,7 @@ fn removing_a_callback_multiple_times_doesnt_interfere_with_other_callbacks() {
|
|
212
203
|
assert_eq!(reactor.remove_callback(output, callback), Err(RemoveCallbackError::NonexistentCallback));
|
213
204
|
}
|
214
205
|
|
215
|
-
assert!(reactor.set_value(input, 2)
|
206
|
+
assert!(reactor.set_value(input, 2));
|
216
207
|
cb1.expect_not_to_have_been_called();
|
217
208
|
cb2.expect_to_have_been_called_with(3);
|
218
209
|
}
|
@@ -223,12 +214,12 @@ fn callbacks_should_only_be_called_once_even_if_multiple_dependencies_change() {
|
|
223
214
|
let cb = CallbackRecorder::new();
|
224
215
|
let mut reactor = Reactor::new();
|
225
216
|
let input = reactor.create_input(1);
|
226
|
-
let plus_one = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
|
227
|
-
let minus_one1 = reactor.create_compute(&[input], |v| v[0] - 1).unwrap();
|
228
|
-
let minus_one2 = reactor.create_compute(&[minus_one1], |v| v[0] - 1).unwrap();
|
229
|
-
let output = reactor.create_compute(&[plus_one, minus_one2], |v| v[0] * v[1]).unwrap();
|
217
|
+
let plus_one = reactor.create_compute(&[CellID::Input(input)], |v| v[0] + 1).unwrap();
|
218
|
+
let minus_one1 = reactor.create_compute(&[CellID::Input(input)], |v| v[0] - 1).unwrap();
|
219
|
+
let minus_one2 = reactor.create_compute(&[CellID::Compute(minus_one1)], |v| v[0] - 1).unwrap();
|
220
|
+
let output = reactor.create_compute(&[CellID::Compute(plus_one), CellID::Compute(minus_one2)], |v| v[0] * v[1]).unwrap();
|
230
221
|
assert!(reactor.add_callback(output, |v| cb.callback_called(v)).is_some());
|
231
|
-
assert!(reactor.set_value(input, 4)
|
222
|
+
assert!(reactor.set_value(input, 4));
|
232
223
|
cb.expect_to_have_been_called_with(10);
|
233
224
|
}
|
234
225
|
|
@@ -238,12 +229,12 @@ fn callbacks_should_not_be_called_if_dependencies_change_but_output_value_doesnt
|
|
238
229
|
let cb = CallbackRecorder::new();
|
239
230
|
let mut reactor = Reactor::new();
|
240
231
|
let input = reactor.create_input(1);
|
241
|
-
let plus_one = reactor.create_compute(&[input], |v| v[0] + 1).unwrap();
|
242
|
-
let minus_one = reactor.create_compute(&[input], |v| v[0] - 1).unwrap();
|
243
|
-
let always_two = reactor.create_compute(&[plus_one, minus_one], |v| v[0] - v[1]).unwrap();
|
232
|
+
let plus_one = reactor.create_compute(&[CellID::Input(input)], |v| v[0] + 1).unwrap();
|
233
|
+
let minus_one = reactor.create_compute(&[CellID::Input(input)], |v| v[0] - 1).unwrap();
|
234
|
+
let always_two = reactor.create_compute(&[CellID::Compute(plus_one), CellID::Compute(minus_one)], |v| v[0] - v[1]).unwrap();
|
244
235
|
assert!(reactor.add_callback(always_two, |v| cb.callback_called(v)).is_some());
|
245
236
|
for i in 2..5 {
|
246
|
-
assert!(reactor.set_value(input, i)
|
237
|
+
assert!(reactor.set_value(input, i));
|
247
238
|
cb.expect_not_to_have_been_called();
|
248
239
|
}
|
249
240
|
}
|
@@ -258,12 +249,12 @@ fn test_adder_with_boolean_values() {
|
|
258
249
|
let b = reactor.create_input(false);
|
259
250
|
let carry_in = reactor.create_input(false);
|
260
251
|
|
261
|
-
let a_xor_b = reactor.create_compute(&[a, b], |v| v[0] ^ v[1]).unwrap();
|
262
|
-
let sum = reactor.create_compute(&[a_xor_b, carry_in], |v| v[0] ^ v[1]).unwrap();
|
252
|
+
let a_xor_b = reactor.create_compute(&[CellID::Input(a), CellID::Input(b)], |v| v[0] ^ v[1]).unwrap();
|
253
|
+
let sum = reactor.create_compute(&[CellID::Compute(a_xor_b), CellID::Input(carry_in)], |v| v[0] ^ v[1]).unwrap();
|
263
254
|
|
264
|
-
let a_xor_b_and_cin = reactor.create_compute(&[a_xor_b, carry_in], |v| v[0] && v[1]).unwrap();
|
265
|
-
let a_and_b = reactor.create_compute(&[a, b], |v| v[0] && v[1]).unwrap();
|
266
|
-
let carry_out = reactor.create_compute(&[a_xor_b_and_cin, a_and_b], |v| v[0] || v[1]).unwrap();
|
255
|
+
let a_xor_b_and_cin = reactor.create_compute(&[CellID::Compute(a_xor_b), CellID::Input(carry_in)], |v| v[0] && v[1]).unwrap();
|
256
|
+
let a_and_b = reactor.create_compute(&[CellID::Input(a), CellID::Input(b)], |v| v[0] && v[1]).unwrap();
|
257
|
+
let carry_out = reactor.create_compute(&[CellID::Compute(a_xor_b_and_cin), CellID::Compute(a_and_b)], |v| v[0] || v[1]).unwrap();
|
267
258
|
|
268
259
|
let tests = &[
|
269
260
|
(false, false, false, false, false),
|
@@ -277,11 +268,11 @@ fn test_adder_with_boolean_values() {
|
|
277
268
|
];
|
278
269
|
|
279
270
|
for &(aval, bval, cinval, expected_cout, expected_sum) in tests {
|
280
|
-
assert!(reactor.set_value(a, aval)
|
281
|
-
assert!(reactor.set_value(b, bval)
|
282
|
-
assert!(reactor.set_value(carry_in, cinval)
|
271
|
+
assert!(reactor.set_value(a, aval));
|
272
|
+
assert!(reactor.set_value(b, bval));
|
273
|
+
assert!(reactor.set_value(carry_in, cinval));
|
283
274
|
|
284
|
-
assert_eq!(reactor.value(sum), Some(expected_sum));
|
285
|
-
assert_eq!(reactor.value(carry_out), Some(expected_cout));
|
275
|
+
assert_eq!(reactor.value(CellID::Compute(sum)), Some(expected_sum));
|
276
|
+
assert_eq!(reactor.value(CellID::Compute(carry_out)), Some(expected_cout));
|
286
277
|
}
|
287
278
|
}
|
data/tracks/swift/config.json
CHANGED
@@ -438,6 +438,17 @@
|
|
438
438
|
"loops"
|
439
439
|
]
|
440
440
|
},
|
441
|
+
{
|
442
|
+
"core": false,
|
443
|
+
"difficulty": 3,
|
444
|
+
"slug": "proverb",
|
445
|
+
"topics": [
|
446
|
+
"algorithms",
|
447
|
+
"strings"
|
448
|
+
],
|
449
|
+
"unlocked_by": null,
|
450
|
+
"uuid": "9604f1ef-4925-4c28-9c59-b986c1a42c7e"
|
451
|
+
},
|
441
452
|
{
|
442
453
|
"core": false,
|
443
454
|
"difficulty": 4,
|
@@ -10,29 +10,29 @@ struct CircularBuffer<T: Equatable> {
|
|
10
10
|
let capacity: Int
|
11
11
|
var writePoint = 0
|
12
12
|
var readPoint = 0
|
13
|
-
|
13
|
+
|
14
14
|
private var isFull: Bool {
|
15
15
|
return buffer.flatMap { $0 }.count >= capacity
|
16
16
|
}
|
17
|
-
|
17
|
+
|
18
18
|
private var isEmpty: Bool {
|
19
19
|
return buffer.flatMap { $0 }.isEmpty
|
20
20
|
}
|
21
|
-
|
21
|
+
|
22
22
|
init(capacity: Int) {
|
23
23
|
self.capacity = capacity
|
24
24
|
buffer = [T?](repeating: nil, count: capacity)
|
25
25
|
}
|
26
|
-
|
26
|
+
|
27
27
|
mutating func write(_ data: T) throws {
|
28
28
|
guard !isFull else {
|
29
29
|
throw CircularBufferError.bufferFull
|
30
30
|
}
|
31
|
-
|
31
|
+
|
32
32
|
buffer[writePoint] = data
|
33
33
|
updateWritePoint()
|
34
34
|
}
|
35
|
-
|
35
|
+
|
36
36
|
mutating func overwrite(_ data: T) {
|
37
37
|
buffer[writePoint] = data
|
38
38
|
if isFull && writePoint == readPoint {
|
@@ -40,26 +40,26 @@ struct CircularBuffer<T: Equatable> {
|
|
40
40
|
}
|
41
41
|
updateWritePoint()
|
42
42
|
}
|
43
|
-
|
43
|
+
|
44
44
|
mutating func read() throws -> T {
|
45
45
|
guard let data = buffer[readPoint] else {
|
46
46
|
throw CircularBufferError.bufferEmpty
|
47
47
|
}
|
48
|
-
|
48
|
+
|
49
49
|
buffer[readPoint] = nil
|
50
50
|
updateReadPoint()
|
51
|
-
|
51
|
+
|
52
52
|
return data
|
53
53
|
}
|
54
|
-
|
54
|
+
|
55
55
|
mutating func clear() {
|
56
56
|
buffer = [T?](repeating: nil, count: capacity)
|
57
57
|
}
|
58
|
-
|
58
|
+
|
59
59
|
private mutating func updateWritePoint() {
|
60
60
|
writePoint = (writePoint + 1) % capacity
|
61
61
|
}
|
62
|
-
|
62
|
+
|
63
63
|
private mutating func updateReadPoint() {
|
64
64
|
readPoint = (readPoint + 1) % capacity
|
65
65
|
}
|