# artemkorsakov's solution

## to Crypto Square in the Go Track

Published at Feb 26 2019 · 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 cyphertext back in to the original message:

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

## 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"
)

var reg, _ = regexp.Compile("\\W")

// Encode returns the encoded version of that text.
func Encode(input string) string {
input = strings.ToLower(reg.ReplaceAllString(input, ""))
rows, columns := GetRectangleSize(input)
rectangle := GetRectangle(input, rows, columns)
encodeString := GetEncodeString(rectangle, rows, columns)
encodeRectangle := GetRectangle(encodeString, columns, rows)
return strings.Join(encodeRectangle, " ")
}

// GetRectangleSize returns the size of the rectangle (r x c).
func GetRectangleSize(input string) (int, int) {
length := len(input)
r := int(math.Sqrt(float64(length)))
if r*r == length {
return r, r
}
if r*(r+1) >= length {
return r, r + 1
}
return r + 1, r + 1
}

// GetRectangle converts a string to a rectangle with given sides.
func GetRectangle(input string, rows int, columns int) []string {
input += strings.Repeat(" ", columns)
rectangle := make([]string, rows)
for i := 0; i < rows; i++ {
rectangle[i] = input[i*columns : i*columns+columns]
}
return rectangle
}

// GetEncodeString returns the coded message (it is obtained by reading down the columns going left to right).
func GetEncodeString(rectangle []string, rows int, columns int) string {
var encodeString string
for i := 0; i < columns; i++ {
for j := 0; j < rows; j++ {
encodeString += string(rectangle[j][i])
}
}
return encodeString
}