Skip to content

Commit 0c8e8ef

Browse files
authored
Add new practice exercise: all-your-base (#104)
1 parent f1f998c commit 0c8e8ef

File tree

12 files changed

+417
-0
lines changed

12 files changed

+417
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@
194194
"prerequisites": [],
195195
"difficulty": 8
196196
},
197+
{
198+
"slug": "all-your-base",
199+
"name": "All Your Base",
200+
"uuid": "36b4c4c7-c5a1-4885-bf2e-2b77130ab23a",
201+
"practices": [],
202+
"prerequisites": [],
203+
"difficulty": 8
204+
},
197205
{
198206
"slug": "anagram",
199207
"name": "Anagram",
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# SQLite-specific instructions
2+
3+
* The **digits** column contains a JSON-encoded list of integers.
4+
Example:
5+
```json
6+
[1,0,1,0,1,0]
7+
```
8+
* The **result** column should contain JSON-encoded data: an object with the digits as integers or a descripition of any errors.
9+
Examples:
10+
```json
11+
{"digits":[1,0,1,0,1,0]}
12+
```
13+
or
14+
```json
15+
{"error":"some error description"}
16+
```
17+
18+
## Table Schema
19+
20+
```sql
21+
CREATE TABLE IF NOT EXISTS "all-your-base" (
22+
input_base INTEGER NOT NULL,
23+
digits TEXT NOT NULL, -- json array
24+
output_base INTEGER NOT NULL,
25+
result TEXT -- json object
26+
);
27+
```
28+
29+
## JSON documentation
30+
31+
[JSON Functions And Operators][json-docs]
32+
33+
[json-docs]: https://www.sqlite.org/json1.htm
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Instructions
2+
3+
Convert a sequence of digits in one base, representing a number, into a sequence of digits in another base, representing the same number.
4+
5+
~~~~exercism/note
6+
Try to implement the conversion yourself.
7+
Do not use something else to perform the conversion for you.
8+
~~~~
9+
10+
## About [Positional Notation][positional-notation]
11+
12+
In positional notation, a number in base **b** can be understood as a linear combination of powers of **b**.
13+
14+
The number 42, _in base 10_, means:
15+
16+
`(4 × 10¹) + (2 × 10⁰)`
17+
18+
The number 101010, _in base 2_, means:
19+
20+
`(1 × 2⁵) + (0 × 2⁴) + (1 × 2³) + (0 × 2²) + (1 × 2¹) + (0 × 2⁰)`
21+
22+
The number 1120, _in base 3_, means:
23+
24+
`(1 × 3³) + (1 × 3²) + (2 × 3¹) + (0 × 3⁰)`
25+
26+
_Yes. Those three numbers above are exactly the same. Congratulations!_
27+
28+
[positional-notation]: https://en.wikipedia.org/wiki/Positional_notation
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Introduction
2+
3+
You've just been hired as professor of mathematics.
4+
Your first week went well, but something is off in your second week.
5+
The problem is that every answer given by your students is wrong!
6+
Luckily, your math skills have allowed you to identify the problem: the student answers _are_ correct, but they're all in base 2 (binary)!
7+
Amazingly, it turns out that each week, the students use a different base.
8+
To help you quickly verify the student answers, you'll be building a tool to translate between bases.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"authors": [
3+
"jimmytty"
4+
],
5+
"files": {
6+
"solution": [
7+
"all-your-base.sql"
8+
],
9+
"test": [
10+
"all-your-base_test.sql"
11+
],
12+
"example": [
13+
".meta/example.sql"
14+
]
15+
},
16+
"blurb": "Convert a number, represented as a sequence of digits in one base, to any other base."
17+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
UPDATE "all-your-base"
2+
SET result = JSON_OBJECT('error', 'input base must be >= 2')
3+
WHERE input_base < 2
4+
AND result ISNULL
5+
;
6+
UPDATE "all-your-base"
7+
SET result = JSON_OBJECT('error', 'output base must be >= 2')
8+
WHERE output_base < 2
9+
AND result ISNULL
10+
;
11+
UPDATE "all-your-base"
12+
SET result = JSON_OBJECT(
13+
'error', 'all digits must satisfy 0 <= d < input base'
14+
)
15+
WHERE (
16+
SELECT COUNT(*)
17+
FROM (
18+
SELECT input_base, j.VALUE AS digit
19+
FROM JSON_EACH(digits) j
20+
)
21+
WHERE digit < 0 OR digit >= input_base
22+
) != 0
23+
AND result ISNULL
24+
;
25+
26+
UPDATE "all-your-base"
27+
SET result = JSON_OBJECT('digits', JSON_ARRAY(0))
28+
WHERE (
29+
SELECT COUNT(v)
30+
FROM (
31+
SELECT j.VALUE v FROM JSON_EACH(digits) j
32+
)
33+
WHERE v != 0
34+
) = 0
35+
AND result ISNULL
36+
;
37+
38+
UPDATE "all-your-base"
39+
SET result = JSON_OBJECT('digits', (
40+
WITH RECURSIVE rcte (n, d) AS (
41+
VALUES((
42+
SELECT
43+
CAST(SUM(digit * POW(input_base, row_number - 1)) AS INTEGER)
44+
FROM (
45+
SELECT row_number() over() AS row_number, *
46+
FROM (
47+
SELECT j.VALUE AS digit
48+
FROM json_each(digits) j
49+
ORDER BY rowid DESC
50+
)
51+
)
52+
), -1)
53+
UNION ALL
54+
SELECT
55+
CAST(n % pow(10, CAST(log10(n) AS INT)) AS INT),
56+
CAST(n / pow(10, CAST(log10(n) AS INT)) AS INT)
57+
FROM rcte
58+
WHERE n != 0
59+
)
60+
SELECT JSON_GROUP_ARRAY(d) FROM rcte WHERE d > -1
61+
))
62+
WHERE output_base = 10
63+
AND result ISNULL
64+
;
65+
66+
UPDATE "all-your-base"
67+
SET result = JSON_OBJECT('digits', (
68+
WITH RECURSIVE rcte (n, d) AS (
69+
VALUES((
70+
SELECT GROUP_CONCAT(j.VALUE, '') * 1
71+
FROM JSON_EACH(digits) j
72+
), -1)
73+
UNION ALL
74+
SELECT n / output_base, n % output_base
75+
FROM rcte
76+
WHERE n > 0
77+
)
78+
SELECT JSON_GROUP_ARRAY(d)
79+
FROM (
80+
SELECT d
81+
FROM rcte
82+
WHERE d > -1
83+
ORDER BY row_number() OVER () DESC
84+
)
85+
))
86+
WHERE input_base = 10
87+
AND result ISNULL
88+
;
89+
90+
UPDATE "all-your-base"
91+
SET result = JSON_OBJECT('digits', (
92+
WITH RECURSIVE rcte (n, d) AS (
93+
VALUES((
94+
SELECT
95+
CAST(SUM(digit * POW(input_base, row_number - 1)) AS INTEGER)
96+
FROM (
97+
SELECT row_number() over() AS row_number, *
98+
FROM (
99+
SELECT j.VALUE AS digit
100+
FROM json_each(digits) j
101+
ORDER BY rowid DESC
102+
)
103+
)
104+
), -1)
105+
UNION ALL
106+
SELECT n / output_base, n % output_base
107+
FROM rcte
108+
WHERE n > 0
109+
)
110+
SELECT JSON_GROUP_ARRAY(d)
111+
FROM (
112+
SELECT d
113+
FROM rcte
114+
WHERE d > -1
115+
ORDER BY row_number() OVER () DESC
116+
)
117+
))
118+
WHERE input_base != 10
119+
AND output_base != 10
120+
AND result ISNULL
121+
;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[5ce422f9-7a4b-4f44-ad29-49c67cb32d2c]
13+
description = "single bit one to decimal"
14+
15+
[0cc3fea8-bb79-46ac-a2ab-5a2c93051033]
16+
description = "binary to single decimal"
17+
18+
[f12db0f9-0d3d-42c2-b3ba-e38cb375a2b8]
19+
description = "single decimal to binary"
20+
21+
[2c45cf54-6da3-4748-9733-5a3c765d925b]
22+
description = "binary to multiple decimal"
23+
24+
[65ddb8b4-8899-4fcc-8618-181b2cf0002d]
25+
description = "decimal to binary"
26+
27+
[8d418419-02a7-4824-8b7a-352d33c6987e]
28+
description = "trinary to hexadecimal"
29+
30+
[d3901c80-8190-41b9-bd86-38d988efa956]
31+
description = "hexadecimal to trinary"
32+
33+
[5d42f85e-21ad-41bd-b9be-a3e8e4258bbf]
34+
description = "15-bit integer"
35+
36+
[d68788f7-66dd-43f8-a543-f15b6d233f83]
37+
description = "empty list"
38+
39+
[5e27e8da-5862-4c5f-b2a9-26c0382b6be7]
40+
description = "single zero"
41+
42+
[2e1c2573-77e4-4b9c-8517-6c56c5bcfdf2]
43+
description = "multiple zeros"
44+
45+
[3530cd9f-8d6d-43f5-bc6e-b30b1db9629b]
46+
description = "leading zeros"
47+
48+
[a6b476a1-1901-4f2a-92c4-4d91917ae023]
49+
description = "input base is one"
50+
51+
[e21a693a-7a69-450b-b393-27415c26a016]
52+
description = "input base is zero"
53+
54+
[54a23be5-d99e-41cc-88e0-a650ffe5fcc2]
55+
description = "input base is negative"
56+
57+
[9eccf60c-dcc9-407b-95d8-c37b8be56bb6]
58+
description = "negative digit"
59+
60+
[232fa4a5-e761-4939-ba0c-ed046cd0676a]
61+
description = "invalid positive digit"
62+
63+
[14238f95-45da-41dc-95ce-18f860b30ad3]
64+
description = "output base is one"
65+
66+
[73dac367-da5c-4a37-95fe-c87fad0a4047]
67+
description = "output base is zero"
68+
69+
[13f81f42-ff53-4e24-89d9-37603a48ebd9]
70+
description = "output base is negative"
71+
72+
[0e6c895d-8a5d-4868-a345-309d094cfe8d]
73+
description = "both bases are negative"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- Schema: CREATE TABLE IF NOT EXISTS "all-your-base" (
2+
-- input_base INTEGER NOT NULL,
3+
-- digits TEXT NOT NULL, -- json array
4+
-- output_base INTEGER NOT NULL,
5+
-- result TEXT -- json object
6+
-- );
7+
-- Task: update the all-your-base table and set the result based on converting
8+
-- digits from input_base to output_base.
9+
-- * the digits column contains a JSON-encoded list of integers.
10+
-- * the result column should contain JSON-encoded data: an
11+
-- object with the digits as integers or a descripition of any errors.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
-- Create database:
2+
.read ./create_fixture.sql
3+
4+
-- Read user student solution and save any output as markdown in user_output.md:
5+
.mode markdown
6+
.output user_output.md
7+
.read ./all-your-base.sql
8+
.output
9+
10+
-- Create a clean testing environment:
11+
.read ./create_test_table.sql
12+
13+
-- Comparison of user input and the tests updates the status for each test:
14+
UPDATE tests
15+
SET status = 'pass'
16+
FROM (SELECT input_base, digits, output_base, result FROM "all-your-base") AS actual
17+
WHERE (actual.input_base, actual.digits, actual.output_base, JSON(actual.result)) = (tests.input_base, tests.digits, tests.output_base, JSON(tests.expected));
18+
19+
-- Update message for failed tests to give helpful information:
20+
UPDATE tests
21+
SET message = (
22+
'Result for "'
23+
|| JSON_OBJECT(
24+
'input_base', tests.input_base,
25+
'digits', JSON(tests.digits),
26+
'output_base', tests.output_base
27+
)
28+
|| '"'
29+
|| ' is <' || COALESCE(actual.result, 'NULL')
30+
|| '> but should be <' || tests.expected || '>'
31+
)
32+
FROM (SELECT input_base, digits, output_base, result FROM "all-your-base") AS actual
33+
WHERE (actual.input_base, actual.digits, actual.output_base) = (tests.input_base, tests.digits, tests.output_base) AND tests.status = 'fail';
34+
35+
-- Save results to ./output.json (needed by the online test-runner)
36+
.mode json
37+
.once './output.json'
38+
SELECT description, status, message, output, test_code, task_id
39+
FROM tests;
40+
41+
-- Display test results in readable form for the student:
42+
.mode table
43+
SELECT description, status, message
44+
FROM tests;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
DROP TABLE IF EXISTS "all-your-base";
2+
CREATE TABLE "all-your-base" (
3+
input_base INTEGER NOT NULL,
4+
digits TEXT NOT NULL, -- json array
5+
output_base INTEGER NOT NULL,
6+
result TEXT -- json object
7+
);
8+
9+
.mode csv
10+
.import ./data.csv "all-your-base"
11+
12+
UPDATE "all-your-base" SET result = NULL;

0 commit comments

Comments
 (0)