Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,14 @@
"prerequisites": [],
"difficulty": 5
},
{
"slug": "ocr-numbers",
"name": "OCR Numbers",
"uuid": "52d9b8d1-7dcd-4056-8a13-cd74a65b6187",
"practices": [],
"prerequisites": [],
"difficulty": 5
},
{
"slug": "pig-latin",
"name": "Pig Latin",
Expand Down
5 changes: 5 additions & 0 deletions exercises/practice/ocr-numbers/.busted
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
return {
default = {
ROOT = { '.' }
}
}
47 changes: 47 additions & 0 deletions exercises/practice/ocr-numbers/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Instructions

Optical Character Recognition or OCR is software that converts images of text into machine-readable text.
Given a grid of characters representing some digits, convert the grid to a string of digits.
If the grid has multiple rows of cells, the rows should be separated in the output with a `","`.

- The grid is made of one of more lines of cells.
- Each line of the grid is made of one or more cells.
- Each cell is three columns wide and four rows high (3x4) and represents one digit.
- Digits are drawn using pipes (`"|"`), underscores (`"_"`), and spaces (`" "`).

## Edge cases

- If the input is not a valid size, your program should indicate there is an error.
- If the input is the correct size, but a cell is not recognizable, your program should output a `"?"` for that character.

## Examples

The following input (without the comments) is converted to `"1234567890"`.

```text
_ _ _ _ _ _ _ _ #
| _| _||_||_ |_ ||_||_|| | # Decimal numbers.
||_ _| | _||_| ||_| _||_| #
# The fourth line is always blank,
```

The following input is converted to `"123,456,789"`.

<!-- prettier-ignore-start -->

```text
_ _
| _| _|
||_ _|

_ _
|_||_ |_
| _||_|

_ _ _
||_||_|
||_| _|

```

<!-- prettier-ignore-end -->
6 changes: 6 additions & 0 deletions exercises/practice/ocr-numbers/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Introduction

Your best friend Marta recently landed their dream job working with a local history museum's collections.
Knowing of your interests in programming, they confide in you about an issue at work for an upcoming exhibit on computing history.
A local university's math department had donated several boxes of historical printouts, but given the poor condition of the documents, the decision has been made to digitize the text.
However, the university's old printer had some quirks in how text was represented, and your friend could use your help to extract the data successfully.
19 changes: 19 additions & 0 deletions exercises/practice/ocr-numbers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"glennj"
],
"files": {
"solution": [
"ocr_numbers.moon"
],
"test": [
"ocr_numbers_spec.moon"
],
"example": [
".meta/example.moon"
]
},
"blurb": "Given a 3 x 4 grid of pipes, underscores, and spaces, determine which number is represented, or whether it is garbled.",
"source": "Inspired by the Bank OCR kata",
"source_url": "https://codingdojo.org/kata/BankOCR/"
}
31 changes: 31 additions & 0 deletions exercises/practice/ocr-numbers/.meta/example.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
List = require 'pl.List'

digits = {
' _ | ||_| ': "0"
' | | ': "1"
' _ _||_ ': "2"
' _ _| _| ': "3"
' |_| | ': "4"
' _ |_ _| ': "5"
' _ |_ |_| ': "6"
' _ | | ': "7"
' _ |_||_| ': "8"
' _ |_| _| ': "9"
}


