trackler 2.2.1.127 → 2.2.1.128

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