Просмотр исходного кода

Merge pull request #243 from exercism/rectangles

rectangles: add to track
John Ryan 9 лет назад
Родитель
Сommit
5422e53067

+ 7
- 1
config.json Просмотреть файл

@@ -55,7 +55,8 @@
55 55
     "wordy",
56 56
     "palindrome-products",
57 57
     "twelve-days",
58
-    "sublist"
58
+    "sublist",
59
+    "rectangles"
59 60
   ],
60 61
   "exercises": [
61 62
     {
@@ -317,6 +318,11 @@
317 318
       "slug": "sublist",
318 319
       "difficulty": 1,
319 320
       "topics": []
321
+    },
322
+    {
323
+      "slug": "rectangles",
324
+      "difficulty": 1,
325
+      "topics": []
320 326
     }
321 327
   ],
322 328
   "deprecated": [

+ 17
- 0
exercises/rectangles/build.gradle Просмотреть файл

@@ -0,0 +1,17 @@
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
+test {
13
+  testLogging {
14
+    exceptionFormat = 'full'
15
+    events = ["passed", "failed", "skipped"]
16
+  }
17
+}

+ 115
- 0
exercises/rectangles/src/example/java/RectangleCounter.java Просмотреть файл

@@ -0,0 +1,115 @@
1
+import static java.util.Arrays.copyOfRange;
2
+import static java.util.Arrays.stream;
3
+
4
+final class RectangleCounter {
5
+
6
+    int countRectangles(final String[] rawGrid) {
7
+        final int nRows = rawGrid.length;
8
+        if (nRows == 0) return 0;
9
+
10
+        final int nCols = rawGrid[0].length();
11
+        if (nCols == 0) return 0;
12
+
13
+        return new Grid(nRows, nCols, rawGrid).countRectangles();
14
+    }
15
+
16
+    private static final class Grid {
17
+
18
+        private enum Entry {
19
+            CORNER,
20
+            HLINE,
21
+            VLINE,
22
+            SPACE;
23
+
24
+            private static Entry fromChar(final char rawGridEntry) {
25
+                switch (rawGridEntry) {
26
+                    case '+': return CORNER;
27
+                    case '-': return HLINE;
28
+                    case '|': return VLINE;
29
+                    case ' ': return SPACE;
30
+                    default:  throw new IllegalStateException("Grid entry " + rawGridEntry + " not recognized.");
31
+                }
32
+            }
33
+        }
34
+
35
+        private int nRows, nCols;
36
+        private final Entry[][] entries;
37
+
38
+        private Grid(final int nRows, final int nCols, final String[] rawGrid) {
39
+            this.nRows = nRows;
40
+            this.nCols = nCols;
41
+            this.entries = new Entry[nRows][nCols];
42
+
43
+            for (int nRow = 0; nRow < nRows; nRow++) {
44
+                for (int nCol = 0; nCol < nCols; nCol++) {
45
+                    entries[nRow][nCol] = Entry.fromChar(rawGrid[nRow].charAt(nCol));
46
+                }
47
+            }
48
+        }
49
+
50
+        private int countRectangles() {
51
+            int result = 0;
52
+
53
+            for (int topRow = 0; topRow < nRows - 1; topRow++) {
54
+
55
+                for (int leftCol = 0; leftCol < nCols - 1; leftCol++) {
56
+
57
+                    // Only check rectangles that lie below/to the right of our current coordinate:
58
+                    for (int bottomRow = topRow + 1; bottomRow < nRows; bottomRow++) {
59
+
60
+                        for (int rightCol = leftCol + 1; rightCol < nCols; rightCol++) {
61
+
62
+                            if (formsRectangle(topRow, bottomRow, leftCol, rightCol)) {
63
+                                result++;
64
+                            }
65
+                        }
66
+                    }
67
+                }
68
+            }
69
+
70
+            return result;
71
+        }
72
+
73
+        private boolean formsRectangle(
74
+                final int topRow,
75
+                final int bottomRow,
76
+                final int leftCol,
77
+                final int rightCol) {
78
+
79
+            return entries[topRow][leftCol].equals(Entry.CORNER)
80
+                    && entries[topRow][rightCol].equals(Entry.CORNER)
81
+                    && entries[bottomRow][leftCol].equals(Entry.CORNER)
82
+                    && entries[bottomRow][rightCol].equals(Entry.CORNER)
83
+                    && isHorizontalLineSegment(topRow, leftCol, rightCol)
84
+                    && isHorizontalLineSegment(bottomRow, leftCol, rightCol)
85
+                    && isVerticalLineSegment(leftCol, topRow, bottomRow)
86
+                    && isVerticalLineSegment(rightCol, topRow, bottomRow);
87
+        }
88
+
89
+        private boolean isHorizontalLineSegment(final int row, final int leftCol, final int rightCol) {
90
+            return stream(copyOfRange(getRow(row), leftCol, rightCol))
91
+                    .allMatch(entry -> entry.equals(Entry.HLINE) || entry.equals(Entry.CORNER));
92
+        }
93
+
94
+        private boolean isVerticalLineSegment(final int col, final int topRow, final int bottomRow) {
95
+            return stream(copyOfRange(getCol(col), topRow, bottomRow))
96
+                    .allMatch(entry -> entry.equals(Entry.VLINE) || entry.equals(Entry.CORNER));
97
+        }
98
+
99
+        private Entry[] getRow(final int number) {
100
+            return entries[number];
101
+        }
102
+
103
+        private Entry[] getCol(final int number) {
104
+            final Entry[] result = new Entry[nRows];
105
+
106
+            for (int nRow = 0; nRow < nRows; nRow++) {
107
+                result[nRow] = entries[nRow][number];
108
+            }
109
+
110
+            return result;
111
+        }
112
+
113
+    }
114
+
115
+}

+ 5
- 0
exercises/rectangles/src/main/java/RectangleCounter.java Просмотреть файл

@@ -0,0 +1,5 @@
1
+final class RectangleCounter {
2
+
3
+
4
+
5
+}

+ 164
- 0
exercises/rectangles/src/test/java/RectangleCounterTest.java Просмотреть файл

@@ -0,0 +1,164 @@
1
+import org.junit.Before;
2
+import org.junit.Ignore;
3
+import org.junit.Test;
4
+
5
+import static org.junit.Assert.assertEquals;
6
+
7
+public final class RectangleCounterTest {
8
+
9
+    private RectangleCounter rectangleCounter;
10
+
11
+    @Before
12
+    public void setUp() {
13
+        rectangleCounter = new RectangleCounter();
14
+    }
15
+
16
+    @Test
17
+    public void testInputWithNoColumnsContainsNoRectangles() {
18
+        String[] inputGrid = new String[]{};
19
+
20
+        assertEquals(0, rectangleCounter.countRectangles(inputGrid));
21
+    }
22
+
23
+    @Ignore
24
+    @Test
25
+    public void testNonTrivialInputWithNoRectangles() {
26
+        String[] inputGrid = new String[]{" "};
27
+
28
+        assertEquals(0, rectangleCounter.countRectangles(inputGrid));
29
+    }
30
+
31
+    @Ignore
32
+    @Test
33
+    public void testInputWithOneRectangle() {
34
+        String[] inputGrid = new String[]{
35
+                "+-+",
36
+                "| |",
37
+                "+-+"
38
+        };
39
+
40
+        assertEquals(1, rectangleCounter.countRectangles(inputGrid));
41
+    }
42
+
43
+    @Ignore
44
+    @Test
45
+    public void testInputWithTwoRectanglesWithoutSharedEdges() {
46
+        String[] inputGrid = new String[]{
47
+                "  +-+",
48
+                "  | |",
49
+                "+-+-+",
50
+                "| |  ",
51
+                "+-+  "
52
+        };
53
+
54
+        assertEquals(2, rectangleCounter.countRectangles(inputGrid));
55
+    }
56
+
57
+    @Ignore
58
+    @Test
59
+    public void testInputWithFiveRectanglesWithSharedEdges() {
60
+        String[] inputGrid = new String[]{
61
+                "  +-+",
62
+                "  | |",
63
+                "+-+-+",
64
+                "| | |",
65
+                "+-+-+"
66
+        };
67
+
68
+        assertEquals(5, rectangleCounter.countRectangles(inputGrid));
69
+    }
70
+
71
+    @Ignore
72
+    @Test
73
+    public void testThatRectangleOfHeightOneIsCounted() {
74
+        String[] inputGrid = new String[]{
75
+                "+--+",
76
+                "+--+"
77
+        };
78
+
79
+        assertEquals(1, rectangleCounter.countRectangles(inputGrid));
80
+    }
81
+
82
+    @Ignore
83
+    @Test
84
+    public void testThatRectangleOfWidthOneIsCounted() {
85
+        String[] inputGrid = new String[]{
86
+                "++",
87
+                "||",
88
+                "++"
89
+        };
90
+
91
+        assertEquals(1, rectangleCounter.countRectangles(inputGrid));
92
+    }
93
+
94
+    @Ignore
95
+    @Test
96
+    public void testThatOneByOneSquareIsCounted() {
97
+        String[] inputGrid = new String[]{
98
+                "++",
99
+                "++"
100
+        };
101
+
102
+        assertEquals(1, rectangleCounter.countRectangles(inputGrid));
103
+    }
104
+
105
+    @Ignore
106
+    @Test
107
+    public void testThatIncompleteRectanglesAreNotCounted() {
108
+        String[] inputGrid = new String[]{
109
+                "  +-+",
110
+                "    |",
111
+                "+-+-+",
112
+                "| | -",
113
+                "+-+-+"
114
+        };
115
+
116
+        assertEquals(1, rectangleCounter.countRectangles(inputGrid));
117
+    }
118
+
119
+    @Ignore
120
+    @Test
121
+    public void testThatRectanglesOfDifferentSizesAreAllCounted() {
122
+        String[] inputGrid = new String[]{
123
+                "+------+----+",
124
+                "|      |    |",
125
+                "+---+--+    |",
126
+                "|   |       |",
127
+                "+---+-------+"
128
+        };
129
+
130
+        assertEquals(3, rectangleCounter.countRectangles(inputGrid));
131
+    }
132
+
133
+    @Ignore
134
+    @Test
135
+    public void testThatIntersectionsWithoutCornerCharacterDoNotCountAsRectangleCorners() {
136
+        String[] inputGrid = new String[]{
137
+                "+------+----+",
138
+                "|      |    |",
139
+                "+------+    |",
140
+                "|   |       |",
141
+                "+---+-------+"
142
+        };
143
+
144
+        assertEquals(2, rectangleCounter.countRectangles(inputGrid));
145
+    }
146
+
147
+    @Ignore
148
+    @Test
149
+    public void testLargeInputWithManyRectangles() {
150
+        String[] inputGrid = new String[]{
151
+                "+---+--+----+",
152
+                "|   +--+----+",
153
+                "+---+--+    |",
154
+                "|   +--+----+",
155
+                "+---+--+--+-+",
156
+                "+---+--+--+-+",
157
+                "+------+  | |",
158
+                "          +-+"
159
+        };
160
+
161
+        assertEquals(60, rectangleCounter.countRectangles(inputGrid));
162
+    }
163
+
164
+}

+ 1
- 0
exercises/settings.gradle Просмотреть файл

@@ -34,6 +34,7 @@ include 'phone-number'
34 34
 include 'pig-latin'
35 35
 include 'queen-attack'
36 36
 include 'raindrops'
37
+include 'rectangles'
37 38
 include 'rna-transcription'
38 39
 include 'robot-name'
39 40
 include 'robot-simulator'