-
-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add crypto-square exercise Implement tests and example solution Generate README Update config
- Loading branch information
1 parent
7b715e3
commit 4927956
Showing
5 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Crypto Square | ||
|
||
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 downcased. | ||
|
||
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 | ||
|
||
> If man was meant to stay on the ground, god would have given us roots. | ||
is normalized to: | ||
|
||
> ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots | ||
The plaintext should be organized in to a rectangle. The size of the | ||
rectangle (`r x c`) should be decided by the length of the message, | ||
such that `c >= r` and `c - r <= 1`, where `c` is the number of columns | ||
and `r` is the number of rows. | ||
|
||
Our normalized text is 54 characters long, dictating a rectangle with | ||
`c = 8` and `r = 7`: | ||
|
||
```plain | ||
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: | ||
|
||
```plain | ||
imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau | ||
``` | ||
|
||
Output the encoded text in chunks. Phrases that fill perfect squares | ||
`(r X r)` should be output in `r`-length chunks separated by spaces. | ||
Imperfect squares will have `n` empty spaces. Those spaces should be distributed evenly across the last `n` rows. | ||
|
||
```plain | ||
imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau | ||
``` | ||
|
||
Notice that were we to stack these, we could visually decode the | ||
cyphertext back in to the original message: | ||
|
||
```plain | ||
imtgdvs | ||
fearwer | ||
mayoogo | ||
anouuio | ||
ntnnlvt | ||
wttddes | ||
aohghn | ||
sseoau | ||
``` | ||
|
||
## Installation | ||
See [this guide](https://github.com/exercism/xr/blob/master/docs/INSTALLATION.md) for instructions on how to setup your local R environment. | ||
|
||
## How to implement your solution | ||
In each problem folder, there is a file named `<exercise_name>.R` containing a function that returns a `NULL` value. Place your implementation inside the body of the function. | ||
|
||
## How to run tests | ||
Inside of RStudio, simply execute the `test_<exercise_name>.R` script. This can be conveniently done with [testthat's `auto_test` function](https://www.rdocumentation.org/packages/testthat/topics/auto_test). Because exercism code and tests are in the same folder, use this same path for both `code_path` and `test_path` parameters. On the command-line, you can also run `Rscript test_<exercise_name>.R`. | ||
|
||
## Source | ||
|
||
J Dalbey's Programming Practice problems [http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html](http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html) | ||
|
||
## Submitting Incomplete Solutions | ||
It's possible to submit an incomplete solution so you can see how others have completed the exercise. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
normalized_plaintext <- function(input) { | ||
|
||
} | ||
|
||
plaintext_segments <- function(input) { | ||
|
||
} | ||
|
||
encoded <- function(input) { | ||
|
||
} | ||
|
||
ciphertext <- function(input) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
library(magrittr) | ||
|
||
normalized_plaintext <- function(input) { | ||
|
||
gsub("[^[:alnum:]]", "", input) %>% | ||
tolower() | ||
|
||
} | ||
|
||
map_plaintext_to_matrix <- function(input) { | ||
|
||
txt <- normalized_plaintext(input) | ||
width <- max(1, nchar(txt) %>% sqrt() %>% ceiling()) | ||
ext_len <- ceiling(nchar(txt) / width) * width | ||
txt <- sprintf(paste0("%-", ext_len, "s"), txt) | ||
|
||
strsplit(txt, "") %>% | ||
unlist() %>% | ||
matrix(ncol = width, byrow = TRUE) | ||
|
||
} | ||
|
||
plaintext_segments <- function(input) { | ||
|
||
if (!nzchar(input)) return("") | ||
map_plaintext_to_matrix(input) %>% | ||
apply(MARGIN = 1, paste, collapse = "") %>% | ||
trimws() | ||
|
||
} | ||
|
||
encoded <- function(input) { | ||
|
||
map_plaintext_to_matrix(input) %>% | ||
apply(MARGIN = 2, paste, collapse = "") %>% | ||
trimws() %>% | ||
paste(collapse = "") | ||
|
||
} | ||
|
||
ciphertext <- function(input) { | ||
|
||
map_plaintext_to_matrix(input) %>% | ||
apply(MARGIN = 2, paste, collapse = "") %>% | ||
paste(collapse = " ") | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
source("./crypto-square.R") | ||
library(testthat) | ||
|
||
test_that("Lowercase", { | ||
expect_equal(normalized_plaintext("Hello"), "hello") | ||
}) | ||
|
||
test_that("Remove spaces", { | ||
expect_equal(normalized_plaintext("Hi there"), "hithere") | ||
}) | ||
|
||
test_that("Remove punctuation", { | ||
expect_equal(normalized_plaintext("@1, 2%, 3 Go!"), "123go") | ||
}) | ||
|
||
test_that("empty plaintext results in an empty rectangle", { | ||
expect_equal(plaintext_segments(""), "") | ||
}) | ||
|
||
test_that("4 character plaintext results in an 2x2 rectangle", { | ||
expect_equal(plaintext_segments("Ab Cd"), c("ab", "cd")) | ||
}) | ||
|
||
test_that("9 character plaintext results in an 3x3 rectangle", { | ||
expect_equal(plaintext_segments("This is fun!"), c("thi", "sis", "fun")) | ||
}) | ||
|
||
test_that("54 character plaintext results in an 8x7 rectangle", { | ||
expect_equal(plaintext_segments( | ||
"If man was meant to stay on the ground, god would have given us roots."), | ||
c("ifmanwas", | ||
"meanttos", | ||
"tayonthe", | ||
"groundgo", | ||
"dwouldha", | ||
"vegivenu", | ||
"sroots")) | ||
}) | ||
|
||
test_that("empty plaintext results in an empty encode", { | ||
expect_equal(encoded(""), "") | ||
}) | ||
|
||
test_that("Non-empty plaintext results in the combined plaintext segments", { | ||
expect_equal(encoded( | ||
"If man was meant to stay on the ground, god would have given us roots."), | ||
"imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau") | ||
}) | ||
|
||
test_that("empty plaintext results in an empty ciphertext", { | ||
expect_equal(ciphertext(""), "") | ||
}) | ||
|
||
test_that("9 character plaintext results in 3 chunks of 3 characters", { | ||
expect_equal(ciphertext("This is fun!"), "tsf hiu isn") | ||
}) | ||
|
||
test_that("54 character plaintext results in 7 chunks, the last two padded with | ||
spaces", { | ||
expect_equal(ciphertext( | ||
"If man was meant to stay on the ground, god would have given us roots."), | ||
"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau ") | ||
}) | ||
|
||
message("All tests passed for exercise: crypto-square") |