Pārlūkot izejas kodu

dominoes: add new exercise (#1379)

* dominoes: add new exercise

* dominoes: add new exercise

* dominoes: add new exercise

* dominoes: add new exercise

* dominoes: add new exercise

* dominoes: add new exercise

* dominoes: add new exercise

* dominoes: add new exercise
jssander 8 gadus atpakaļ
vecāks
revīzija
624d2e77a7

+ 13
- 0
config.json Parādīt failu

1104
     },
1104
     },
1105
     {
1105
     {
1106
       "core": false,
1106
       "core": false,
1107
+      "difficulty": 7,
1108
+      "slug": "dominoes",
1109
+      "topics": [
1110
+        "games",
1111
+        "algorithms",
1112
+        "lists",
1113
+        "exception_handling"
1114
+      ],
1115
+      "unlocked_by": "scrabble-score",
1116
+      "uuid": "8e3cb20e-623b-4b4d-8a91-d1a51c0911b5"
1117
+    },
1118
+    {
1119
+      "core": false,
1107
       "difficulty": 8,
1120
       "difficulty": 8,
1108
       "slug": "ocr-numbers",
1121
       "slug": "ocr-numbers",
1109
       "topics": [
1122
       "topics": [

+ 5
- 0
exercises/dominoes/.meta/src/reference/java/ChainNotFoundException.java Parādīt failu

1
+class ChainNotFoundException extends Exception {
2
+	public ChainNotFoundException(String message) {
3
+		super(message);
4
+	}
5
+}

+ 30
- 0
exercises/dominoes/.meta/src/reference/java/Domino.java Parādīt failu

1
+import java.util.Objects;
2
+
3
+class Domino {
4
+    private int left;
5
+    private int right;
6
+    Domino(int left, int right) {
7
+        this.left = left;
8
+        this.right = right;
9
+    }
10
+    
11
+    int getLeft() {
12
+    	return this.left;
13
+    }
14
+    
15
+    int getRight() {
16
+    	return this.right;
17
+    }
18
+    
19
+    @Override
20
+    public boolean equals(Object o) {
21
+    	Domino otherDomino = (Domino) o;
22
+    	return (this.getLeft() == otherDomino.getLeft() && this.getRight() == otherDomino.getRight()) ||
23
+    			(this.getLeft() == otherDomino.getRight() && this.getRight() == otherDomino.getLeft());
24
+    }
25
+    
26
+    @Override
27
+    public int hashCode() {
28
+    	return Objects.hash(left, right);
29
+    }
30
+}

+ 67
- 0
exercises/dominoes/.meta/src/reference/java/Dominoes.java Parādīt failu

1
+import java.util.ArrayList;
2
+import java.util.Arrays;
3
+import java.util.List;
4
+
5
+class Dominoes {
6
+	
7
+	List<Domino> formChain(List<Domino> inputDominoes) throws ChainNotFoundException {
8
+		if (inputDominoes.size() == 0) {
9
+			return inputDominoes;
10
+		} else {
11
+			return formPartialChain(new ArrayList<Domino>(), inputDominoes);
12
+		}
13
+	}
14
+	
15
+	private boolean isValidChain(ArrayList<Domino> chain) {
16
+		return isValidPartialChain(chain) && (chain.get(0).getLeft() == chain.get(chain.size() - 1).getRight());
17
+	}
18
+	
19
+	private boolean isValidPartialChain(ArrayList<Domino> chain) {
20
+		for (int i = 0; i < chain.size() - 1; i++) {
21
+			if (chain.get(i).getRight() != chain.get(i+1).getLeft()) {
22
+				return false;
23
+			}
24
+		}
25
+		
26
+		return true;
27
+	}
28
+	
29
+	ArrayList<Domino> formPartialChain(ArrayList<Domino> current, List<Domino> remaining) throws ChainNotFoundException {
30
+		if (remaining.size() == 0) {
31
+			if (isValidChain(current)) {
32
+				return current;
33
+			} else {
34
+				throw new ChainNotFoundException("No domino chain found.");
35
+			}
36
+		}
37
+		
38
+		for (int i = 0; i < remaining.size(); i++) {
39
+			ArrayList<Domino> newRemaining = new ArrayList<Domino>(remaining);
40
+			newRemaining.remove(i);
41
+			
42
+			ArrayList<Domino> newChainA = new ArrayList<Domino>(current);
43
+			newChainA.add(remaining.get(i));
44
+			
45
+			ArrayList<Domino> newChainB = new ArrayList<Domino>(current);
46
+			newChainB.add(new Domino(remaining.get(i).getRight(), remaining.get(i).getLeft()));
47
+			
48
+			if (isValidPartialChain(newChainA)) {
49
+				try {
50
+					return formPartialChain(newChainA, newRemaining);
51
+				} catch (ChainNotFoundException e) {
52
+					//This path does not have a valid chain
53
+				}
54
+			}
55
+			
56
+			if (isValidPartialChain(newChainB)) {
57
+				try {
58
+					return formPartialChain(newChainB, newRemaining);
59
+				} catch (ChainNotFoundException e) {
60
+					//This path doesn't have a valid chain
61
+				}
62
+			}
63
+		}
64
+		
65
+		throw new ChainNotFoundException("No domino chain found.");
66
+	}
67
+}

+ 2
- 0
exercises/dominoes/.meta/version Parādīt failu

1
+1.0.0
2
+

+ 29
- 0
exercises/dominoes/README.md Parādīt failu

1
+# Dominoes
2
+
3
+Make a chain of dominoes.
4
+
5
+Compute a way to order a given set of dominoes in such a way that they form a
6
+correct domino chain (the dots on one half of a stone match the dots on the
7
+neighbouring half of an adjacent stone) and that dots on the halfs of the stones
8
+which don't have a neighbour (the first and last stone) match each other.
9
+
10
+For example given the stones `[2|1]`, `[2|3]` and `[1|3]` you should compute something
11
+like `[1|2] [2|3] [3|1]` or `[3|2] [2|1] [1|3]` or `[1|3] [3|2] [2|1]` etc, where the first and last numbers are the same.
12
+
13
+For stones `[1|2]`, `[4|1]` and `[2|3]` the resulting chain is not valid: `[4|1] [1|2] [2|3]`'s first and last numbers are not the same. 4 != 3
14
+
15
+Some test cases may use duplicate stones in a chain solution, assume that multiple Domino sets are being used.
16
+
17
+# Running the tests
18
+
19
+You can run all the tests for an exercise by entering
20
+
21
+```sh
22
+$ gradle test
23
+```
24
+
25
+in your terminal.
26
+
27
+## Submitting Incomplete Solutions
28
+
29
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.

+ 18
- 0
exercises/dominoes/build.gradle Parādīt failu

1
+apply plugin: "java"
2
+apply plugin: "eclipse"
3
+apply plugin: "idea"
4
+
5
+repositories {
6
+    mavenCentral()
7
+}
8
+
9
+dependencies {
10
+    testCompile "junit:junit:4.12"
11
+}
12
+
13
+test {
14
+    testLogging {
15
+        exceptionFormat = 'full'
16
+        events = ["passed", "failed", "skipped"]
17
+    }
18
+}

+ 5
- 0
exercises/dominoes/src/main/java/ChainNotFoundException.java Parādīt failu

1
+class ChainNotFoundException extends Exception {
2
+	public ChainNotFoundException(String message) {
3
+		super(message);
4
+	}
5
+}

+ 30
- 0
exercises/dominoes/src/main/java/Domino.java Parādīt failu

1
+import java.util.Objects;
2
+
3
+class Domino {
4
+    private int left;
5
+    private int right;
6
+    Domino(int left, int right) {
7
+        this.left = left;
8
+        this.right = right;
9
+    }
10
+    
11
+    int getLeft() {
12
+    	return this.left;
13
+    }
14
+    
15
+    int getRight() {
16
+    	return this.right;
17
+    }
18
+    
19
+    @Override
20
+    public boolean equals(Object o) {
21
+    	Domino otherDomino = (Domino) o;
22
+    	return (this.getLeft() == otherDomino.getLeft() && this.getRight() == otherDomino.getRight()) ||
23
+    			(this.getLeft() == otherDomino.getRight() && this.getRight() == otherDomino.getLeft());
24
+    }
25
+    
26
+    @Override
27
+    public int hashCode() {
28
+    	return Objects.hash(left, right);
29
+    }
30
+}

+ 230
- 0
exercises/dominoes/src/test/java/DominoesTest.java Parādīt failu

1
+import org.junit.Ignore;
2
+import org.junit.Test;
3
+
4
+import java.util.List;
5
+import java.util.ArrayList;
6
+import java.util.Arrays;
7
+import java.util.Collections;
8
+
9
+import static org.junit.Assert.assertEquals;
10
+import static org.junit.Assert.assertNull;
11
+
12
+import org.junit.Rule;
13
+import org.junit.rules.ExpectedException;
14
+
15
+public class DominoesTest {
16
+	
17
+	@Rule
18
+	public ExpectedException expectedException = ExpectedException.none(); 
19
+	
20
+	@Test
21
+	public void emtpyInputEmptyOutputTest() throws ChainNotFoundException {
22
+		Dominoes dominoes = new Dominoes();
23
+		
24
+		List<Domino> dominoesList = new ArrayList<>();
25
+		
26
+		List<Domino> chain = dominoes.formChain(dominoesList);
27
+		
28
+		assertEquals("The output list should be empty.", 0, chain.size());
29
+	}
30
+	
31
+	@Ignore("Remove to run test")
32
+	@Test
33
+	public void singletonInputSingletonOutput() throws ChainNotFoundException {
34
+		Dominoes dominoes = new Dominoes();
35
+		
36
+		Domino[] dominoesArray = {new Domino(1, 1)};
37
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
38
+		
39
+		List<Domino> chain = dominoes.formChain(dominoesList);
40
+		
41
+		assertValidChain(dominoesList, chain);
42
+	}
43
+	
44
+	@Ignore("Remove to run test")
45
+	@Test
46
+	public void singletonCantBeChainedTest() throws ChainNotFoundException {
47
+		Dominoes dominoes = new Dominoes();
48
+		
49
+		Domino[] dominoesArray = {new Domino(1, 2)};
50
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
51
+		
52
+		expectedException.expect(ChainNotFoundException.class);
53
+		expectedException.expectMessage("No domino chain found.");
54
+		
55
+		dominoes.formChain(dominoesList);
56
+	}
57
+	
58
+	@Ignore("Remove to run test")
59
+	@Test
60
+	public void threeElementsTest() throws ChainNotFoundException {
61
+		Dominoes dominoes = new Dominoes();
62
+		
63
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(3, 1), new Domino(2, 3)};
64
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
65
+		
66
+		List<Domino> chain = dominoes.formChain(dominoesList);
67
+		
68
+		assertValidChain(dominoesList, chain);
69
+	}
70
+	
71
+	@Ignore("Remove to run test")
72
+	@Test
73
+	public void canReverseDominoesTest() throws ChainNotFoundException {
74
+		Dominoes dominoes = new Dominoes();
75
+		
76
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(1, 3), new Domino(2, 3)};
77
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
78
+		
79
+		List<Domino> chain = dominoes.formChain(dominoesList);
80
+		
81
+		assertValidChain(dominoesList, chain);
82
+	}
83
+	
84
+	@Ignore("Remove to run test")
85
+	@Test
86
+	public void cantBeChainedTest() throws ChainNotFoundException {
87
+		Dominoes dominoes = new Dominoes();
88
+		
89
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(4, 1), new Domino(2, 3)};
90
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
91
+		
92
+		expectedException.expect(ChainNotFoundException.class);
93
+		expectedException.expectMessage("No domino chain found.");
94
+		
95
+		dominoes.formChain(dominoesList);
96
+	}
97
+	
98
+	@Ignore("Remove to run test")
99
+	@Test
100
+	public void disconnectedSimpleTest() throws ChainNotFoundException {
101
+		Dominoes dominoes = new Dominoes();
102
+		
103
+		Domino[] dominoesArray = {new Domino(1, 1), new Domino(2, 2)};
104
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
105
+		
106
+		expectedException.expect(ChainNotFoundException.class);
107
+		expectedException.expectMessage("No domino chain found.");
108
+		
109
+		dominoes.formChain(dominoesList);
110
+	}
111
+	
112
+	@Ignore("Remove to run test")
113
+	@Test
114
+	public void disconnectedDoubleLoopTest() throws ChainNotFoundException {
115
+		Dominoes dominoes = new Dominoes();
116
+		
117
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(2, 1), new Domino(3, 4), new Domino(4, 3)};
118
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
119
+		
120
+		expectedException.expect(ChainNotFoundException.class);
121
+		expectedException.expectMessage("No domino chain found.");
122
+		
123
+		dominoes.formChain(dominoesList);
124
+	}
125
+	
126
+	@Ignore("Remove to run test")
127
+	@Test
128
+	public void disconnectedSingleIsolatedTest() throws ChainNotFoundException {
129
+		Dominoes dominoes = new Dominoes();
130
+		
131
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(2, 3), new Domino(3, 1), new Domino(4, 4)};
132
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
133
+		
134
+		expectedException.expect(ChainNotFoundException.class);
135
+		expectedException.expectMessage("No domino chain found.");
136
+		
137
+		dominoes.formChain(dominoesList);
138
+	}
139
+	
140
+	@Ignore("Remove to run test")
141
+	@Test
142
+	public void needBacktrackTest() throws ChainNotFoundException {
143
+		Dominoes dominoes = new Dominoes();
144
+		
145
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(2, 3), new Domino(3, 1), new Domino(2, 4), new Domino(4, 2)};
146
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
147
+		
148
+		List<Domino> chain = dominoes.formChain(dominoesList);
149
+		
150
+		assertValidChain(dominoesList, chain);
151
+	}
152
+	
153
+	@Ignore("Remove to run test")
154
+	@Test
155
+	public void separateLoopsTest() throws ChainNotFoundException {
156
+		Dominoes dominoes = new Dominoes();
157
+		
158
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(2, 3), new Domino(3, 1),
159
+				new Domino(1, 1), new Domino(2, 2), new Domino(3, 3)};
160
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
161
+		
162
+		List<Domino> chain = dominoes.formChain(dominoesList);
163
+		
164
+		assertValidChain(dominoesList, chain);
165
+	}
166
+	
167
+	@Ignore("Remove to run test")
168
+	@Test
169
+	public void nineElementsTest() throws ChainNotFoundException {
170
+		Dominoes dominoes = new Dominoes();
171
+		Domino[] dominoesArray = {new Domino(1, 2), new Domino(5, 3), new Domino(3, 1),
172
+				new Domino(1, 2), new Domino(2, 4), new Domino(1, 6),
173
+				new Domino(2, 3), new Domino(3, 4), new Domino(5, 6)};
174
+		List<Domino> dominoesList = Arrays.asList(dominoesArray);
175
+		
176
+		List<Domino> chain = dominoes.formChain(dominoesList);
177
+		
178
+		assertValidChain(dominoesList, chain);
179
+	}
180
+	
181
+	private void assertValidChain(List<Domino> inputDominoes, List<Domino> outputDominoes) {
182
+		assertSameDominoes(inputDominoes, outputDominoes);
183
+		assertEndDominoesMatch(outputDominoes);
184
+		assertConsecutiveDominoes(outputDominoes);
185
+	}
186
+	
187
+	private void assertEndDominoesMatch(List<Domino> outputDominoes) {
188
+		int leftValueOfFirstDomino = outputDominoes.get(0).getLeft();
189
+		int rightValueOfLastDomino = outputDominoes.get(outputDominoes.size() - 1).getRight();
190
+		String errorMessage = "The left value of the first domino ("
191
+		    + leftValueOfFirstDomino
192
+		    + ") needs to match the right value of the last domino ("
193
+		    + rightValueOfLastDomino
194
+		    + ").";
195
+		
196
+		assertEquals(errorMessage, leftValueOfFirstDomino, rightValueOfLastDomino);
197
+	}
198
+	
199
+	private void assertSameDominoes(List<Domino> inputDominoes, List<Domino> outputDominoes) {
200
+		String errorMessage = "The number of dominoes in the input list (" + inputDominoes.size()
201
+				+ ") needs to match the number of dominoes in the output chain (" + outputDominoes.size() + ")";
202
+		
203
+		assertEquals(errorMessage, inputDominoes.size(), outputDominoes.size());
204
+		
205
+		for (Domino domino : inputDominoes) {
206
+			int inputFrequency = Collections.frequency(inputDominoes, domino);
207
+			int outputFrequency = Collections.frequency(outputDominoes, domino);
208
+			
209
+			String frequencyErrorMessage = "The frequency of domino (" + domino.getLeft() + ", " + domino.getRight() + ")"
210
+					+ " in the input is (" + inputFrequency + "), but (" + outputFrequency + ") in the output.";
211
+					
212
+			assertEquals(frequencyErrorMessage, inputFrequency, outputFrequency);
213
+		}
214
+	}
215
+	
216
+	private void assertConsecutiveDominoes(List<Domino> dominoes) {
217
+		for (int i = 0; i < dominoes.size() - 1; i++) {
218
+			
219
+			int rightValueOfIthDomino = dominoes.get(i).getRight();
220
+			int leftValueOfNextDomino = dominoes.get(i+1).getLeft();
221
+			String errorMessage = "The right value of domino number " + i + " ("
222
+			    + rightValueOfIthDomino
223
+			    + ") needs to match the left value of domino number " + (i+1) + " ("
224
+			    + leftValueOfNextDomino
225
+			    + ").";
226
+			
227
+			assertEquals(errorMessage, dominoes.get(i).getRight(), dominoes.get(i+1).getLeft());
228
+		}
229
+	}
230
+}

+ 1
- 0
exercises/settings.gradle Parādīt failu

25
 include 'diamond'
25
 include 'diamond'
26
 include 'difference-of-squares'
26
 include 'difference-of-squares'
27
 include 'diffie-hellman'
27
 include 'diffie-hellman'
28
+include 'dominoes'
28
 include 'error-handling'
29
 include 'error-handling'
29
 include 'etl'
30
 include 'etl'
30
 include 'flatten-array'
31
 include 'flatten-array'