trackler 2.2.1.127 → 2.2.1.128

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/c/docs/RESOURCES.md +0 -1
  4. data/tracks/delphi/exercises/isbn-verifier/uTestISBNVerifier.pas +2 -2
  5. data/tracks/ecmascript/config.json +2 -2
  6. data/tracks/elm/config/maintainers.json +11 -11
  7. data/tracks/elm/config.json +170 -245
  8. data/tracks/fsharp/exercises/pov/PovTest.fs +1 -1
  9. data/tracks/java/exercises/queen-attack/.meta/src/reference/java/Queen.java +38 -0
  10. data/tracks/java/exercises/queen-attack/.meta/src/reference/java/QueenAttackCalculator.java +11 -12
  11. data/tracks/java/exercises/queen-attack/.meta/version +1 -1
  12. data/tracks/java/exercises/queen-attack/src/test/java/QueenAttackCalculatorTest.java +50 -44
  13. data/tracks/python/config.json +26 -0
  14. data/tracks/python/exercises/bank-account/README.md +53 -0
  15. data/tracks/python/exercises/bank-account/bank_account.py +18 -0
  16. data/tracks/python/exercises/bank-account/bank_account_test.py +120 -0
  17. data/tracks/python/exercises/bank-account/example.py +35 -0
  18. data/tracks/python/exercises/go-counting/example.py +6 -6
  19. data/tracks/python/exercises/go-counting/go_counting.py +3 -2
  20. data/tracks/python/exercises/go-counting/go_counting_test.py +58 -51
  21. data/tracks/python/exercises/house/example.py +7 -13
  22. data/tracks/python/exercises/house/house_test.py +79 -204
  23. data/tracks/python/exercises/meetup/example.py +10 -1
  24. data/tracks/python/exercises/meetup/meetup_test.py +1 -6
  25. data/tracks/python/exercises/pascals-triangle/example.py +12 -14
  26. data/tracks/python/exercises/pascals-triangle/pascals_triangle.py +1 -9
  27. data/tracks/python/exercises/pascals-triangle/pascals_triangle_test.py +43 -29
  28. data/tracks/python/exercises/sgf-parsing/README.md +110 -0
  29. data/tracks/python/exercises/sgf-parsing/example.py +100 -0
  30. data/tracks/python/exercises/sgf-parsing/sgf_parsing.py +26 -0
  31. data/tracks/python/exercises/sgf-parsing/sgf_parsing_test.py +94 -0
  32. data/tracks/typescript/config.json +1 -1
  33. data/tracks/typescript/exercises/pangram/pangram.example.ts +2 -2
  34. data/tracks/typescript/exercises/pangram/pangram.test.ts +0 -2
  35. data/tracks/typescript/exercises/pangram/pangram.ts +0 -11
  36. metadata +11 -3
  37. data/tracks/java/exercises/queen-attack/.meta/src/reference/java/BoardCoordinate.java +0 -39
