Skip to content

Commit 4cb228e

Browse files
authored
[Update exercise] Crypto Square (#539)
* [Update exercise] Crypto Suare * linter fix * changed library import
1 parent c25b3d7 commit 4cb228e

4 files changed

Lines changed: 42 additions & 104 deletions

File tree

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,18 @@
1-
normalized_plaintext <- function(input) {
2-
gsub("[^[:alnum:]]", "", input) |>
3-
tolower()
4-
}
5-
6-
map_plaintext_to_matrix <- function(input) {
7-
txt <- normalized_plaintext(input)
8-
width <- max(1, nchar(txt) |> sqrt() |> ceiling())
9-
ext_len <- ceiling(nchar(txt) / width) * width
10-
txt <- sprintf(paste0("%-", ext_len, "s"), txt)
11-
12-
strsplit(txt, "") |>
13-
unlist() |>
14-
matrix(ncol = width, byrow = TRUE)
15-
}
16-
17-
plaintext_segments <- function(input) {
18-
if (!nzchar(input)) {
19-
return("")
20-
}
21-
map_plaintext_to_matrix(input) |>
22-
apply(MARGIN = 1, paste, collapse = "") |>
23-
trimws()
24-
}
25-
26-
encoded <- function(input) {
27-
map_plaintext_to_matrix(input) |>
28-
apply(MARGIN = 2, paste, collapse = "") |>
29-
trimws() |>
30-
paste(collapse = "")
31-
}
1+
library(stringr)
322

333
ciphertext <- function(input) {
34-
map_plaintext_to_matrix(input) |>
35-
apply(MARGIN = 2, paste, collapse = "") |>
36-
paste(collapse = " ")
4+
normalized <- input |> str_to_lower() |> str_remove_all("[^a-z0-9]")
5+
if (normalized == "") return("")
6+
7+
# R matrices are column-major
8+
# we will need a transpose to match the problem specification
9+
r <- normalized |> nchar() |> sqrt() |> ceiling()
10+
c <- (nchar(normalized) / r) |> ceiling()
11+
normalized |>
12+
str_pad(c * r, "right") |>
13+
str_split_1("") |>
14+
matrix(nrow = r, ncol = c) |>
15+
t() |>
16+
apply(2, str_flatten) |>
17+
str_flatten(collapse = " ")
3718
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{%- import "generator_macros.j2" as macros with context -%}
2+
{{ macros.canonical_ref() }}
3+
4+
{{ macros.header() }}
5+
6+
{% for case in cases -%}
7+
test_that("{{ case["description"] }}", {
8+
expect_equal({{ case["property"] }}("{{ case["input"]["plaintext"] }}"), "{{ case["expected"] }}")
9+
})
10+
{% endfor %}
Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
normalized_plaintext <- function(input) {
2-
3-
}
4-
5-
plaintext_segments <- function(input) {
6-
7-
}
8-
9-
encoded <- function(input) {
10-
11-
}
12-
131
ciphertext <- function(input) {
14-
2+
153
}
Lines changed: 16 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,31 @@
1+
# These tests are auto-generated with test data from:
2+
# https://github.com/exercism/problem-specifications/tree/main/exercises/crypto-square/canonical-data.json
3+
# File last updated on 2026-08-05
4+
15
source("./crypto-square.R")
26
library(testthat)
37

8+
test_that("empty plaintext results in an empty ciphertext", {
9+
expect_equal(ciphertext(""), "")
10+
})
11+
test_that("normalization results in empty plaintext", {
12+
expect_equal(ciphertext("... --- ..."), "")
13+
})
414
test_that("Lowercase", {
5-
expect_equal(normalized_plaintext("Hello"), "hello")
15+
expect_equal(ciphertext("A"), "a")
616
})
7-
817
test_that("Remove spaces", {
9-
expect_equal(normalized_plaintext("Hi there"), "hithere")
18+
expect_equal(ciphertext(" b "), "b")
1019
})
11-
1220
test_that("Remove punctuation", {
13-
expect_equal(normalized_plaintext("@1, 2%, 3 Go!"), "123go")
14-
})
15-
16-
test_that("empty plaintext results in an empty rectangle", {
17-
expect_equal(plaintext_segments(""), "")
18-
})
19-
20-
test_that("4 character plaintext results in an 2x2 rectangle", {
21-
expect_equal(plaintext_segments("Ab Cd"), c("ab", "cd"))
22-
})
23-
24-
test_that("9 character plaintext results in an 3x3 rectangle", {
25-
expect_equal(plaintext_segments("This is fun!"), c("thi", "sis", "fun"))
26-
})
27-
28-
test_that("54 character plaintext results in an 8x7 rectangle", {
29-
expect_equal(
30-
plaintext_segments(
31-
"If man was meant to stay on the ground, god would have given us roots."
32-
),
33-
c(
34-
"ifmanwas",
35-
"meanttos",
36-
"tayonthe",
37-
"groundgo",
38-
"dwouldha",
39-
"vegivenu",
40-
"sroots"
41-
)
42-
)
43-
})
44-
45-
test_that("empty plaintext results in an empty encode", {
46-
expect_equal(encoded(""), "")
47-
})
48-
49-
test_that("Non-empty plaintext results in the combined plaintext segments", {
50-
expect_equal(
51-
encoded(
52-
"If man was meant to stay on the ground, god would have given us roots."
53-
),
54-
"imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau"
55-
)
56-
})
57-
58-
test_that("empty plaintext results in an empty ciphertext", {
59-
expect_equal(ciphertext(""), "")
21+
expect_equal(ciphertext("@1,%!"), "1")
6022
})
61-
6223
test_that("9 character plaintext results in 3 chunks of 3 characters", {
6324
expect_equal(ciphertext("This is fun!"), "tsf hiu isn")
6425
})
65-
26+
test_that("8 character plaintext results in 3 chunks, the last one with a trailing space", {
27+
expect_equal(ciphertext("Chill out."), "clu hlt io ")
28+
})
6629
test_that("54 character plaintext results in 8 chunks, the last two with trailing spaces", {
6730
expect_equal(
6831
ciphertext(
@@ -71,7 +34,3 @@ test_that("54 character plaintext results in 8 chunks, the last two with trailin
7134
"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau "
7235
)
7336
})
74-
75-
test_that("normalization results in empty plaintext", {
76-
expect_equal(ciphertext("... --- ..."), "")
77-
})

0 commit comments

Comments
 (0)