trackler 2.2.1.135 → 2.2.1.136

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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/problem-specifications/exercises/pov/canonical-data.json +33 -1
  4. data/tracks/c/exercises/acronym/test/test_acronym.c +25 -17
  5. data/tracks/csharp/exercises/binary-search-tree/BinarySearchTreeTest.cs +37 -28
  6. data/tracks/csharp/generators/Exercises/BinarySearchTree.cs +69 -0
  7. data/tracks/haskell/config.json +1 -0
  8. data/tracks/haskell/exercises/accumulate/package.yaml +1 -1
  9. data/tracks/haskell/exercises/acronym/package.yaml +1 -1
  10. data/tracks/haskell/exercises/all-your-base/package.yaml +1 -1
  11. data/tracks/haskell/exercises/allergies/package.yaml +1 -1
  12. data/tracks/haskell/exercises/alphametics/package.yaml +1 -1
  13. data/tracks/haskell/exercises/anagram/package.yaml +1 -1
  14. data/tracks/haskell/exercises/atbash-cipher/package.yaml +1 -1
  15. data/tracks/haskell/exercises/bank-account/package.yaml +1 -1
  16. data/tracks/haskell/exercises/beer-song/package.yaml +1 -1
  17. data/tracks/haskell/exercises/binary-search-tree/package.yaml +1 -1
  18. data/tracks/haskell/exercises/binary/package.yaml +1 -1
  19. data/tracks/haskell/exercises/bob/package.yaml +1 -1
  20. data/tracks/haskell/exercises/bowling/package.yaml +1 -1
  21. data/tracks/haskell/exercises/bracket-push/package.yaml +1 -1
  22. data/tracks/haskell/exercises/change/package.yaml +1 -1
  23. data/tracks/haskell/exercises/clock/package.yaml +1 -1
  24. data/tracks/haskell/exercises/collatz-conjecture/package.yaml +1 -1
  25. data/tracks/haskell/exercises/complex-numbers/package.yaml +1 -1
  26. data/tracks/haskell/exercises/connect/package.yaml +1 -1
  27. data/tracks/haskell/exercises/crypto-square/package.yaml +1 -1
  28. data/tracks/haskell/exercises/custom-set/package.yaml +1 -1
  29. data/tracks/haskell/exercises/diamond/package.yaml +1 -1
  30. data/tracks/haskell/exercises/difference-of-squares/package.yaml +1 -1
  31. data/tracks/haskell/exercises/dominoes/package.yaml +1 -1
  32. data/tracks/haskell/exercises/etl/package.yaml +1 -1
  33. data/tracks/haskell/exercises/food-chain/package.yaml +1 -1
  34. data/tracks/haskell/exercises/forth/package.yaml +1 -1
  35. data/tracks/haskell/exercises/gigasecond/package.yaml +1 -1
  36. data/tracks/haskell/exercises/go-counting/package.yaml +1 -1
  37. data/tracks/haskell/exercises/grade-school/package.yaml +1 -1
  38. data/tracks/haskell/exercises/grains/package.yaml +1 -1
  39. data/tracks/haskell/exercises/hamming/package.yaml +1 -1
  40. data/tracks/haskell/exercises/hello-world/package.yaml +1 -1
  41. data/tracks/haskell/exercises/hexadecimal/package.yaml +1 -1
  42. data/tracks/haskell/exercises/house/package.yaml +1 -1
  43. data/tracks/haskell/exercises/isbn-verifier/package.yaml +1 -1
  44. data/tracks/haskell/exercises/isogram/package.yaml +1 -1
  45. data/tracks/haskell/exercises/kindergarten-garden/examples/success-standard/src/Garden.hs +1 -10
  46. data/tracks/haskell/exercises/kindergarten-garden/package.yaml +2 -3
  47. data/tracks/haskell/exercises/kindergarten-garden/src/Garden.hs +3 -7
  48. data/tracks/haskell/exercises/kindergarten-garden/test/Tests.hs +10 -16
  49. data/tracks/haskell/exercises/largest-series-product/package.yaml +1 -1
  50. data/tracks/haskell/exercises/leap/package.yaml +1 -1
  51. data/tracks/haskell/exercises/lens-person/examples/success-standard/package.yaml +0 -1
  52. data/tracks/haskell/exercises/lens-person/package.yaml +1 -1
  53. data/tracks/haskell/exercises/linked-list/package.yaml +1 -1
  54. data/tracks/haskell/exercises/list-ops/package.yaml +1 -1
  55. data/tracks/haskell/exercises/luhn/package.yaml +1 -1
  56. data/tracks/haskell/exercises/matrix/package.yaml +1 -1
  57. data/tracks/haskell/exercises/meetup/package.yaml +1 -1
  58. data/tracks/haskell/exercises/minesweeper/package.yaml +1 -1
  59. data/tracks/haskell/exercises/nth-prime/package.yaml +1 -1
  60. data/tracks/haskell/exercises/nucleotide-count/package.yaml +1 -1
  61. data/tracks/haskell/exercises/ocr-numbers/package.yaml +1 -1
  62. data/tracks/haskell/exercises/octal/package.yaml +1 -1
  63. data/tracks/haskell/exercises/palindrome-products/package.yaml +1 -1
  64. data/tracks/haskell/exercises/pangram/package.yaml +1 -1
  65. data/tracks/haskell/exercises/parallel-letter-frequency/package.yaml +1 -1
  66. data/tracks/haskell/exercises/pascals-triangle/package.yaml +1 -1
  67. data/tracks/haskell/exercises/perfect-numbers/package.yaml +1 -1
  68. data/tracks/haskell/exercises/phone-number/package.yaml +1 -1
  69. data/tracks/haskell/exercises/pig-latin/package.yaml +1 -1
  70. data/tracks/haskell/exercises/poker/package.yaml +1 -1
  71. data/tracks/haskell/exercises/pov/package.yaml +2 -2
  72. data/tracks/haskell/exercises/pov/test/Tests.hs +15 -0
  73. data/tracks/haskell/exercises/prime-factors/package.yaml +1 -1
  74. data/tracks/haskell/exercises/protein-translation/package.yaml +1 -1
  75. data/tracks/haskell/exercises/pythagorean-triplet/package.yaml +1 -1
  76. data/tracks/haskell/exercises/queen-attack/package.yaml +1 -1
  77. data/tracks/haskell/exercises/rail-fence-cipher/package.yaml +1 -1
  78. data/tracks/haskell/exercises/raindrops/package.yaml +1 -1
  79. data/tracks/haskell/exercises/rna-transcription/package.yaml +1 -1
  80. data/tracks/haskell/exercises/robot-name/package.yaml +1 -1
  81. data/tracks/haskell/exercises/robot-simulator/package.yaml +1 -1
  82. data/tracks/haskell/exercises/roman-numerals/package.yaml +1 -1
  83. data/tracks/haskell/exercises/rotational-cipher/package.yaml +1 -1
  84. data/tracks/haskell/exercises/run-length-encoding/package.yaml +1 -1
  85. data/tracks/haskell/exercises/saddle-points/package.yaml +1 -1
  86. data/tracks/haskell/exercises/say/package.yaml +1 -1
  87. data/tracks/haskell/exercises/scrabble-score/package.yaml +1 -1
  88. data/tracks/haskell/exercises/secret-handshake/package.yaml +1 -1
  89. data/tracks/haskell/exercises/series/package.yaml +1 -1
  90. data/tracks/haskell/exercises/sgf-parsing/package.yaml +1 -1
  91. data/tracks/haskell/exercises/sieve/package.yaml +1 -1
  92. data/tracks/haskell/exercises/simple-cipher/package.yaml +1 -1
  93. data/tracks/haskell/exercises/simple-linked-list/package.yaml +1 -1
  94. data/tracks/haskell/exercises/space-age/package.yaml +1 -1
  95. data/tracks/haskell/exercises/spiral-matrix/package.yaml +1 -1
  96. data/tracks/haskell/exercises/strain/package.yaml +1 -1
  97. data/tracks/haskell/exercises/sublist/package.yaml +1 -1
  98. data/tracks/haskell/exercises/sum-of-multiples/package.yaml +1 -1
  99. data/tracks/haskell/exercises/transpose/package.yaml +1 -1
  100. data/tracks/haskell/exercises/triangle/package.yaml +1 -1
  101. data/tracks/haskell/exercises/trinary/package.yaml +1 -1
  102. data/tracks/haskell/exercises/twelve-days/package.yaml +1 -1
  103. data/tracks/haskell/exercises/word-count/package.yaml +1 -1
  104. data/tracks/haskell/exercises/wordy/package.yaml +1 -1
  105. data/tracks/haskell/exercises/zebra-puzzle/package.yaml +1 -1
  106. data/tracks/haskell/exercises/zipper/package.yaml +1 -1
  107. data/tracks/java/CONTRIBUTING.md +39 -3
  108. data/tracks/java/POLICIES.md +68 -3
  109. data/tracks/java/exercises/crypto-square/README.md +4 -5
  110. data/tracks/java/exercises/error-handling/README.md +38 -0
  111. data/tracks/java/exercises/series/README.md +6 -6
  112. data/tracks/java/exercises/sieve/README.md +5 -3
  113. data/tracks/java/scripts/canonical_data_check.sh +1 -1
  114. data/tracks/python/exercises/react/example.py +54 -63
  115. data/tracks/python/exercises/react/react.py +10 -10
  116. data/tracks/python/exercises/react/react_test.py +197 -131
  117. data/tracks/python/exercises/sieve/README.md +5 -3
  118. data/tracks/rust/exercises/react/example.rs +103 -64
  119. data/tracks/rust/exercises/react/src/lib.rs +31 -17
  120. data/tracks/rust/exercises/react/tests/react.rs +52 -61
  121. data/tracks/swift/config.json +11 -0
  122. data/tracks/swift/exercises/circular-buffer/Sources/CircularBufferExample.swift +12 -12
  123. data/tracks/swift/exercises/circular-buffer/Tests/CircularBufferTests/CircularBufferTests.swift +1 -1
  124. data/tracks/swift/exercises/proverb/Package.swift +5 -0
  125. data/tracks/swift/exercises/proverb/README.md +25 -0
  126. data/tracks/swift/exercises/proverb/Sources/Proverb.swift +1 -0
  127. data/tracks/swift/exercises/proverb/Sources/ProverbExample.swift +28 -0
  128. data/tracks/swift/exercises/proverb/Tests/LinuxMain.swift +6 -0
  129. data/tracks/swift/exercises/proverb/Tests/ProverbTests/ProverbTests.swift +61 -0
  130. data/tracks/typescript/config.json +14 -0
  131. data/tracks/typescript/exercises/palindrome-products/README.md +65 -0
  132. data/tracks/typescript/exercises/palindrome-products/package.json +36 -0
  133. data/tracks/typescript/exercises/palindrome-products/palindrome-products.example.ts +38 -0
  134. data/tracks/typescript/exercises/palindrome-products/palindrome-products.test.ts +69 -0
  135. data/tracks/typescript/exercises/palindrome-products/palindrome-products.ts +0 -0
  136. data/tracks/typescript/exercises/palindrome-products/tsconfig.json +22 -0
  137. data/tracks/typescript/exercises/palindrome-products/tslint.json +127 -0
  138. data/tracks/typescript/exercises/palindrome-products/yarn.lock +2624 -0
  139. metadata +17 -2
