I wrote a Java program that given a text message will print the encoded message. The problem is described in this link.
Summary:
We have to write a program that will encrypt a message that do not contain space character. Assuming that \$L\$ is the length of the message we have to put characters of this string in matrix where \$\textit{columns} \cdot \textit{rows} \ge L\$ and \$\lfloor \sqrt L \rfloor \le \textit{rows} \le \textit{columns} < \lceil \sqrt L \rceil\$. To get the encrypted message we have to iterate over column and print each one as a word.
For example:
Input: haveaniceday
Output: hae and via ecy
import java.util.Scanner;
public class Encryption {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String input = scan.next();
int stringLengh = input.length();
int lowerBound = getFloorSqrt(stringLengh);
int upperBound = getCeilSqrt(stringLengh);
IntRange range = new IntRange(lowerBound, upperBound);
range = getRangeWithMinArea(range, stringLengh);
char[][] grid = getGridEncryption(range, input);
System.out.println(getEncryptedMessage(grid));
}
/**
* return the ceil of the square root of a number.
*
* @param number
* @return
*/
public static int getCeilSqrt(int number) {
return (int) Math.ceil(Math.sqrt(number));
}
/**
* return the floor of the square root of a number.
*
* @param number
* @return
*/
public static int getFloorSqrt(int number) {
return (int) Math.floor(Math.sqrt(number));
}
/**
* Iterate over ranges enclosed by the initial range to get the one which
* having area greater than or equal the minimal area.
*
* @param initialRange
*
* @param minimalArea
* @return
*/
public static IntRange getRangeWithMinArea(IntRange initialRange, int minimalArea) {
if (initialRange.getLowerBound() * initialRange.getUpperBound() < minimalArea
&& initialRange.getLowerBound() <= initialRange.getUpperBound()) {
return getRangeWithMinArea(initialRange.incremntLowerBound(), minimalArea);
}
return initialRange;
}
/**
* Assuming a matrix of characters this function will return a phrase where
* each word is represented by one column. eg. input:|a|b|c| |d|e|f|
*
* output: ad be cf.
*
* @param grid
* @return
*/
private static String getEncryptedMessage(char[][] grid) {
StringBuffer str = new StringBuffer();
for (int i = 0; i < grid[0].length; i++) {
for (int j = 0; j < grid.length; j++) {
if (grid[j][i] != '\u0000')
str.append(grid[j][i]);
}
str.append(" ");
}
return str.toString();
}
/**
*
* @param range
* @param str
* @return
*/
public static char[][] getGridEncryption(IntRange range, String str) {
char[] text = str.toCharArray();
char[][] ret = new char[range.getLowerBound()][range.getUpperBound()];
int k = 0;
for (int i = 0; i < range.getLowerBound(); i++) {
for (int j = 0; j < range.getUpperBound() && k < str.length(); j++) {
ret[i][j] = text[k];
k++;
}
}
return ret;
}
/**
* IntRange represents a set of integer bounded by two numbers upperBound
* and lowerBound. such as upperBound is greater or equal lowerBound.
*/
static class IntRange {
private final int lowerBound;
private final int upperBound;
IntRange(int lowerBound, int upperBound) {
this.lowerBound = lowerBound;
this.upperBound = upperBound;
}
public int getLowerBound() {
return lowerBound;
}
public int getUpperBound() {
return upperBound;
}
public IntRange incrementUpperBound() {
return new IntRange(this.lowerBound, this.upperBound + 1);
}
public IntRange incremntLowerBound() {
return new IntRange(this.lowerBound + 1, this.upperBound);
}
}
}