Skip to content

Commit c8734ec

Browse files
authored
new exercise: ocr-numbers (#148)
1 parent 861c3b7 commit c8734ec

14 files changed

+8991
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,14 @@
367367
"prerequisites": [],
368368
"difficulty": 8
369369
},
370+
{
371+
"slug": "ocr-numbers",
372+
"name": "OCR Numbers",
373+
"uuid": "5bacd600-5030-4bef-9dbe-4bbd807b3d23",
374+
"practices": [],
375+
"prerequisites": [],
376+
"difficulty": 8
377+
},
370378
{
371379
"slug": "minesweeper",
372380
"name": "Minesweeper",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Reserved Memory
2+
3+
Bytes 64-191 of the linear memory are reserved for the input string.
4+
5+
The input string can be modified in place if desired.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Instructions
2+
3+
Given a 3 x 4 grid of pipes, underscores, and spaces, determine which number is represented, or whether it is garbled.
4+
5+
## Step One
6+
7+
To begin with, convert a simple binary font to a string containing 0 or 1.
8+
9+
The binary font uses pipes and underscores, four rows high and three columns wide.
10+
11+
```text
12+
_ #
13+
| | # zero.
14+
|_| #
15+
# the fourth row is always blank
16+
```
17+
18+
Is converted to "0"
19+
20+
```text
21+
#
22+
| # one.
23+
| #
24+
# (blank fourth row)
25+
```
26+
27+
Is converted to "1"
28+
29+
If the input is the correct size, but not recognizable, your program should return '?'
30+
31+
If the input is the incorrect size, your program should return an error.
32+
33+
## Step Two
34+
35+
Update your program to recognize multi-character binary strings, replacing garbled numbers with ?
36+
37+
## Step Three
38+
39+
Update your program to recognize all numbers 0 through 9, both individually and as part of a larger string.
40+
41+
```text
42+
_
43+
_|
44+
|_
45+
46+
```
47+
48+
Is converted to "2"
49+
50+
```text
51+
_ _ _ _ _ _ _ _ #
52+
| _| _||_||_ |_ ||_||_|| | # decimal numbers.
53+
||_ _| | _||_| ||_| _||_| #
54+
# fourth line is always blank
55+
```
56+
57+
Is converted to "1234567890"
58+
59+
## Step Four
60+
61+
Update your program to handle multiple numbers, one per line.
62+
When converting several lines, join the lines with commas.
63+
64+
```text
65+
_ _
66+
| _| _|
67+
||_ _|
68+
69+
_ _
70+
|_||_ |_
71+
| _||_|
72+
73+
_ _ _
74+
||_||_|
75+
||_| _|
76+
77+
```
78+
79+
Is converted to "123,456,789".
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"root": true,
3+
"extends": "@exercism/eslint-config-javascript",
4+
"env": {
5+
"jest": true
6+
},
7+
"overrides": [
8+
{
9+
"files": [
10+
"*.spec.js"
11+
],
12+
"excludedFiles": [
13+
"custom.spec.js"
14+
],
15+
"extends": "@exercism/eslint-config-javascript/maintainers"
16+
}
17+
]
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"authors": [
3+
"atk"
4+
],
5+
"files": {
6+
"solution": [
7+
"ocr-numbers.wat"
8+
],
9+
"test": [
10+
"ocr-numbers.spec.js"
11+
],
12+
"example": [
13+
".meta/proof.ci.wat"
14+
],
15+
"invalidator": [
16+
"package.json"
17+
]
18+
},
19+
"blurb": "Given a 3 x 4 grid of pipes, underscores, and spaces, determine which number is represented, or whether it is garbled.",
20+
"source": "Inspired by the Bank OCR kata",
21+
"source_url": "https://codingdojo.org/kata/BankOCR/",
22+
"custom": {
23+
"version.tests.compatibility": "jest-27",
24+
"flag.tests.task-per-describe": false,
25+
"flag.tests.may-run-long": false,
26+
"flag.tests.includes-optional": false
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
2+
3+
(module
4+
(memory (export "mem") 2)
5+
6+
(data $digits (i32.const 0) "\77\24\5d\6d\2e\6b\7b\25\7f\6f")
7+
8+
(global $lineBreak i32 (i32.const 10))
9+
(global $vertical i32 (i32.const 124))
10+
(global $horizontal i32 (i32.const 95))
11+
(global $zero i32 (i32.const 48))
12+
(global $unknown i32 (i32.const 63))
13+
(global $comma i32 (i32.const 44))
14+
(global $outputOffset i32 (i32.const 256))
15+
16+
;;
17+
;; Converts 7-bit multi-character numbers into a number string
18+
;;
19+
;; @param {i32} $inputOffset - offset of the input in linear memory
20+
;; @param {i32} $inputLength - length of the input in linear memory
21+
;;
22+
;; @returns {(i32,i32)} - offset and length of output in linear memory
23+
(func (export "convert") (param $inputOffset i32) (param $inputLength i32) (result i32 i32)
24+
(local $inputPos i32)
25+
(local $inputPtr i32)
26+
(local $lineLength i32)
27+
(local $lines i32)
28+
(local $digit i32)
29+
(local $outputLength i32)
30+
(local.set $lineLength (i32.const -1))
31+
(loop $measureLine
32+
(local.set $lineLength (i32.add (local.get $lineLength) (i32.const 1)))
33+
(br_if $measureLine
34+
(i32.ne (i32.load8_u (i32.add (local.get $inputOffset)
35+
(local.get $lineLength)))
36+
(global.get $lineBreak)))
37+
)
38+
(local.set $lineLength (i32.add (local.get $lineLength) (i32.const 1)))
39+
(loop $readDigits
40+
(local.set $inputPtr (i32.add (local.get $inputOffset) (local.get $inputPos)))
41+
;; generate bitmask from segments
42+
(local.set $lines (i32.or (i32.or (i32.or (i32.or (i32.or (i32.or
43+
;; bit 1: top
44+
(i32.eq (i32.load8_u (i32.add (local.get $inputPtr) (i32.const 1)))
45+
(global.get $horizontal))
46+
;; bit 2: upper left
47+
(i32.shl (i32.eq (i32.load8_u (i32.add (local.get $inputPtr)
48+
(local.get $lineLength))) (global.get $vertical)) (i32.const 1)))
49+
;; bit 3: upper right
50+
(i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr)
51+
(local.get $lineLength)) (i32.const 2))) (global.get $vertical)) (i32.const 2)))
52+
;; bit 4: middle
53+
(i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr)
54+
(local.get $lineLength)) (i32.const 1))) (global.get $horizontal)) (i32.const 3)))
55+
;; bit 5: lower left
56+
(i32.shl (i32.eq (i32.load8_u (i32.add (local.get $inputPtr)
57+
(i32.shl (local.get $lineLength) (i32.const 1))))
58+
(global.get $vertical)) (i32.const 4)))
59+
;; bit 6: lower right
60+
(i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr)
61+
(i32.shl (local.get $lineLength) (i32.const 1))) (i32.const 2)))
62+
(global.get $vertical)) (i32.const 5)))
63+
;; bit 7: bottom
64+
(i32.shl (i32.eq (i32.load8_u (i32.add (i32.add (local.get $inputPtr)
65+
(i32.shl (local.get $lineLength) (i32.const 1))) (i32.const 1)))
66+
(global.get $horizontal)) (i32.const 6))))
67+
;; bitmask index in data is number; 10 = not found ('?')
68+
(local.set $digit (i32.const -1))
69+
(loop $findDigit
70+
(local.set $digit (i32.add (local.get $digit) (i32.const 1)))
71+
(br_if $findDigit (i32.and (i32.lt_s (local.get $digit) (i32.const 10))
72+
(i32.ne (local.get $lines) (i32.load8_u (local.get $digit)))))
73+
)
74+
;; write number or question mark
75+
(i32.store8 (i32.add (global.get $outputOffset) (local.get $outputLength))
76+
(select (i32.add (local.get $digit) (global.get $zero)) (global.get $unknown)
77+
(i32.lt_u (local.get $digit) (i32.const 10))))
78+
(local.set $outputLength (i32.add (local.get $outputLength) (i32.const 1)))
79+
(local.set $inputPos (i32.add (local.get $inputPos) (i32.const 3)))
80+
;; line break
81+
(if (i32.eqz (i32.rem_u (i32.add (local.get $inputPos) (i32.const 1))
82+
(local.get $lineLength))) (then
83+
(i32.store8 (i32.add (global.get $outputOffset) (local.get $outputLength)) (global.get $comma))
84+
(local.set $outputLength (i32.add (local.get $outputLength) (i32.const 1)))
85+
(local.set $inputPos
86+
(i32.add (i32.add (local.get $inputPos) (i32.const 1))
87+
(i32.mul (local.get $lineLength) (i32.const 3))))
88+
))
89+
(br_if $readDigits (i32.lt_u (local.get $inputPos) (local.get $inputLength)))
90+
)
91+
;; remove superfluous ','
92+
(global.get $outputOffset) (i32.sub (local.get $outputLength) (i32.const 1))
93+
)
94+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
[5ee54e1a-b554-4bf3-a056-9a7976c3f7e8]
13+
description = "Recognizes 0"
14+
15+
[027ada25-17fd-4d78-aee6-35a19623639d]
16+
description = "Recognizes 1"
17+
18+
[3cce2dbd-01d9-4f94-8fae-419a822e89bb]
19+
description = "Unreadable but correctly sized inputs return ?"
20+
21+
[cb19b733-4e36-4cf9-a4a1-6e6aac808b9a]
22+
description = "Input with a number of lines that is not a multiple of four raises an error"
23+
24+
[235f7bd1-991b-4587-98d4-84206eec4cc6]
25+
description = "Input with a number of columns that is not a multiple of three raises an error"
26+
27+
[4a841794-73c9-4da9-a779-1f9837faff66]
28+
description = "Recognizes 110101100"
29+
30+
[70c338f9-85b1-4296-a3a8-122901cdfde8]
31+
description = "Garbled numbers in a string are replaced with ?"
32+
33+
[ea494ff4-3610-44d7-ab7e-72fdef0e0802]
34+
description = "Recognizes 2"
35+
36+
[1acd2c00-412b-4268-93c2-bd7ff8e05a2c]
37+
description = "Recognizes 3"
38+
39+
[eaec6a15-be17-4b6d-b895-596fae5d1329]
40+
description = "Recognizes 4"
41+
42+
[440f397a-f046-4243-a6ca-81ab5406c56e]
43+
description = "Recognizes 5"
44+
45+
[f4c9cf6a-f1e2-4878-bfc3-9b85b657caa0]
46+
description = "Recognizes 6"
47+
48+
[e24ebf80-c611-41bb-a25a-ac2c0f232df5]
49+
description = "Recognizes 7"
50+
51+
[b79cad4f-e264-4818-9d9e-77766792e233]
52+
description = "Recognizes 8"
53+
54+
[5efc9cfc-9227-4688-b77d-845049299e66]
55+
description = "Recognizes 9"
56+
57+
[f60cb04a-42be-494e-a535-3451c8e097a4]
58+
description = "Recognizes string of decimal numbers"
59+
60+
[b73ecf8b-4423-4b36-860d-3710bdb8a491]
61+
description = "Numbers separated by empty lines are recognized. Lines are joined by commas."

exercises/practice/ocr-numbers/.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
audit=false
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Exercism
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default {
2+
presets: ["@exercism/babel-preset-javascript"],
3+
plugins: [],
4+
};

0 commit comments

Comments
 (0)