ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# jaishreedhage's solution

## to Crypto Square in the Objective-C Track

Published at Jul 13 2018 · 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. Phrases that fill perfect rectangles `(r X c)` should be output `c` chunks of `r` length, separated by spaces. Phrases that do not fill perfect rectangles will have `n` empty spaces. Those spaces should be distributed evenly, added to the end of the last `n` chunks.

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

## Setup

There are two different methods of getting set up to run the tests with Objective-C:

• Create an Xcode project with a test target which will run the tests.
• Use the ruby gem `objc` as a test runner utility.

Both are described in more detail here: http://exercism.io/languages/objective-c

### Submitting Exercises

When submitting an exercise, make sure your solution file is in the same directory as the test code.

The submit command will look something like:

``````exercism submit <path-to-exercism-workspace>/objective-c/crypto-square/CryptoSquare.m
``````

You can find the Exercism workspace by running `exercism debug` and looking for the line beginning with Workspace.

## 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.

### CryptoSquareTest.m

``````#import <XCTest/XCTest.h>
#if __has_include("CryptoSquareExample.h")
# import "CryptoSquareExample.h"
# else
# import "CryptoSquare.h"
#endif

@interface CryptoSquareTest : XCTestCase

@end

@implementation CryptoSquareTest

- (void)testNormalizeStrangeCharacters {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"s#\$%^&plunk"];
XCTAssertEqualObjects(@"splunk", [crypto normalizePlaintext]);
}

- (void)testNormalizeUppercaseCharacters {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"WHOA HEY!"];
XCTAssertEqualObjects(@"whoahey", [crypto normalizePlaintext]);
}

- (void)testNormalizeWithNumbers {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"1, 2, 3 GO!"];
XCTAssertEqualObjects(@"123go", [crypto normalizePlaintext]);
}

- (void)testSizeOfSmallSquare {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"1234"];
XCTAssertEqual(2, crypto.numberOfColumns);
}

- (void)testSizeOfSlightlyLargerSquare {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"123456789"];
XCTAssertEqual(3, crypto.numberOfColumns);
}

- (void)testSizeOfNonPerfectSquare {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"123456789abc"];
XCTAssertEqual(4, crypto.numberOfColumns);
}

- (void)testSizeIsDeterminedByNormalizedPlaintext {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"Oh hey, this is nuts!"];
XCTAssertEqual(4, crypto.numberOfColumns);
}

- (void)testPlaintextSegments {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"Never vex thine heart with idle woes"];
NSArray *expected = @[@"neverv", @"exthin", @"eheart", @"withid", @"lewoes"];
XCTAssertEqualObjects(expected, crypto.plaintextSegments);
}

- (void)testOtherPlaintextSegments {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"ZOMG! ZOMBIES!!!"];
NSArray *expected = @[@"zomg", @"zomb", @"ies"];
XCTAssertEqualObjects(expected, crypto.plaintextSegments);
}

- (void)testCiphertext {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"Time is an illusion. Lunchtime doubly so."];
XCTAssertEqualObjects(@"tasneyinicdsmiohooelntuillibsuuml", crypto.cipherText);
}

- (void)testAnotherCiphertext {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"We all know interspecies romance is weird."];
XCTAssertEqualObjects(@"wneiaweoreneawssciliprerlneoidktcms", crypto.cipherText);
}

- (void)testNormalizedCiphertext {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"Vampires are people too!"];
XCTAssertEqualObjects(@"vrel aepe mset paoo irpo", crypto.normalizedCipherText);
}

- (void)testNormalizedCiphertextSpillsIntoShortSegment {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"Madness, and then illumination."];
XCTAssertEqualObjects(@"msemo aanin dninn dlaet ltshu i", crypto.normalizedCipherText);
}

- (void)testAnotherNormalizedCiphertext {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:
@"If man was meant to stay on the ground god would have given us roots"];
NSString *expected = @"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghns seoau";
XCTAssertEqualObjects(expected, crypto.normalizedCipherText);
}

- (void)testNormalizedCiphertextWithPunctuation {
CryptoSquare *crypto = [[CryptoSquare alloc] initWithText:@"Have a nice day. Feed the dog & chill out!"];
NSString *expected = @"hifei acedl veeol eddgo aatcu nyhht";
XCTAssertEqualObjects(expected, crypto.normalizedCipherText);
}

@end``````

### CryptoSquare/CryptoSquareTest/CryptoSquare.h

``````//
//  CryptoSquare.h
//  CryptoSquare
//
//  Created by Jaishree Dhage on 11/12/17.
//

#import <Foundation/Foundation.h>

@interface CryptoSquare : NSObject

-(instancetype)initWithText:(NSString *)text;
-(NSString *)normalizePlaintext;

@end``````

### CryptoSquare/CryptoSquareTest/CryptoSquare.m

``````//
//  CryptoSquare.m
//  CryptoSquare
//
//  Created by Jaishree Dhage on 11/12/17.
//

#import "CryptoSquare.h"

@interface CryptoSquare ()

@end

@implementation CryptoSquare

-(instancetype)initWithText:(NSString *)text{
self = [super init];
if(self){
self.text = text;
[self normalizePlaintext];
}
return self;
}

-(NSString *)normalizePlaintext{

self.text = [self.text lowercaseString];
NSMutableCharacterSet *set = [NSMutableCharacterSet whitespaceCharacterSet];
[set formUnionWithCharacterSet:[NSMutableCharacterSet punctuationCharacterSet]];
[set formUnionWithCharacterSet:[NSMutableCharacterSet symbolCharacterSet]];
self.text = [[self.text componentsSeparatedByCharactersInSet:set] componentsJoinedByString:@""];

self.numberOfColumns = ceil(sqrt(self.text.length));
NSInteger a = abs(((self.numberOfColumns - 1) * self.numberOfColumns)-self.text.length);
NSInteger b = abs((self.numberOfColumns * self.numberOfColumns)-self.text.length);

self.numberOfRows =  a>b?self.numberOfColumns:self.numberOfColumns-1;
if(a==b){
self.numberOfRows = self.numberOfColumns;
}
NSMutableArray *plainText = [NSMutableArray array];
for(int i=0,k=0;i<self.text.length;i++){
k++;
if(k%self.numberOfColumns==0)
else if(i+1==self.text.length)
}

self.plaintextSegments = plainText;

NSMutableString *cipher = [NSMutableString string];
NSMutableString *normalizedCipher = [NSMutableString string];

for(int i=0;i<self.numberOfColumns;i++){
for(int j=0;j<self.numberOfRows;j++){
if(i<self.plaintextSegments[j].length){
[cipher appendFormat:@"%c",[self.plaintextSegments[j] characterAtIndex:i]];
}
}
}

int rows;
for(rows=0;rows<self.text.length/self.numberOfRows;rows++){
[normalizedCipher appendString:[cipher substringWithRange:NSMakeRange(rows*self.numberOfRows, self.numberOfRows)]];
if(rows+1!=self.text.length/self.numberOfRows)
[normalizedCipher appendFormat:@" "];
}

if(self.text.length%self.numberOfRows!=0){
[normalizedCipher appendFormat:@" "];
[normalizedCipher appendString:[cipher substringFromIndex:(rows*self.numberOfRows)]];
}

self.cipherText = cipher;
self.normalizedCipherText = normalizedCipher;

return self.text;

}

@end``````