Explorar el Código

all-your-base: add to track

Stuart Kent hace 9 años
padre
commit
ef4af6bd53

+ 7
- 1
config.json Ver fichero

53
     "bracket-push",
53
     "bracket-push",
54
     "pythagorean-triplet",
54
     "pythagorean-triplet",
55
     "binary-search-tree",
55
     "binary-search-tree",
56
-    "binary-search"
56
+    "binary-search",
57
+    "all-your-base"
57
   ],
58
   ],
58
   "exercises": [
59
   "exercises": [
59
     {
60
     {
305
       "slug": "binary-search",
306
       "slug": "binary-search",
306
       "difficulty": 1,
307
       "difficulty": 1,
307
       "topics": []
308
       "topics": []
309
+    },
310
+    {
311
+      "slug": "all-your-base",
312
+      "difficulty": 1,
313
+      "topics": []
308
     }
314
     }
309
   ],
315
   ],
310
   "deprecated": [
316
   "deprecated": [

+ 17
- 0
exercises/all-your-base/build.gradle Ver fichero

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
+}

+ 80
- 0
exercises/all-your-base/src/example/java/BaseConverter.java Ver fichero

1
+import java.util.Arrays;
2
+
3
+final class BaseConverter {
4
+
5
+    private static final int MINIMUM_VALID_BASE = 2;
6
+
7
+    private static final String INVALID_BASE_ERROR_MESSAGE = "Bases must be at least 2.";
8
+
9
+    private final int numeral;
10
+
11
+    BaseConverter(final int originalBase, final int[] originalDigits) {
12
+        validateInputs(originalBase, originalDigits);
13
+        this.numeral = computeNumeral(originalBase, originalDigits);
14
+    }
15
+
16
+    int[] convertToBase(final int newBase) {
17
+        if (newBase < MINIMUM_VALID_BASE) {
18
+            throw new IllegalArgumentException(INVALID_BASE_ERROR_MESSAGE);
19
+        }
20
+
21
+        final int largestExponent = computeLargestExponentForBase(newBase);
22
+        final int[] result = new int[largestExponent + 1];
23
+        int remainder = numeral;
24
+
25
+        for (int currentExponent = largestExponent; currentExponent >= 0; currentExponent--) {
26
+            final int coefficient = (int) Math.floor(remainder / Math.pow(newBase, currentExponent));
27
+
28
+            result[largestExponent - currentExponent] = coefficient;
29
+
30
+            remainder -= coefficient * Math.pow(newBase, currentExponent);
31
+        }
32
+
33
+        return result;
34
+    }
35
+
36
+    private void validateInputs(final int originalBase, final int[] originalDigits) {
37
+        if (originalBase < MINIMUM_VALID_BASE) {
38
+            throw new IllegalArgumentException(INVALID_BASE_ERROR_MESSAGE);
39
+        }
40
+
41
+        if (originalDigits.length == 0) {
42
+            throw new IllegalArgumentException("You must supply at least one digit.");
43
+        }
44
+
45
+        if (originalDigits.length > 1 && originalDigits[0] == 0) {
46
+            throw new IllegalArgumentException("Digits may not contain leading zeros.");
47
+        }
48
+
49
+        if (Arrays.stream(originalDigits).min().getAsInt() < 0) {
50
+            throw new IllegalArgumentException("Digits may not be negative.");
51
+        }
52
+
53
+        if (Arrays.stream(originalDigits).max().getAsInt() >= originalBase) {
54
+            throw new IllegalArgumentException("All digits must be strictly less than the base.");
55
+        }
56
+    }
57
+
58
+    private int computeNumeral(final int originalBase, final int[] originalDigits) {
59
+        int result = 0;
60
+
61
+        final int largestExponent = originalDigits.length - 1;
62
+
63
+        for (int currentExponent = largestExponent; currentExponent >= 0; currentExponent--) {
64
+            result += originalDigits[largestExponent - currentExponent] * Math.pow(originalBase, currentExponent);
65
+        }
66
+
67
+        return result;
68
+    }
69
+
70
+    private int computeLargestExponentForBase(final int newBase) {
71
+        int result = 0;
72
+
73
+        while (Math.pow(newBase, result + 1) < numeral) {
74
+            result += 1;
75
+        }
76
+
77
+        return result;
78
+    }
79
+
80
+}

+ 5
- 0
exercises/all-your-base/src/main/java/BaseConverter.java Ver fichero

1
+final class BaseConverter {
2
+
3
+
4
+
5
+}

+ 256
- 0
exercises/all-your-base/src/test/java/BaseConverterTest.java Ver fichero

1
+import org.junit.Rule;
2
+import org.junit.Test;
3
+import org.junit.rules.ExpectedException;
4
+
5
+import java.util.Arrays;
6
+
7
+import static org.junit.Assert.assertArrayEquals;
8
+
9
+public final class BaseConverterTest {
10
+
11
+    /*
12
+     * See https://github.com/junit-team/junit4/wiki/Rules for information on JUnit Rules in general and
13
+     * ExpectedExceptions in particular.
14
+     */
15
+    @Rule
16
+    public ExpectedException expectedException = ExpectedException.none();
17
+
18
+    @Test
19
+    public void testSingleBitOneToDecimal() {
20
+        final BaseConverter baseConverter = new BaseConverter(2, new int[]{1});
21
+
22
+        final int[] expectedDigits = new int[]{1};
23
+        final int[] actualDigits = baseConverter.convertToBase(10);
24
+
25
+        assertArrayEquals(
26
+                String.format(
27
+                        "Expected digits: %s but found digits: %s",
28
+                        Arrays.toString(expectedDigits),
29
+                        Arrays.toString(actualDigits)),
30
+                expectedDigits,
31
+                actualDigits);
32
+    }
33
+
34
+    @Test
35
+    public void testBinaryToSingleDecimal() {
36
+        final BaseConverter baseConverter = new BaseConverter(2, new int[]{1, 0, 1});
37
+
38
+        final int[] expectedDigits = new int[]{5};
39
+        final int[] actualDigits = baseConverter.convertToBase(10);
40
+
41
+        assertArrayEquals(
42
+                String.format(
43
+                        "Expected digits: %s but found digits: %s",
44
+                        Arrays.toString(expectedDigits),
45
+                        Arrays.toString(actualDigits)),
46
+                expectedDigits,
47
+                actualDigits);
48
+    }
49
+
50
+    @Test
51
+    public void testSingleDecimalToBinary() {
52
+        final BaseConverter baseConverter = new BaseConverter(10, new int[]{5});
53
+
54
+        final int[] expectedDigits = new int[]{1, 0, 1};
55
+        final int[] actualDigits = baseConverter.convertToBase(2);
56
+
57
+        assertArrayEquals(
58
+                String.format(
59
+                        "Expected digits: %s but found digits: %s",
60
+                        Arrays.toString(expectedDigits),
61
+                        Arrays.toString(actualDigits)),
62
+                expectedDigits,
63
+                actualDigits);
64
+    }
65
+
66
+    @Test
67
+    public void testBinaryToMultipleDecimal() {
68
+        final BaseConverter baseConverter = new BaseConverter(2, new int[]{1, 0, 1, 0, 1, 0});
69
+
70
+        final int[] expectedDigits = new int[]{4, 2};
71
+        final int[] actualDigits = baseConverter.convertToBase(10);
72
+
73
+        assertArrayEquals(
74
+                String.format(
75
+                        "Expected digits: %s but found digits: %s",
76
+                        Arrays.toString(expectedDigits),
77
+                        Arrays.toString(actualDigits)),
78
+                expectedDigits,
79
+                actualDigits);
80
+    }
81
+
82
+    @Test
83
+    public void testDecimalToBinary() {
84
+        final BaseConverter baseConverter = new BaseConverter(10, new int[]{4, 2});
85
+
86
+        final int[] expectedDigits = new int[]{1, 0, 1, 0, 1, 0};
87
+        final int[] actualDigits = baseConverter.convertToBase(2);
88
+
89
+        assertArrayEquals(
90
+                String.format(
91
+                        "Expected digits: %s but found digits: %s",
92
+                        Arrays.toString(expectedDigits),
93
+                        Arrays.toString(actualDigits)),
94
+                expectedDigits,
95
+                actualDigits);
96
+    }
97
+
98
+    @Test
99
+    public void testTrinaryToHexadecimal() {
100
+        final BaseConverter baseConverter = new BaseConverter(3, new int[]{1, 1, 2, 0});
101
+
102
+        final int[] expectedDigits = new int[]{2, 10};
103
+        final int[] actualDigits = baseConverter.convertToBase(16);
104
+
105
+        assertArrayEquals(
106
+                String.format(
107
+                        "Expected digits: %s but found digits: %s",
108
+                        Arrays.toString(expectedDigits),
109
+                        Arrays.toString(actualDigits)),
110
+                expectedDigits,
111
+                actualDigits);
112
+    }
113
+
114
+    @Test
115
+    public void testHexadecimalToTrinary() {
116
+        final BaseConverter baseConverter = new BaseConverter(16, new int[]{2, 10});
117
+
118
+        final int[] expectedDigits = new int[]{1, 1, 2, 0};
119
+        final int[] actualDigits = baseConverter.convertToBase(3);
120
+
121
+        assertArrayEquals(
122
+                String.format(
123
+                        "Expected digits: %s but found digits: %s",
124
+                        Arrays.toString(expectedDigits),
125
+                        Arrays.toString(actualDigits)),
126
+                expectedDigits,
127
+                actualDigits);
128
+    }
129
+
130
+    @Test
131
+    public void test15BitInteger() {
132
+        final BaseConverter baseConverter = new BaseConverter(97, new int[]{3, 46, 60});
133
+
134
+        final int[] expectedDigits = new int[]{6, 10, 45};
135
+        final int[] actualDigits = baseConverter.convertToBase(73);
136
+
137
+        assertArrayEquals(
138
+                String.format(
139
+                        "Expected digits: %s but found digits: %s",
140
+                        Arrays.toString(expectedDigits),
141
+                        Arrays.toString(actualDigits)),
142
+                expectedDigits,
143
+                actualDigits);
144
+    }
145
+
146
+    @Test
147
+    public void testEmptyDigits() {
148
+        expectedException.expect(IllegalArgumentException.class);
149
+        expectedException.expectMessage("You must supply at least one digit.");
150
+
151
+        new BaseConverter(2, new int[]{});
152
+    }
153
+
154
+    @Test
155
+    public void testSingleZero() {
156
+        final BaseConverter baseConverter = new BaseConverter(10, new int[]{0});
157
+
158
+        final int[] expectedDigits = new int[]{0};
159
+        final int[] actualDigits = baseConverter.convertToBase(2);
160
+
161
+        assertArrayEquals(
162
+                String.format(
163
+                        "Expected digits: %s but found digits: %s",
164
+                        Arrays.toString(expectedDigits),
165
+                        Arrays.toString(actualDigits)),
166
+                expectedDigits,
167
+                actualDigits);
168
+    }
169
+
170
+    @Test
171
+    public void testMultipleZeros() {
172
+        expectedException.expect(IllegalArgumentException.class);
173
+        expectedException.expectMessage("Digits may not contain leading zeros.");
174
+
175
+        new BaseConverter(10, new int[]{0, 0, 0});
176
+    }
177
+
178
+    @Test
179
+    public void testLeadingZeros() {
180
+        expectedException.expect(IllegalArgumentException.class);
181
+        expectedException.expectMessage("Digits may not contain leading zeros.");
182
+
183
+        new BaseConverter(7, new int[]{0, 6, 0});
184
+    }
185
+
186
+    @Test
187
+    public void testNegativeDigit() {
188
+        expectedException.expect(IllegalArgumentException.class);
189
+        expectedException.expectMessage("Digits may not be negative.");
190
+
191
+        new BaseConverter(2, new int[]{1, -1, 1, 0, 1, 0});
192
+    }
193
+
194
+    @Test
195
+    public void testInvalidPositiveDigit() {
196
+        expectedException.expect(IllegalArgumentException.class);
197
+        expectedException.expectMessage("All digits must be strictly less than the base.");
198
+
199
+        new BaseConverter(2, new int[]{1, 2, 1, 0, 1, 0});
200
+    }
201
+
202
+    @Test
203
+    public void testFirstBaseIsOne() {
204
+        expectedException.expect(IllegalArgumentException.class);
205
+        expectedException.expectMessage("Bases must be at least 2.");
206
+
207
+        new BaseConverter(1, new int[]{});
208
+    }
209
+
210
+    @Test
211
+    public void testSecondBaseIsOne() {
212
+        final BaseConverter baseConverter = new BaseConverter(2, new int[]{1, 0, 1, 0, 1, 0});
213
+
214
+        expectedException.expect(IllegalArgumentException.class);
215
+        expectedException.expectMessage("Bases must be at least 2.");
216
+
217
+        baseConverter.convertToBase(1);
218
+    }
219
+
220
+    @Test
221
+    public void testFirstBaseIsZero() {
222
+        expectedException.expect(IllegalArgumentException.class);
223
+        expectedException.expectMessage("Bases must be at least 2.");
224
+
225
+        new BaseConverter(0, new int[]{});
226
+    }
227
+
228
+    @Test
229
+    public void testSecondBaseIsZero() {
230
+        final BaseConverter baseConverter = new BaseConverter(2, new int[]{1, 0, 1, 0, 1, 0});
231
+
232
+        expectedException.expect(IllegalArgumentException.class);
233
+        expectedException.expectMessage("Bases must be at least 2.");
234
+
235
+        baseConverter.convertToBase(0);
236
+    }
237
+
238
+    @Test
239
+    public void testFirstBaseIsNegative() {
240
+        expectedException.expect(IllegalArgumentException.class);
241
+        expectedException.expectMessage("Bases must be at least 2.");
242
+
243
+        new BaseConverter(-2, new int[]{});
244
+    }
245
+
246
+    @Test
247
+    public void testSecondBaseIsNegative() {
248
+        final BaseConverter baseConverter = new BaseConverter(2, new int[]{1});
249
+
250
+        expectedException.expect(IllegalArgumentException.class);
251
+        expectedException.expectMessage("Bases must be at least 2.");
252
+
253
+        baseConverter.convertToBase(-7);
254
+    }
255
+
256
+}

+ 1
- 0
exercises/settings.gradle Ver fichero

1
 include 'accumulate'
1
 include 'accumulate'
2
 include 'acronym'
2
 include 'acronym'
3
+include 'all-your-base'
3
 include 'allergies'
4
 include 'allergies'
4
 include 'anagram'
5
 include 'anagram'
5
 include 'atbash-cipher'
6
 include 'atbash-cipher'