Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add crypto-square exercise #261

Merged
merged 1 commit into from
Jun 5, 2024
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 @@ -234,6 +234,14 @@
"prerequisites": [],
"difficulty": 5
},
{
"slug": "crypto-square",
"name": "Crypto Square",
"uuid": "de268eb1-66a8-4094-b19f-25da515fb7ac",
"practices": [],
"prerequisites": [],
"difficulty": 7
},
{
"slug": "nth-prime",
"name": "Nth Prime",
Expand Down
6 changes: 6 additions & 0 deletions exercises/practice/crypto-square/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Hints

## General

- The `$t0-9` registers can be used to temporarily store values
- The instructions specify which registers are used as input and output
9 changes: 9 additions & 0 deletions exercises/practice/crypto-square/.docs/instructions.append.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Instructions append

## Registers

| Register | Usage | Type | Description |
| -------- | ------------ | ------- | ----------------------------- |
| `$a0` | input | address | null-terminated input string |
| `$a1` | input/output | address | null-terminated output string |
| `$t0-9` | temporary | any | used for temporary storage |
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": [
"keiravillekode"
],
"files": {
"solution": [
"impl.mips"
],
"test": [
"runner.mips"
],
"example": [
".meta/example.mips"
]
},
"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"
}
96 changes: 96 additions & 0 deletions exercises/practice/crypto-square/.meta/example.mips
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# | Register | Usage | Type | Description |
# | -------- | ------------ | ------- | ---------------------------------- |
# | `$a0` | input | address | null-terminated input string |
# | `$a1` | input/output | address | null-terminated output string |
# | `$t0` | temporary | integer | count of alphanumeric characters |
# | `$t1` | temporary | integer | number of input columns |
# | `$t2` | temporary | integer | number of input rows, plus 1 |
# | `$t3` | temporary | integer | product, then output row number |
# | `$t4` | temporary | address | start of input string |
# | `$t5` | temporary | address | pointer into output |
# | `$t6` | temporary | byte | '0' |
# | `$t7` | temporary | byte | '9' |
# | `$t8` | temporary | byte | 'a' |
# | `$t9` | temporary | byte | 'z' |
# | `$v0` | temporary | byte | character in string |
# | `$v1` | temporary | address | return address |

.globl ciphertext

ciphertext:
move $v1, $ra # save return address
move $t4, $a0 # start of input string
li $t6, '0'
li $t7, '9'
li $t8, 'a'
li $t9, 'z'

li $t0, -1
count_alphanumeric:
addi $t0, $t0, 1 # count of alphanumeric characters
jal get_input # return next alphanumeric, or null terminator
bnez $v0, count_alphanumeric

beqz $t0, return_empty # output an empty string when count is 0
move $a0, $t4 # start of input string

move $t1, $zero
increment_columns:
addi $t1, $t1, 1 # number of columns
mulu $t3, $t1, $t1
blt $t3, $t0, increment_columns # repeat while columns * column < count

subi $t2, $t1, 2
increment_rows:
addi $t2, $t2, 1 # number of rows
mulu $t3, $t2, $t1
blt $t3, $t0, increment_rows # repeat while rows * column < count

add $t3, $t3, $t1
subi $t3, $t3, 1 # output length is (rows + 1) * columns - 1

addi $t2, $t2, 1 # rows + 1
add $t5, $a1, $t3
sb $zero, 0($t5) # write null terminator
li $v0, ' '

write_space:
subi $t5, $t5, 1
sb $v0, 0($t5)
bne $t5, $a1, write_space

next_output_column:
move $t5, $a1
addi $a1, $a1, 1

move $t3, $zero
next_output_row:
addi $t3, $t3, 1 # 1-based output row number
jal get_input
sb $v0, 0($t5) # output alphanumeric byte
subi $t0, $t0, 1
beqz $t0, return # return when decremented count is 0
add $t5, $t5, $t2
blt $t3, $t1, next_output_row
j next_output_column

return_empty:
sb $zero, 0($a1) # write null terminator

return:
jr $v1

check_input:
blt $v0, $t6, get_input # reject if < '0'
ble $v0, $t7, accept_input # accept if numeric
ori $v0, 0x20 # convert to lower case
blt $v0, $t8, get_input # reject if < 'a'
ble $v0, $t9, accept_input # accept if alphabetic

get_input:
lb $v0, 0($a0) # read input byte
addi $a0, $a0, 1
bnez $v0, check_input

accept_input:
jr $ra
34 changes: 34 additions & 0 deletions exercises/practice/crypto-square/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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"
10 changes: 10 additions & 0 deletions exercises/practice/crypto-square/impl.mips
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# | Register | Usage | Type | Description |
# | -------- | ------------ | ------- | ----------------------------- |
# | `$a0` | input | address | null-terminated input string |
# | `$a1` | input/output | address | null-terminated output string |
# | `$t0-9` | temporary | any | used for temporary storage |

.globl ciphertext

ciphertext:
jr $ra
Loading