 # utk's solution

## to Crypto Square in the C# Track

Published at May 29 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 ciphertext back in to the original message:

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

## Running the tests

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

Initially, only the first test will be enabled. This is to encourage you to solve the exercise one step at a time. Once you get the first test passing, remove the `Skip` property from the next test and work on getting that test passing. Once none of the tests are skipped and they are all passing, you can submit your solution using `exercism submit CryptoSquare.cs`

## Further information

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

## Source

J Dalbey's Programming Practice problems http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html

### CryptoSquareTest.cs

``````// This file was auto-generated based on version 3.2.0 of the canonical data.

using Xunit;

public class CryptoSquareTest
{
[Fact]
public void Empty_plaintext_results_in_an_empty_ciphertext()
{
var plaintext = "";
var expected = "";
Assert.Equal(expected, CryptoSquare.Ciphertext(plaintext));
}

[Fact(Skip = "Remove to run test")]
public void Lowercase()
{
var plaintext = "A";
var expected = "a";
Assert.Equal(expected, CryptoSquare.Ciphertext(plaintext));
}

[Fact(Skip = "Remove to run test")]
public void Remove_spaces()
{
var plaintext = "  b ";
var expected = "b";
Assert.Equal(expected, CryptoSquare.Ciphertext(plaintext));
}

[Fact(Skip = "Remove to run test")]
public void Remove_punctuation()
{
var plaintext = "@1,%!";
var expected = "1";
Assert.Equal(expected, CryptoSquare.Ciphertext(plaintext));
}

[Fact(Skip = "Remove to run test")]
public void Number_9_character_plaintext_results_in_3_chunks_of_3_characters()
{
var plaintext = "This is fun!";
var expected = "tsf hiu isn";
Assert.Equal(expected, CryptoSquare.Ciphertext(plaintext));
}

[Fact(Skip = "Remove to run test")]
public void Number_8_character_plaintext_results_in_3_chunks_the_last_one_with_a_trailing_space()
{
var plaintext = "Chill out.";
var expected = "clu hlt io ";
Assert.Equal(expected, CryptoSquare.Ciphertext(plaintext));
}

[Fact(Skip = "Remove to run test")]
public void Number_54_character_plaintext_results_in_7_chunks_the_last_two_with_trailing_spaces()
{
var plaintext = "If man was meant to stay on the ground, god would have given us roots.";
var expected = "imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn  sseoau ";
Assert.Equal(expected, CryptoSquare.Ciphertext(plaintext));
}
}``````
``````using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public static class CryptoSquare
{
public static string NormalizedPlaintext(string plaintext)
{
if (plaintext.Length == 0) return string.Empty;
return new string(plaintext.ToLower().Where(x => !char.IsPunctuation(x) && !char.IsWhiteSpace(x)).ToArray());
}

public static IEnumerable<string> PlaintextSegments(string plaintext)
{
int len = plaintext.Length;
int rows, cols;
GetRectangleDimensions(len, out rows, out cols);
string plainTextForRectangle = plaintext.PadRight(rows * cols);
int chunkLen = plainTextForRectangle.Length / cols;
List<string> chunks = new List<string>();
for(int i=0; i<plainTextForRectangle.Length; i=i+chunkLen)
{
}
List<string> res = new List<string>();
for(int i=0; i<rows; i++)
{
}
return res;
}

public static string RemoveFromAllAt<T>(this List<T> list, int idx)
{
if (typeof(T) == typeof(string))
{
StringBuilder res = new StringBuilder();
foreach (var ele in list)
{
res.Append(ele.ToString().ElementAt(idx));
}
return res.ToString();
}
return string.Empty;
}

private static void GetRectangleDimensions(int len, out int rows, out int cols)
{
bool foundUpper = false;
int lower = 0, upper = 0;
for(int i=2; !foundUpper; i++)
{
if(i*i >= len)
{
lower = i - 1;
upper = i;
foundUpper = true;
}
}
if ((upper * upper == len) || ((upper * (upper - 1)) < len)) { rows = upper; cols = upper; return; }

rows = upper; cols = upper - 1;
return;
}

public static string Encoded(string plaintext)
{
throw new NotImplementedException("You need to implement this function.");
}

public static string Ciphertext(string plaintext)
{
string normalizedText = NormalizedPlaintext(plaintext);
if (normalizedText.Length <= 1)
return normalizedText;
var chunks = PlaintextSegments(normalizedText).ToArray();
return string.Join(" ", chunks);
}
}``````