# nabiljdaoud's solution

## to Crypto Square in the Go Track

Published at Mar 19 2020 · 0 comments
Instructions
Test suite
Solution

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`:

``````"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:

``````"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.

``````"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:

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

## Coding the solution

Look for a stub file having the name crypto_square.go and place your solution code in that file.

## Running the tests

To run the tests run the command `go test` from within the exercise directory.

If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem` flags:

``````go test -v --bench . --benchmem
``````

Keep in mind that each reviewer will run benchmarks on a different machine, with different specs, so the results from these benchmark tests may vary.

## Further information

For more detailed information about the Go track, including how to get help if you're having trouble, please visit the exercism.io Go language page.

## Source

J Dalbey's Programming Practice problems 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.

### crypto_square_test.go

``````package cryptosquare

import "testing"

var tests = []struct {
pt string // plain text
ct string // cipher text
}{
{
"s#\$%^&plunk",
"su pn lk",
},
{
"1, 2, 3 GO!",
"1g 2o 3 ",
},
{
"1234",
"13 24",
},
{
"123456789",
"147 258 369",
},
{
"123456789abc",
"159 26a 37b 48c",
},
{
"Never vex thine heart with idle woes",
"neewl exhie vtetw ehaho ririe vntds",
},
{
"ZOMG! ZOMBIES!!!",
"zzi ooe mms gb ",
},
{
"Time is an illusion. Lunchtime doubly so.",
"tasney inicds miohoo elntu  illib  suuml ",
},
{
"We all know interspecies romance is weird.",
"wneiaw eorene awssci liprer lneoid ktcms ",
},
{
"msemo aanin dnin  ndla  etlt  shui ",
},
{
"Vampires are people too!",
"vrel aepe mset paoo irpo",
},
{
"",
"",
},
{
"1",
"1",
},
{
"12",
"1 2",
},
{
"12 3",
"13 2 ",
},
{
"12345678",
"147 258 36 ",
},
{
"123456789a",
"159 26a 37  48 ",
},
{
"If man was meant to stay on the ground god would have given us roots",
"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn  sseoau ",
},
{
"Have a nice day. Feed the dog & chill out!",
"hifei acedl veeol eddgo aatcu nyhht",
},
}

func TestEncode(t *testing.T) {
for _, test := range tests {
if ct := Encode(test.pt); ct != test.ct {
t.Fatalf(`Encode(%q):
got  %q
want %q`, test.pt, ct, test.ct)
}
}
}

func BenchmarkEncode(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
Encode(test.pt)
}
}
}``````
``````package cryptosquare

import (
"math"
"regexp"
"strings"
)

// Encode encodes a plain text string into a cipher text string
func Encode(pt string) string {
normalized := normalize(pt)
rectangularized := rectangularize(normalized)
// fmt.Println(rectangularized)
encoded := flatten(rectangularized)
return encoded
}

func normalize(pt string) string {
r := regexp.MustCompile("[^a-zA-Z0-9]+")
return strings.ToLower(r.ReplaceAllString(pt, ""))
}

func rectangularize(normalized string) []string {
r, c := getNumRowsAndColumns(normalized)
result := make([]string, r)
for len(normalized) < r*c {
normalized += " "
}
for i := 0; i < r; i++ {
result[i] = string(normalized[i*c : (i+1)*c])
}
return result
}

// getRowsAndColumns takes the normalized string and returns the
// number of rows and columns such that r <= c and c - r <= 1.
func getNumRowsAndColumns(normalized string) (r, c int) {
total := len(normalized)
r = int(math.Floor(math.Sqrt(float64(total))))
c = int(math.Ceil(math.Sqrt(float64(total))))
if r*c < total {
r++
}
return
}

func flatten(rectangle []string) string {
rows := len(rectangle)
if rows == 0 {
return ""
}
cols := len(rectangle[0])
output := make([]byte, rows*cols+cols-1)
i := 0
for col := 0; col < cols; col++ {
for row := 0; row < rows; row++ {
output[i] = rectangle[row][col]
i++
}
if col < cols-1 {
output[i] = ' '
i++
}
}
return string(output)
}``````