@@ -1,14 +1,13 @@
1
1
  final class QueenAttackCalculator {
2
2
 
3
- private final BoardCoordinate whiteQueenCoordinate;
3
+ private final Queen whiteQueen;
4
4
 
5
- private final BoardCoordinate blackQueenCoordinate;
5
+ private final Queen blackQueen;
6
6
 
7
- QueenAttackCalculator(final BoardCoordinate whiteQueenCoordinate, final BoardCoordinate blackQueenCoordinate)
8
- throws IllegalArgumentException {
7
+ QueenAttackCalculator(final Queen whiteQueen, final Queen blackQueen) {
9
8
 
10
- this.whiteQueenCoordinate = whiteQueenCoordinate;
11
- this.blackQueenCoordinate = blackQueenCoordinate;
9
+ this.whiteQueen = whiteQueen;
10
+ this.blackQueen = blackQueen;
12
11
 
13
12
  validateInputs();
14
13
  }
@@ -17,13 +16,13 @@ final class QueenAttackCalculator {
17
16
  return queensShareColumn() || queensShareRow() || queensShareDiagonal();
18
17
  }
19
18
 
20
- private void validateInputs() throws IllegalArgumentException {
21
- if (whiteQueenCoordinate == null || blackQueenCoordinate == null) {
22
- throw new IllegalArgumentException("You must supply valid board coordinates for both Queens.");
19
+ private void validateInputs() {
20
+ if (whiteQueen == null || blackQueen == null) {
21
+ throw new IllegalArgumentException("You must supply valid positions for both Queens.");
23
22
  }
24
23
 
25
24
  if (queensShareBoardCoordinate()) {
26
- throw new IllegalArgumentException("Queens may not occupy the same board coordinate.");
25
+ throw new IllegalArgumentException("Queens cannot occupy the same position.");
27
26
  }
28
27
  }
29
28
 
@@ -44,11 +43,11 @@ final class QueenAttackCalculator {
44
43
  }
45
44
 
46
45
  private int differenceBetweenRows() {
47
- return Math.abs(whiteQueenCoordinate.getRow() - blackQueenCoordinate.getRow());
46
+ return Math.abs(whiteQueen.getRow() - blackQueen.getRow());
48
47
  }
49
48
 
50
49
  private int differenceBetweenColumns() {
51
- return Math.abs(whiteQueenCoordinate.getColumn() - blackQueenCoordinate.getColumn());
50
+ return Math.abs(whiteQueen.getColumn() - blackQueen.getColumn());
52
51
  }
53
52
 
54
53
  }
@@ -1 +1 @@
1
- 2.0.0
1
+ 2.1.0
@@ -12,119 +12,125 @@ public class QueenAttackCalculatorTest {
12
12
  public ExpectedException expectedException = ExpectedException.none();
13
13
 
14
14
  @Test
15
- public void testQueensThatDoNotShareRowColumnOrDiagonalCannotAttack() {
16
- final QueenAttackCalculator calculator
17
- = new QueenAttackCalculator(new BoardCoordinate(2, 4), new BoardCoordinate(6, 6));
15
+ public void testCreateQueenWithAValidPosition() {
16
+ new Queen(2, 2);
17
+ }
18
18
 
19
- assertFalse(calculator.canQueensAttackOneAnother());
19
+ @Ignore("Remove to run test")
20
+ @Test
21
+ public void testCreateQueenMustHavePositiveRow() {
22
+ expectedException.expect(IllegalArgumentException.class);
23
+ expectedException.expectMessage("Queen position must have positive row.");
24
+
25
+ new Queen(-2, 2);
20
26
  }
21
27
 
22
28
  @Ignore("Remove to run test")
23
29
  @Test
24
- public void testQueensCanAttackOnTheSameRow() {
25
- final QueenAttackCalculator calculator
26
- = new QueenAttackCalculator(new BoardCoordinate(2, 4), new BoardCoordinate(2, 6));
30
+ public void testCreateQueenMustHaveRowOnBoard() {
31
+ expectedException.expect(IllegalArgumentException.class);
32
+ expectedException.expectMessage("Queen position must have row <= 7.");
27
33
 
28
- assertTrue(calculator.canQueensAttackOneAnother());
34
+ new Queen(8, 4);
29
35
  }
30
36
 
31
37
  @Ignore("Remove to run test")
32
38
  @Test
33
- public void testQueensCanAttackOnTheSameColumn() {
34
- final QueenAttackCalculator calculator
35
- = new QueenAttackCalculator(new BoardCoordinate(4, 5), new BoardCoordinate(2, 5));
39
+ public void testCreateQueenMustHavePositiveColumn() {
40
+ expectedException.expect(IllegalArgumentException.class);
41
+ expectedException.expectMessage("Queen position must have positive column.");
36
42
 
37
- assertTrue(calculator.canQueensAttackOneAnother());
43
+ new Queen(2, -2);
38
44
  }
39
45
 
40
46
  @Ignore("Remove to run test")
41
47
  @Test
42
- public void testQueensCanAttackOnFirstDiagonal() {
43
- final QueenAttackCalculator calculator
44
- = new QueenAttackCalculator(new BoardCoordinate(2, 2), new BoardCoordinate(0, 4));
48
+ public void testCreateQueenMustHaveColumnOnBoard() {
49
+ expectedException.expect(IllegalArgumentException.class);
50
+ expectedException.expectMessage("Queen position must have column <= 7.");
45
51
 
46
- assertTrue(calculator.canQueensAttackOneAnother());
52
+ new Queen(4, 8);
47
53
  }
48
54
 
49
55
  @Ignore("Remove to run test")
50
56
  @Test
51
- public void testQueensCanAttackOnSecondDiagonal() {
57
+ public void testQueensCannotAttack() {
52
58
  final QueenAttackCalculator calculator
53
- = new QueenAttackCalculator(new BoardCoordinate(2, 2), new BoardCoordinate(3, 1));
59
+ = new QueenAttackCalculator(new Queen(2, 4), new Queen(6, 6));
54
60
 
55
- assertTrue(calculator.canQueensAttackOneAnother());
61
+ assertFalse(calculator.canQueensAttackOneAnother());
56
62
  }
57
63
 
58
64
  @Ignore("Remove to run test")
59
65
  @Test
60
- public void testQueensCanAttackOnThirdDiagonal() {
66
+ public void testQueensCanAttackOnTheSameRow() {
61
67
  final QueenAttackCalculator calculator
62
- = new QueenAttackCalculator(new BoardCoordinate(2, 2), new BoardCoordinate(1, 1));
68
+ = new QueenAttackCalculator(new Queen(2, 4), new Queen(2, 6));
63
69
 
64
70
  assertTrue(calculator.canQueensAttackOneAnother());
65
71
  }
66
72
 
67
73
  @Ignore("Remove to run test")
68
74
  @Test
69
- public void testQueensCanAttackOnFourthDiagonal() {
75
+ public void testQueensCanAttackOnTheSameColumn() {
70
76
  final QueenAttackCalculator calculator
71
- = new QueenAttackCalculator(new BoardCoordinate(2, 2), new BoardCoordinate(5, 5));
77
+ = new QueenAttackCalculator(new Queen(4, 5), new Queen(2, 5));
72
78
 
73
79
  assertTrue(calculator.canQueensAttackOneAnother());
74
80
  }
75
81
 
76
82
  @Ignore("Remove to run test")
77
83
  @Test
78
- public void testCoordinateWithNegativeRowNotAllowed() {
79
- expectedException.expect(IllegalArgumentException.class);
80
- expectedException.expectMessage("Coordinate must have positive row.");
84
+ public void testQueensCanAttackOnFirstDiagonal() {
85
+ final QueenAttackCalculator calculator
86
+ = new QueenAttackCalculator(new Queen(2, 2), new Queen(0, 4));
81
87
 
82
- new BoardCoordinate(-2, 2);
88
+ assertTrue(calculator.canQueensAttackOneAnother());
83
89
  }
84
90
 
85
91
  @Ignore("Remove to run test")
86
92
  @Test
87
- public void testCoordinateWithRowGreaterThan7NotAllowed() {
88
- expectedException.expect(IllegalArgumentException.class);
89
- expectedException.expectMessage("Coordinate must have row <= 7.");
93
+ public void testQueensCanAttackOnSecondDiagonal() {
94
+ final QueenAttackCalculator calculator
95
+ = new QueenAttackCalculator(new Queen(2, 2), new Queen(3, 1));
90
96
 
91
- new BoardCoordinate(8, 4);
97
+ assertTrue(calculator.canQueensAttackOneAnother());
92
98
  }
93
99
 
94
100
  @Ignore("Remove to run test")
95
101
  @Test
96
- public void testCoordinateWithNegativeColumnNotAllowed() {
97
- expectedException.expect(IllegalArgumentException.class);
98
- expectedException.expectMessage("Coordinate must have positive column.");
102
+ public void testQueensCanAttackOnThirdDiagonal() {
103
+ final QueenAttackCalculator calculator
104
+ = new QueenAttackCalculator(new Queen(2, 2), new Queen(1, 1));
99
105
 
100
- new BoardCoordinate(2, -2);
106
+ assertTrue(calculator.canQueensAttackOneAnother());
101
107
  }
102
108
 
103
109
  @Ignore("Remove to run test")
104
110
  @Test
105
- public void testCoordinateWithColumnGreaterThan7NotAllowed() {
106
- expectedException.expect(IllegalArgumentException.class);
107
- expectedException.expectMessage("Coordinate must have column <= 7.");
111
+ public void testQueensCanAttackOnFourthDiagonal() {
112
+ final QueenAttackCalculator calculator
113
+ = new QueenAttackCalculator(new Queen(2, 2), new Queen(5, 5));
108
114
 
109
- new BoardCoordinate(4, 8);
115
+ assertTrue(calculator.canQueensAttackOneAnother());
110
116
  }
111
117
 
112
118
  @Ignore("Remove to run test")
113
119
  @Test
114
- public void testNullCoordinateNotAllowed() {
120
+ public void testNullPositionsNotAllowed() {
115
121
  expectedException.expect(IllegalArgumentException.class);
116
- expectedException.expectMessage("You must supply valid board coordinates for both Queens.");
122
+ expectedException.expectMessage("You must supply valid positions for both Queens.");
117
123
 
118
- new QueenAttackCalculator(null, new BoardCoordinate(0, 7));
124
+ new QueenAttackCalculator(null, new Queen(0, 7));
119
125
  }
120
126
 
121
127
  @Ignore("Remove to run test")
122
128
  @Test
123
129
  public void testQueensMustNotOccupyTheSameSquare() {
124
130
  expectedException.expect(IllegalArgumentException.class);
125
- expectedException.expectMessage("Queens may not occupy the same board coordinate.");
131
+ expectedException.expectMessage("Queens cannot occupy the same position.");
126
132
 
127
- new QueenAttackCalculator(new BoardCoordinate(2, 2), new BoardCoordinate(2, 2));
133
+ new QueenAttackCalculator(new Queen(2, 2), new Queen(2, 2));
128
134
  }
129
135
 
130
136
  }
@@ -666,6 +666,18 @@
666
666
  "transforming"
667
667
  ]
668
668
  },
669
+ {
670
+ "uuid": "83a3ff95-c043-401c-bc2c-547d52344b02",
671
+ "slug": "bank-account",
672
+ "core": false,
673
+ "unlocked_by": null,
674
+ "difficulty": 4,
675
+ "topics": [
676
+ "classes",
677
+ "concurrency",
678
+ "conditionals"
679
+ ]
680
+ },
669
681
  {
670
682
  "uuid": "d41238ce-359c-4a9a-81ea-ca5d2c4bb50d",
671
683
  "slug": "twelve-days",
@@ -1305,6 +1317,17 @@
1305
1317
  "lists"
1306
1318
  ]
1307
1319
  },
1320
+ {
1321
+ "uuid": "0d6325d1-c0a3-456e-9a92-cea0559e82ed",
1322
+ "slug": "sgf-parsing",
1323
+ "core": false,
1324
+ "unlocked_by": null,
1325
+ "difficulty": 7,
1326
+ "topics": [
1327
+ "parsing",
1328
+ "trees"
1329
+ ]
1330
+ },
1308
1331
  {
1309
1332
  "uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
1310
1333
  "slug": "accumulate",
@@ -1365,5 +1388,8 @@
1365
1388
  "slug": "parallel-letter-frequency",
1366
1389
  "deprecated": true
1367
1390
  }
1391
+ ],
1392
+ "foregone": [
1393
+ "lens-person"
1368
1394
  ]
1369
1395
  }
@@ -0,0 +1,53 @@
1
+ # Bank Account
2
+
3
+ Simulate a bank account supporting opening/closing, withdrawals, and deposits
4
+ of money. Watch out for concurrent transactions!
5
+
6
+ A bank account can be accessed in multiple ways. Clients can make
7
+ deposits and withdrawals using the internet, mobile phones, etc. Shops
8
+ can charge against the account.
9
+
10
+ Create an account that can be accessed from multiple threads/processes
11
+ (terminology depends on your programming language).
12
+
13
+ It should be possible to close an account; operations against a closed
14
+ account must fail.
15
+
16
+ ## Instructions
17
+
18
+ Run the test file, and fix each of the errors in turn. When you get the
19
+ first test to pass, go to the first pending or skipped test, and make
20
+ that pass as well. When all of the tests are passing, feel free to
21
+ submit.
22
+
23
+ Remember that passing code is just the first step. The goal is to work
24
+ towards a solution that is as readable and expressive as you can make
25
+ it.
26
+
27
+ Have fun!
28
+
29
+ ## Exception messages
30
+
31
+ Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
32
+ indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
33
+ every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
34
+ a message.
35
+
36
+ To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
37
+ `raise Exception`, you shold write:
38
+
39
+ ```python
40
+ raise Exception("Meaningful message indicating the source of the error")
41
+ ```
42
+
43
+ ## Submitting Exercises
44
+
45
+ Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/bank-account` directory.
46
+
47
+ You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`.
48
+
49
+ For more detailed information about running tests, code style and linting,
50
+ please see the [help page](http://exercism.io/languages/python).
51
+
52
+ ## Submitting Incomplete Solutions
53
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,18 @@
1
+ class BankAccount(object):
2
+ def __init__(self):
3
+ pass
4
+
5
+ def get_balance(self):
6
+ pass
7
+
8
+ def open(self):
9
+ pass
10
+
11
+ def deposit(self, amount):
12
+ pass
13
+
14
+ def withdraw(self, amount):
15
+ pass
16
+
17
+ def close(self):
18
+ pass
@@ -0,0 +1,120 @@
1
+ import sys
2
+ import threading
3
+ import time
4
+ import unittest
5
+
6
+ from bank_account import BankAccount
7
+
8
+
9
+ class BankAccountTests(unittest.TestCase):
10
+
11
+ def setUp(self):
12
+ self.account = BankAccount()
13
+
14
+ def test_newly_opened_account_has_zero_balance(self):
15
+ self.account.open()
16
+ self.assertEqual(self.account.get_balance(), 0)
17
+
18
+ def test_can_deposit_money(self):
19
+ self.account.open()
20
+ self.account.deposit(100)
21
+ self.assertEqual(self.account.get_balance(), 100)
22
+
23
+ def test_can_deposit_money_sequentially(self):
24
+ self.account.open()
25
+ self.account.deposit(100)
26
+ self.account.deposit(50)
27
+
28
+ self.assertEqual(self.account.get_balance(), 150)
29
+
30
+ def test_can_withdraw_money(self):
31
+ self.account.open()
32
+ self.account.deposit(100)
33
+ self.account.withdraw(50)
34
+
35
+ self.assertEqual(self.account.get_balance(), 50)
36
+
37
+ def test_can_withdraw_money_sequentially(self):
38
+ self.account.open()
39
+ self.account.deposit(100)
40
+ self.account.withdraw(20)
41
+ self.account.withdraw(80)
42
+
43
+ self.assertEqual(self.account.get_balance(), 0)
44
+
45
+ def test_checking_balance_of_closed_account_throws_error(self):
46
+ self.account.open()
47
+ self.account.close()
48
+
49
+ with self.assertRaises(ValueError):
50
+ self.account.get_balance()
51
+
52
+ def test_deposit_into_closed_account(self):
53
+ self.account.open()
54
+ self.account.close()
55
+
56
+ with self.assertRaises(ValueError):
57
+ self.account.deposit(50)
58
+
59
+ def test_withdraw_from_closed_account(self):
60
+ self.account.open()
61
+ self.account.close()
62
+
63
+ with self.assertRaises(ValueError):
64
+ self.account.withdraw(50)
65
+
66
+ def test_cannot_withdraw_more_than_deposited(self):
67
+ self.account.open()
68
+ self.account.deposit(25)
69
+
70
+ with self.assertRaises(ValueError):
71
+ self.account.withdraw(50)
72
+
73
+ def test_cannot_withdraw_negative(self):
74
+ self.account.open()
75
+ self.account.deposit(100)
76
+
77
+ with self.assertRaises(ValueError):
78
+ self.account.withdraw(-50)
79
+
80
+ def test_cannot_deposit_negative(self):
81
+ self.account.open()
82
+
83
+ with self.assertRaises(ValueError):
84
+ self.account.deposit(-50)
85
+
86
+ def test_can_handle_concurrent_transactions(self):
87
+ self.account.open()
88
+ self.account.deposit(1000)
89
+
90
+ for _ in range(10):
91
+ self.adjust_balance_concurrently()
92
+
93
+ def adjust_balance_concurrently(self):
94
+ def transact():
95
+ self.account.deposit(5)
96
+ time.sleep(0.001)
97
+ self.account.withdraw(5)
98
+
99
+ # Greatly improve the chance of an operation being interrupted
100
+ # by thread switch, thus testing synchronization effectively
101
+ try:
102
+ sys.setswitchinterval(1e-12)
103
+ except AttributeError:
104
+ # For Python 2 compatibility
105
+ sys.setcheckinterval(1)
106
+
107
+ threads = []
108
+ for _ in range(1000):
109
+ t = threading.Thread(target=transact)
110
+ threads.append(t)
111
+ t.start()
112
+
113
+ for thread in threads:
114
+ thread.join()
115
+
116
+ self.assertEqual(self.account.get_balance(), 1000)
117
+
118
+
119
+ if __name__ == '__main__':
120
+ unittest.main()
@@ -0,0 +1,35 @@
1
+ import threading
2
+
3
+
4
+ class BankAccount(object):
5
+ def __init__(self):
6
+ self.is_open = False
7
+ self.balance = 0
8
+ self.lock = threading.Lock()
9
+
10
+ def get_balance(self):
11
+ with self.lock:
12
+ if self.is_open:
13
+ return self.balance
14
+ else:
15
+ raise ValueError
16
+
17
+ def open(self):
18
+ self.is_open = True
19
+
20
+ def deposit(self, amount):
21
+ with self.lock:
22
+ if self.is_open and amount > 0:
23
+ self.balance += amount
24
+ else:
25
+ raise ValueError
26
+
27
+ def withdraw(self, amount):
28
+ with self.lock:
29
+ if self.is_open and 0 < amount <= self.balance:
30
+ self.balance -= amount
31
+ else:
32
+ raise ValueError
33
+
34
+ def close(self):
35
+ self.is_open = False
@@ -8,7 +8,7 @@ DIRECTIONS = [(0, 1), (0, -1), (1, 0), (-1, 0)]
8
8
 
9
9
  class Board:
10
10
  def __init__(self, board):
11
- self.board = board.splitlines()
11
+ self.board = board
12
12
  self.width = len(self.board[0])
13
13
  self.height = len(self.board)
14
14
 
@@ -35,10 +35,10 @@ class Board:
35
35
 
36
36
  return (visited_territory, visited_stones)
37
37
 
38
- def territoryFor(self, coord):
39
- assert len(coord) == 2
40
- x, y = coord[0], coord[1]
41
- if not self.valid(x, y) or self.board[y][x] in STONES:
38
+ def territory(self, x, y):
39
+ if not self.valid(x, y):
40
+ raise ValueError('invalid coordinate')
41
+ if self.board[y][x] in STONES:
42
42
  return (NONE, set())
43
43
 
44
44
  visited_territory, visited_stones = self.walk(x, y)
@@ -55,7 +55,7 @@ class Board:
55
55
  for y in range(self.height):
56
56
  for x in range(self.width):
57
57
  if not (x, y) in visited:
58
- owner, owned_territories = self.territoryFor((x, y))
58
+ owner, owned_territories = self.territory(x, y)
59
59
  result[owner].update(owned_territories)
60
60
  visited.update(owned_territories)
61
61
 
@@ -9,12 +9,13 @@ class Board:
9
9
  def __init__(self, board):
10
10
  pass
11
11
 
12
- def territoryFor(self, coord):
12
+ def territory(self, x, y):
13
13
  """Find the owner and the territories given a coordinate on
14
14
  the board
15
15
 
16
16
  Args:
17
- coord ((int,int)): Coordinate on the board
17
+ x (int): Column on the board
18
+ y (int): Row on the board
18
19
 
19
20
  Returns:
20
21
  (str, set): A tuple, the first element being the owner