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 @@ -594,6 +594,14 @@
"prerequisites": [],
"difficulty": 5
},
{
"slug": "crypto-square",
"name": "Crypto Square",
"uuid": "7e4ad5c7-fe53-4f7b-ac20-8f4c03799194",
"practices": [],
"prerequisites": [],
"difficulty": 5
},
{
"slug": "flower-field",
"name": "Flower Field",
Expand Down
5 changes: 5 additions & 0 deletions exercises/practice/crypto-square/.busted
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
return {
default = {
ROOT = { '.' }
}
}
71 changes: 71 additions & 0 deletions exercises/practice/crypto-square/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Instructions

Implement the classic method for composing secret messages called a square code.

Given an English text, output the encoded version of that text.

First, the input is normalized: the spaces and punctuation are removed from the English text and the message is down-cased.

Then, the normalized characters are broken into rows.
These rows can be regarded as forming a rectangle when printed with intervening newlines.

For example, the sentence

```text
"If man was meant to stay on the ground, god would have given us roots."
```

is normalized to:

```text
"ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots"
```

The plaintext should be organized into a rectangle as square as possible.
The size of the rectangle should be decided by the length of the message.

If `c` is the number of columns and `r` is the number of rows, then for the rectangle `r` x `c` find the smallest possible integer `c` such that:

- `r * c >= length of message`,
- and `c >= r`,
- and `c - r <= 1`.

Our normalized text is 54 characters long, dictating a rectangle with `c = 8` and `r = 7`:

```text
"ifmanwas"
"meanttos"
"tayonthe"
"groundgo"
"dwouldha"
"vegivenu"
"sroots "
```

The coded message is obtained by reading down the columns going left to right.

The message above is coded as:

```text
"imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau"
```

Output the encoded text in chunks that fill perfect rectangles `(r X c)`, with `c` chunks of `r` length, separated by spaces.
For phrases that are `n` characters short of the perfect rectangle, pad each of the last `n` chunks with a single trailing space.

```text
"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau "
```

Notice that were we to stack these, we could visually decode the ciphertext back in to the original message:

```text
"imtgdvs"
"fearwer"
"mayoogo"
"anouuio"
"ntnnlvt"
"wttddes"
"aohghn "
"sseoau "
```
19 changes: 19 additions & 0 deletions exercises/practice/crypto-square/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"glennj"
],
"files": {
"solution": [
"crypto_square.moon"
],
"test": [
"crypto_square_spec.moon"
],
"example": [
".meta/example.moon"
]
},
"blurb": "Implement the classic method for composing secret messages called a square code.",
"source": "J Dalbey's Programming Practice problems",
"source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html"
}
21 changes: 21 additions & 0 deletions exercises/practice/crypto-square/.meta/example.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pad = (str, width) -> string.format "%-#{width}s", str

join = table.concat

encode = (text) ->
clean = text\gsub('[^%a%d]', '')\lower!
return '' if clean == ''
len = math.ceil math.sqrt #clean

segments = {}
for i = 1, #clean, len
table.insert segments, clean\sub(i, i + len - 1)

-- pad the last segment
segments[#segments] = pad segments[#segments], len

transposed = [join [s\sub(i,i) for s in *segments] for i = 1, len]
join transposed, " "


{ :encode }
11 changes: 11 additions & 0 deletions exercises/practice/crypto-square/.meta/spec_generator.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
module_imports: {'encode'},

generate_test: (case, level) ->
lines = {
"result = encode #{quote case.input.plaintext}",
"expected = #{quote case.expected}",
"assert.are.equal expected, result"
}
table.concat [indent line, level for line in *lines], '\n'
}
39 changes: 39 additions & 0 deletions exercises/practice/crypto-square/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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.

[407c3837-9aa7-4111-ab63-ec54b58e8e9f]
description = "empty plaintext results in an empty ciphertext"

[aad04a25-b8bb-4304-888b-581bea8e0040]
description = "normalization results in empty plaintext"

[64131d65-6fd9-4f58-bdd8-4a2370fb481d]
description = "Lowercase"

[63a4b0ed-1e3c-41ea-a999-f6f26ba447d6]
description = "Remove spaces"

[1b5348a1-7893-44c1-8197-42d48d18756c]
description = "Remove punctuation"

[8574a1d3-4a08-4cec-a7c7-de93a164f41a]
description = "9 character plaintext results in 3 chunks of 3 characters"

[a65d3fa1-9e09-43f9-bcec-7a672aec3eae]
description = "8 character plaintext results in 3 chunks, the last one with a trailing space"

[fbcb0c6d-4c39-4a31-83f6-c473baa6af80]
description = "54 character plaintext results in 7 chunks, the last two with trailing spaces"
include = false

[33fd914e-fa44-445b-8f38-ff8fbc9fe6e6]
description = "54 character plaintext results in 8 chunks, the last two with trailing spaces"
reimplements = "fbcb0c6d-4c39-4a31-83f6-c473baa6af80"
4 changes: 4 additions & 0 deletions exercises/practice/crypto-square/crypto_square.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
encode: (plaintext) ->
error 'Implement me'
}
42 changes: 42 additions & 0 deletions exercises/practice/crypto-square/crypto_square_spec.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import encode from require 'crypto_square'

describe 'crypto-square', ->
it 'empty plaintext results in an empty ciphertext', ->
result = encode ''
expected = ''
assert.are.equal expected, result

pending 'normalization results in empty plaintext', ->
result = encode '... --- ...'
expected = ''
assert.are.equal expected, result

pending 'Lowercase', ->
result = encode 'A'
expected = 'a'
assert.are.equal expected, result

pending 'Remove spaces', ->
result = encode ' b '
expected = 'b'
assert.are.equal expected, result

pending 'Remove punctuation', ->
result = encode '@1,%!'
expected = '1'
assert.are.equal expected, result

pending '9 character plaintext results in 3 chunks of 3 characters', ->
result = encode 'This is fun!'
expected = 'tsf hiu isn'
assert.are.equal expected, result

pending '8 character plaintext results in 3 chunks, the last one with a trailing space', ->
result = encode 'Chill out.'
expected = 'clu hlt io '
assert.are.equal expected, result

pending '54 character plaintext results in 8 chunks, the last two with trailing spaces', ->
result = encode 'If man was meant to stay on the ground, god would have given us roots.'
expected = 'imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau '
assert.are.equal expected, result
Loading