@@ -1,12 +1,29 @@
1
- // Because these are passed without & to some functions,
2
- // it will probably be necessary for these two types to be Copy.
3
- pub type CellID = ();
4
- pub type CallbackID = ();
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 SetValueError {
8
- NonexistentCell,
9
- ComputeCell,
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) -> CellID {
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<CellID, CellID> {
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 an Err if either:
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: CellID, _new_value: T) -> Result<(), SetValueError> {
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: CellID, _callback: F) -> Option<CallbackID> {
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: CellID, callback: CallbackID) -> Result<(), RemoveCallbackError> {
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).is_ok());
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
- assert_eq!(Reactor::new().set_value(input, 0), Err(SetValueError::NonexistentCell));
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).is_ok());
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).is_ok());
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).is_ok());
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).is_ok());
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).is_ok());
156
+ assert!(reactor.set_value(input, 2));
166
157
  cb.expect_not_to_have_been_called();
167
- assert!(reactor.set_value(input, 4).is_ok());
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).is_ok());
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).is_ok());
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).is_ok());
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).is_ok());
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).is_ok());
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).is_ok());
281
- assert!(reactor.set_value(b, bval).is_ok());
282
- assert!(reactor.set_value(carry_in, cinval).is_ok());
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
  }
@@ -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
  }
@@ -2,7 +2,7 @@ import XCTest
2
2
  @testable import CircularBuffer
3
3
 
4
4
  class CircularBufferTests: XCTestCase {
5
-
5
+
6
6
  func testReadEmptyBufferThrowsBufferEmptyException() {
7
7
  var buffer = CircularBuffer<Int>(capacity: 1)
8
8
 
@@ -0,0 +1,5 @@
1
+ import PackageDescription
2
+
3
+ let package = Package(
4
+ name: "Proverb"
5
+ )