toNumber = (row) ->
chunks = [table.concat [line\sub(i, i+2) for line in *row] for i = 1, #row[1], 3]
table.concat [digits[chunk] or "?" for chunk in *chunks]


convert = (rows) ->
rows = List rows
assert #rows % 4 == 0, "Number of input lines is not a multiple of four"
assert #rows[1] % 3 == 0, "Number of input columns is not a multiple of three"

numbers = [toNumber rows\slice(i, i+3) for i = 1, #rows, 4]
table.concat numbers, ','


{ :convert }
14 changes: 14 additions & 0 deletions exercises/practice/ocr-numbers/.meta/generator.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import convert from require <%- h.quote(slug.snake) %>

describe <%- h.quote(slug.kebab .. ':') %>, ->
<% for i, case in ipairs(data.cases) do -%>
<%= test_cmd(i == 1) %> <%- h.quote(case.description) %>, ->
rows = <%- h.string_list(case.input.rows, 2, {inline=0}) %>
<% if not case.expected.error then -%>
assert.are.equal <%- h.quote(case.expected) %>, convert rows
<% else -%>
f = -> <%= case.property %> rows
assert.has.errors f, <%- h.quote(case.expected.error) %>
<% end -%>

<% end -%>
61 changes: 61 additions & 0 deletions exercises/practice/ocr-numbers/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[5ee54e1a-b554-4bf3-a056-9a7976c3f7e8]
description = "Recognizes 0"

[027ada25-17fd-4d78-aee6-35a19623639d]
description = "Recognizes 1"

[3cce2dbd-01d9-4f94-8fae-419a822e89bb]
description = "Unreadable but correctly sized inputs return ?"

[cb19b733-4e36-4cf9-a4a1-6e6aac808b9a]
description = "Input with a number of lines that is not a multiple of four raises an error"

[235f7bd1-991b-4587-98d4-84206eec4cc6]
description = "Input with a number of columns that is not a multiple of three raises an error"

[4a841794-73c9-4da9-a779-1f9837faff66]
description = "Recognizes 110101100"

[70c338f9-85b1-4296-a3a8-122901cdfde8]
description = "Garbled numbers in a string are replaced with ?"

[ea494ff4-3610-44d7-ab7e-72fdef0e0802]
description = "Recognizes 2"

[1acd2c00-412b-4268-93c2-bd7ff8e05a2c]
description = "Recognizes 3"

[eaec6a15-be17-4b6d-b895-596fae5d1329]
description = "Recognizes 4"

[440f397a-f046-4243-a6ca-81ab5406c56e]
description = "Recognizes 5"

[f4c9cf6a-f1e2-4878-bfc3-9b85b657caa0]
description = "Recognizes 6"

[e24ebf80-c611-41bb-a25a-ac2c0f232df5]
description = "Recognizes 7"

[b79cad4f-e264-4818-9d9e-77766792e233]
description = "Recognizes 8"

[5efc9cfc-9227-4688-b77d-845049299e66]
description = "Recognizes 9"

[f60cb04a-42be-494e-a535-3451c8e097a4]
description = "Recognizes string of decimal numbers"

[b73ecf8b-4423-4b36-860d-3710bdb8a491]
description = "Numbers separated by empty lines are recognized. Lines are joined by commas."
4 changes: 4 additions & 0 deletions exercises/practice/ocr-numbers/ocr_numbers.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
convert: (rows) ->
error 'Implement me'
}
165 changes: 165 additions & 0 deletions exercises/practice/ocr-numbers/ocr_numbers_spec.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import convert from require 'ocr_numbers'

describe 'ocr-numbers:', ->
it 'Recognizes 0', ->
rows = {
' _ ',
'| |',
'|_|',
' ',
}
assert.are.equal '0', convert rows

pending 'Recognizes 1', ->
rows = {
' ',
' |',
' |',
' ',
}
assert.are.equal '1', convert rows

pending 'Unreadable but correctly sized inputs return ?', ->
rows = {
' ',
' _',
' |',
' ',
}
assert.are.equal '?', convert rows

pending 'Input with a number of lines that is not a multiple of four raises an error', ->
rows = {
' _ ',
'| |',
' ',
}
f = -> convert rows
assert.has.errors f, 'Number of input lines is not a multiple of four'

pending 'Input with a number of columns that is not a multiple of three raises an error', ->
rows = {
' ',
' |',
' |',
' ',
}
f = -> convert rows
assert.has.errors f, 'Number of input columns is not a multiple of three'

pending 'Recognizes 110101100', ->
rows = {
' _ _ _ _ ',
' | || | || | | || || |',
' | ||_| ||_| | ||_||_|',
' ',
}
assert.are.equal '110101100', convert rows

pending 'Garbled numbers in a string are replaced with ?', ->
rows = {
' _ _ _ ',
' | || | || | || || |',
' | | _| ||_| | ||_||_|',
' ',
}
assert.are.equal '11?10?1?0', convert rows

pending 'Recognizes 2', ->
rows = {
' _ ',
' _|',
'|_ ',
' ',
}
assert.are.equal '2', convert rows

pending 'Recognizes 3', ->
rows = {
' _ ',
' _|',
' _|',
' ',
}
assert.are.equal '3', convert rows

pending 'Recognizes 4', ->
rows = {
' ',
'|_|',
' |',
' ',
}
assert.are.equal '4', convert rows

pending 'Recognizes 5', ->
rows = {
' _ ',
'|_ ',
' _|',
' ',
}
assert.are.equal '5', convert rows

pending 'Recognizes 6', ->
rows = {
' _ ',
'|_ ',
'|_|',
' ',
}
assert.are.equal '6', convert rows

pending 'Recognizes 7', ->
rows = {
' _ ',
' |',
' |',
' ',
}
assert.are.equal '7', convert rows

pending 'Recognizes 8', ->
rows = {
' _ ',
'|_|',
'|_|',
' ',
}
assert.are.equal '8', convert rows

pending 'Recognizes 9', ->
rows = {
' _ ',
'|_|',
' _|',
' ',
}
assert.are.equal '9', convert rows

pending 'Recognizes string of decimal numbers', ->
rows = {
' _ _ _ _ _ _ _ _ ',
' | _| _||_||_ |_ ||_||_|| |',
' ||_ _| | _||_| ||_| _||_|',
' ',
}
assert.are.equal '1234567890', convert rows

pending 'Numbers separated by empty lines are recognized. Lines are joined by commas.', ->
rows = {
' _ _ ',
' | _| _|',
' ||_ _|',
' ',
' _ _ ',
'|_||_ |_ ',
' | _||_|',
' ',
' _ _ _ ',
' ||_||_|',
' ||_| _|',
' ',
}
assert.are.equal '123,456,789', convert rows

Loading