Skip to content

Commit 499f026

Browse files
authored
Add crypto-square (#117)
1 parent 275b10e commit 499f026

9 files changed

Lines changed: 220 additions & 0 deletions

File tree

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,14 @@
594594
"prerequisites": [],
595595
"difficulty": 5
596596
},
597+
{
598+
"slug": "crypto-square",
599+
"name": "Crypto Square",
600+
"uuid": "7e4ad5c7-fe53-4f7b-ac20-8f4c03799194",
601+
"practices": [],
602+
"prerequisites": [],
603+
"difficulty": 5
604+
},
597605
{
598606
"slug": "flower-field",
599607
"name": "Flower Field",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
return {
2+
default = {
3+
ROOT = { '.' }
4+
}
5+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Instructions
2+
3+
Implement the classic method for composing secret messages called a square code.
4+
5+
Given an English text, output the encoded version of that text.
6+
7+
First, the input is normalized: the spaces and punctuation are removed from the English text and the message is down-cased.
8+
9+
Then, the normalized characters are broken into rows.
10+
These rows can be regarded as forming a rectangle when printed with intervening newlines.
11+
12+
For example, the sentence
13+
14+
```text
15+
"If man was meant to stay on the ground, god would have given us roots."
16+
```
17+
18+
is normalized to:
19+
20+
```text
21+
"ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots"
22+
```
23+
24+
The plaintext should be organized into a rectangle as square as possible.
25+
The size of the rectangle should be decided by the length of the message.
26+
27+
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:
28+
29+
- `r * c >= length of message`,
30+
- and `c >= r`,
31+
- and `c - r <= 1`.
32+
33+
Our normalized text is 54 characters long, dictating a rectangle with `c = 8` and `r = 7`:
34+
35+
```text
36+
"ifmanwas"
37+
"meanttos"
38+
"tayonthe"
39+
"groundgo"
40+
"dwouldha"
41+
"vegivenu"
42+
"sroots "
43+
```
44+
45+
The coded message is obtained by reading down the columns going left to right.
46+
47+
The message above is coded as:
48+
49+
```text
50+
"imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau"
51+
```
52+
53+
Output the encoded text in chunks that fill perfect rectangles `(r X c)`, with `c` chunks of `r` length, separated by spaces.
54+
For phrases that are `n` characters short of the perfect rectangle, pad each of the last `n` chunks with a single trailing space.
55+
56+
```text
57+
"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau "
58+
```
59+
60+
Notice that were we to stack these, we could visually decode the ciphertext back in to the original message:
61+
62+
```text
63+
"imtgdvs"
64+
"fearwer"
65+
"mayoogo"
66+
"anouuio"
67+
"ntnnlvt"
68+
"wttddes"
69+
"aohghn "
70+
"sseoau "
71+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"glennj"
4+
],
5+
"files": {
6+
"solution": [
7+
"crypto_square.moon"
8+
],
9+
"test": [
10+
"crypto_square_spec.moon"
11+
],
12+
"example": [
13+
".meta/example.moon"
14+
]
15+
},
16+
"blurb": "Implement the classic method for composing secret messages called a square code.",
17+
"source": "J Dalbey's Programming Practice problems",
18+
"source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html"
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
pad = (str, width) -> string.format "%-#{width}s", str
2+
3+
join = table.concat
4+
5+
encode = (text) ->
6+
clean = text\gsub('[^%a%d]', '')\lower!
7+
return '' if clean == ''
8+
len = math.ceil math.sqrt #clean
9+
10+
segments = {}
11+
for i = 1, #clean, len
12+
table.insert segments, clean\sub(i, i + len - 1)
13+
14+
-- pad the last segment
15+
segments[#segments] = pad segments[#segments], len
16+
17+
transposed = [join [s\sub(i,i) for s in *segments] for i = 1, len]
18+
join transposed, " "
19+
20+
21+
{ :encode }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
module_imports: {'encode'},
3+
4+
generate_test: (case, level) ->
5+
lines = {
6+
"result = encode #{quote case.input.plaintext}",
7+
"expected = #{quote case.expected}",
8+
"assert.are.equal expected, result"
9+
}
10+
table.concat [indent line, level for line in *lines], '\n'
11+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
[407c3837-9aa7-4111-ab63-ec54b58e8e9f]
13+
description = "empty plaintext results in an empty ciphertext"
14+
15+
[aad04a25-b8bb-4304-888b-581bea8e0040]
16+
description = "normalization results in empty plaintext"
17+
18+
[64131d65-6fd9-4f58-bdd8-4a2370fb481d]
19+
description = "Lowercase"
20+
21+
[63a4b0ed-1e3c-41ea-a999-f6f26ba447d6]
22+
description = "Remove spaces"
23+
24+
[1b5348a1-7893-44c1-8197-42d48d18756c]
25+
description = "Remove punctuation"
26+
27+
[8574a1d3-4a08-4cec-a7c7-de93a164f41a]
28+
description = "9 character plaintext results in 3 chunks of 3 characters"
29+
30+
[a65d3fa1-9e09-43f9-bcec-7a672aec3eae]
31+
description = "8 character plaintext results in 3 chunks, the last one with a trailing space"
32+
33+
[fbcb0c6d-4c39-4a31-83f6-c473baa6af80]
34+
description = "54 character plaintext results in 7 chunks, the last two with trailing spaces"
35+
include = false
36+
37+
[33fd914e-fa44-445b-8f38-ff8fbc9fe6e6]
38+
description = "54 character plaintext results in 8 chunks, the last two with trailing spaces"
39+
reimplements = "fbcb0c6d-4c39-4a31-83f6-c473baa6af80"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
encode: (plaintext) ->
3+
error 'Implement me'
4+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import encode from require 'crypto_square'
2+
3+
describe 'crypto-square', ->
4+
it 'empty plaintext results in an empty ciphertext', ->
5+
result = encode ''
6+
expected = ''
7+
assert.are.equal expected, result
8+
9+
pending 'normalization results in empty plaintext', ->
10+
result = encode '... --- ...'
11+
expected = ''
12+
assert.are.equal expected, result
13+
14+
pending 'Lowercase', ->
15+
result = encode 'A'
16+
expected = 'a'
17+
assert.are.equal expected, result
18+
19+
pending 'Remove spaces', ->
20+
result = encode ' b '
21+
expected = 'b'
22+
assert.are.equal expected, result
23+
24+
pending 'Remove punctuation', ->
25+
result = encode '@1,%!'
26+
expected = '1'
27+
assert.are.equal expected, result
28+
29+
pending '9 character plaintext results in 3 chunks of 3 characters', ->
30+
result = encode 'This is fun!'
31+
expected = 'tsf hiu isn'
32+
assert.are.equal expected, result
33+
34+
pending '8 character plaintext results in 3 chunks, the last one with a trailing space', ->
35+
result = encode 'Chill out.'
36+
expected = 'clu hlt io '
37+
assert.are.equal expected, result
38+
39+
pending '54 character plaintext results in 8 chunks, the last two with trailing spaces', ->
40+
result = encode 'If man was meant to stay on the ground, god would have given us roots.'
41+
expected = 'imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau '
42+
assert.are.equal expected, result

0 commit comments

Comments
 (0)