I have been trying to recreate a python function to decrypt messages using a transposition cipher. although it keeps giving me incorrect outputs and making the messages longer. I think the error is to do with the array and the for loop but I'm not 100% sure.
My code
public String TranspositionDecryptText (String EncryptedText, int Key) {
double NumColumnsD = Math.ceil(EncryptedText.length() / Key);
int NumColumns = (int) NumColumnsD;
int NumRows = Key;
int NumShadedBoxes = (NumColumns * NumRows) - EncryptedText.length();
String NormalArray[] = new String[NumColumns];
int col = 0;
int row = 0;
for (int i = 0; i < EncryptedText.length(); i++) {
NormalArray[col] = NormalArray[col] + EncryptedText.charAt(i);
col = col + 1;
if ((col == NumColumns) || ((col == NumColumns - 1) && (row >= NumRows - NumShadedBoxes))) {
col = 0;
row = row + 1;
}
}
String NormalString = "";
for (int i = 0; i < NormalArray.length; i++) {
NormalString = NormalString + NormalArray[i];
}
return NormalString;
}
Python version http://inventwithpython.com/hacking/chapter9.html
def decryptMessage(key, message):
# The transposition decrypt function will simulate the "columns" and
# "rows" of the grid that the plaintext is written on by using a list
# of strings. First, we need to calculate a few values.
# The number of "columns" in our transposition grid:
numOfColumns = math.ceil(len(message) / key)
# The number of "rows" in our grid will need:
numOfRows = key
# The number of "shaded boxes" in the last "column" of the grid:
numOfShadedBoxes = (numOfColumns * numOfRows) - len(message)
# Each string in plaintext represents a column in the grid.
plaintext = [''] * numOfColumns
# The col and row variables point to where in the grid the next
# character in the encrypted message will go.
col = 0
row = 0
for symbol in message:
plaintext[col] += symbol
col += 1 # point to next column
# If there are no more columns OR we're at a shaded box, go back to
# the first column and the next row.
if (col == numOfColumns) or (col == numOfColumns - 1 and row >= numOfRows - numOfShadedBoxes):
col = 0
row += 1
return ''.join(plaintext)
I found that the text string given needed to be divisible by the key for the decryption to work. After finding this I added a loop to add spaces to the end of the text before being encrypted so the decryption program then has to trim the returned text before. The code now looks like this :
public class TranspositionCipher {
public String TranspositionEncryptText (String Text, int Key) {
while (Text.length() % Key != 0) {
Text = Text + " ";
}
ArrayList EncryptedText = new ArrayList<String>(Key); // Creates an array with as many elements as key
String HoldText = "";
for (int col = 0; col < Key; col++) {
int pointer = col;
while (pointer < Text.length()) {
HoldText = HoldText + Text.charAt(pointer);
pointer = pointer + Key;
}
EncryptedText.add(col, HoldText);
HoldText = "";
}
String EncryptedString = ""; // String version of encrypted text
Iterator iter = EncryptedText.iterator(); // Used to go through the array
while (iter.hasNext()) { // While there are more elements in the array
EncryptedString = EncryptedString + iter.next(); // Add the element to the string
}
return EncryptedString; // Return the encrypted text as a string
}
public String TranspositionDecryptText (String EncryptedText, int Key) {
double NumColumnsD = Math.ceil(EncryptedText.length() / Key);
int NumColumns = (int) NumColumnsD;
int NumRows = Key;
int NumShadedBoxes = (NumColumns * NumRows) - EncryptedText.length();
String NormalArray[] = new String[NumColumns];
int col = 0;
int row = 0;
for (int i = 0; i < NumColumns; i++) {
NormalArray[i] = "";
}
for (int i = 0; i < EncryptedText.length(); i++) {
NormalArray[col] = NormalArray[col] + EncryptedText.charAt(i);
System.out.println(NormalArray[col]);
col = col + 1;
if ((col == NumColumns) || ((col == NumColumns - 1) && (row >= NumRows - NumShadedBoxes))) {
col = 0;
row = row + 1;
}
}
String NormalString = "";
for (int i = 0; i < NormalArray.length; i++) {
NormalString = NormalString + NormalArray[i];
}
NormalString = NormalString.trim();
return NormalString;
}
}
Related
Find patterns in a given matrix.
I have a matrix with values '.' and '#'
Now I want to find count with the given pattern in the matrix :
a)
##
b)
#
#
For the above pattern, the cells if exist surrounding them should be '.'
I am able to create successful logic for it:
static int getMatches(String[] B, int m, int n) {
int count = 0;
boolean[][] flag = new boolean[m][n];
for (int i = 0; i < m; i++) {
String S = B[i];
for (int j = 0; j < n; j++) {
char c = S.charAt(j);
boolean valid = true;
if (c == '#' && flag[i][j] == false) {
if (j + 1 < n && S.charAt(j + 1) == '#' && flag[i][j + 1] == false) {
int[][] adj = { { 0, -1 }, { 0, 2 }, { -1, 0 }, { -1, 1 }, { 1, 0 }, { 1, 1 } };
valid = isValid(adj, i, j, m, n, B);
} else {
valid = false;
}
} else {
valid = false;
}
if (c == '#' && !valid && flag[i][j] == false) {
if (i + 1 < m && S.charAt(i + 1) == '#' && flag[i + 1][i] == false) {
int[][] adj = { { 0, -1 }, { 1, -1 }, { 1, 1 }, { 0, 1 }, { -1, 0 }, { 2, 0 } };
valid = isValid(adj, i, j, m, n, B);
} else {
valid = false;
}
}
flag[i][j] = true;
if (valid) {
count++;
}
}
}
return count;
}
static boolean isValid(int[][] adj, int i, int j, int m, int n, String[] B) {
for (int a = 0; a < adj.length; a++) {
int i1 = i + adj[a][0];
int j1 = j + adj[a][1];
if (i1 >= 0 && i1 < m) {
if (j1 >= 0 && j1 < n) {
char d = B[i1].charAt(j1);
if (d == '#') {
return false;
}
}
}
}
return true;
}
Now I want to change the pattern to 3 cells like this:
a)
###
b)
#
#
#
c)
##
#
d)
##
#
e)
#
##
f)
#
##
How to build logic for this? Is their a way to extend my above code or is there a better approach to solve this problem.
As far as I understand, the problem can be simplified to finding the adjacent # fields, and their area must match a certain number.
So I have created the following code:
public static int getMatches(String[] matrix, int m, int n, int patternArea) {
int count = 0;
for (int i = 0; i < m; i++) {
String row = matrix[i];
for (int j = 0; j < n; j++) {
char item = row.charAt(j);
if (item == '#' && countArea(matrix, i, j) + 1 == patternArea) {
count++;
}
}
}
return count;
}
private static int countArea( String[] matrix, final int i, final int j ) {
int area = 0;
setVisited(matrix, i,j);
if (matrix[Math.max(i-1, 0)].charAt(j) == '#') {
area += countArea(matrix, i-1, j) + 1;
}
if (matrix[Math.min(i+1, matrix.length-1)].charAt(j) == '#') {
area += countArea(matrix, i+1, j) + 1;
}
if (matrix[i].charAt(Math.max(j-1, 0)) == '#') {
area += countArea(matrix, i, j-1) + 1;
}
if (matrix[i].charAt(Math.min(j+1, matrix[0].length()-1)) == '#') {
area += countArea(matrix, i, j+1) + 1;
}
return area;
}
private static void setVisited( final String[] matrix, final int i, final int j ) {
char[] rowChars = matrix[i].toCharArray();
rowChars[j] = '0';
matrix[i] = String.valueOf(rowChars);
}
Explanation:
Find at least 1 # field
From that position, recursively find any adjacent # fields - countArea method
Always mark already visited fields - I chose 0, but any other char will do other than . and #
Finally, if the area is matching a given number (patternArea), increase count variable
This is working only, if you include all of the patterns for a certain number. Given your example, you did just that. In case you really want to do exact pattern matching, then this approach will not be useful for your case.
Shared solution should work with any matrix of any symbols and number of rows/columns
Let's assume next parameters that we'll have as our input:
Matrix is represented as two-dimensional array - matrix[r][c], where r - number of rows in matrix, c - number of columns in matrix
Matrix has all its cells filled with some symbols
Pattern is represented as two-dimensional array - arr[k][m], where k - number of rows in pattern, m - number of columns in pattern
Algorithm will iterate each column of each row in matrix
Pattern can potentially be present in cell[x][y] only if next conditions are met:
x + k <= r (there are enough of matrix rows below this one (including current row) to include number of pattern rows)
y + m <= c (there are enough of matrix columns right of this one (including current column) to include number of pattern columns)
Comparison of pattern to current matrix cells says that they are equal. Comparison in done based on next conditions:
if pattern character is null - continue comparison
if pattern character is equal to matrix character - continue comparison
if pattern character is not equal to matrix character - end comparison, pattern is not located in this cell
if all pattern symbols checked - pattern is found in given matrix cell
Result of comparison in represented in 0-based index pairs
Let's get to the code.
We will have next classes:
Pattern Rule - represents pattern to be found. please specify nulls manually to make actually 2-dimensional array of equal row/col count
private static final class PatternRule {
private final Character[][] pattern;
private final int rowCount;
private final int colCount;
private PatternRule(Character[][] pattern) {
this.pattern = pattern;
this.rowCount = pattern.length;
this.colCount = pattern[0].length;
}
public int getRowCount() {
return rowCount;
}
public int getColCount() {
return colCount;
}
public Character getCharacterAt(int row, int column) {
return pattern[row][column];
}
}
Found Pattern Location - class to represent found cells for pattern locations
private static final class FoundPatternLocation {
private final int rowIndex;
private final int colIndex;
private FoundPatternLocation(int rowIndex, int colIndex) {
this.rowIndex = rowIndex;
this.colIndex = colIndex;
}
#Override
public String toString() {
return "[" + rowIndex + "][" + colIndex + "]";
}
}
Matrix - class that creates matrix and performs search of pattern locations
private static final class Matrix {
private final Character[][] matrix;
private final int rowCount;
private final int colCount;
private Matrix(int rowCount, int colCount, Character[][] matrix) {
this.rowCount = rowCount;
this.colCount = colCount;
this.matrix = matrix;
}
public static Matrix createMatrix(int rowCount, int colCount, char[] matrixSymbols) {
Character[][] newMatrix = new Character[colCount][rowCount];
Random rand = new Random();
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
for (int colIndex = 0; colIndex < colCount; colIndex++) {
// select random char from allowed symbols
newMatrix[rowIndex][colIndex] = matrixSymbols[rand.nextInt(matrixSymbols.length)];
}
}
return new Matrix(rowCount, colCount, newMatrix);
}
public void printMatrix() {
System.out.println("---- Matrix -----");
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
List<String> rowValues = new ArrayList<>();
for (int colIndex = 0; colIndex < colCount; colIndex++) {
rowValues.add(String.valueOf(matrix[rowIndex][colIndex]));
}
String printableRowString = String.join(" ", rowValues);
System.out.println(printableRowString);
}
System.out.println("-----------------");
}
public List<FoundPatternLocation> findPatternLocations(PatternRule patternRule) {
List<FoundPatternLocation> actualPatternLocation = new ArrayList<>();
for (int rowNum = 0; rowNum < this.rowCount; rowNum++) {
for (int colNum = 0; colNum < this.colCount; colNum++) {
if (isPatternFittingToCurrentCell(rowNum, colNum, patternRule)) { // can pattern be located in this cell?
if (isPatternLocatedInCell(rowNum, colNum, patternRule)) { // is pattern actually located in this cell?
actualPatternLocation.add(new FoundPatternLocation(rowNum, colNum));
}
}
}
}
return actualPatternLocation;
}
private boolean isPatternFittingToCurrentCell(int matrixRowIndex, int matrixColIndex, PatternRule patternRule) {
int patternRowsCount = patternRule.getRowCount();
int patternColumnsCount = patternRule.getColCount();
int availableMatrixRowsForPattern = rowCount - matrixRowIndex;
int availableMatrixColsForPattern = colCount - matrixColIndex;
return patternRowsCount <= availableMatrixRowsForPattern && patternColumnsCount <= availableMatrixColsForPattern;
}
private boolean isPatternLocatedInCell(int rowNum, int colNum, PatternRule patternRule) {
int patternRowsCount = patternRule.getRowCount();
int patternColumnsCount = patternRule.getColCount();
for (int currentPatternRowIndex = 0; currentPatternRowIndex < patternRowsCount; currentPatternRowIndex++) {
for (int currentPatternColIndex = 0; currentPatternColIndex < patternColumnsCount; currentPatternColIndex++) {
int currentMatrixRowIndex = currentPatternRowIndex + rowNum;
int currentMatrixColIndex = currentPatternColIndex + colNum;
Character currentMatrixCharacter = matrix[currentMatrixRowIndex][currentMatrixColIndex];
Character currentPatternCharacter = patternRule.getCharacterAt(currentPatternRowIndex, currentPatternColIndex);
if (currentPatternCharacter == null) {
continue;
}
if (Objects.equals(currentMatrixCharacter, currentPatternCharacter)) {
continue;
}
return false;
}
}
return true;
}
}
Class to perform execution
public static void main(String[] args) {
int rowCount = 5;
int colCount = 5;
char[] matrixSymbols = new char[] {'✓', 'X'};
Matrix matrix = Matrix.createMatrix(rowCount, colCount, matrixSymbols);
matrix.printMatrix();
PatternRule patternRuleA = createPatternRuleA();
PatternRule patternRuleB = createPatternRuleB();
PatternRule patternRuleC = createPatternRuleC();
List<FoundPatternLocation> patternLocationsA = matrix.findPatternLocations(patternRuleA);
printPatternLocations(patternLocationsA, "Pattern A");
List<FoundPatternLocation> patternLocationsB = matrix.findPatternLocations(patternRuleB);
printPatternLocations(patternLocationsB, "Pattern B");
List<FoundPatternLocation> patternLocationsC = matrix.findPatternLocations(patternRuleC);
printPatternLocations(patternLocationsC, "Pattern C");
}
private static void printPatternLocations(List<FoundPatternLocation> patternLocations, String patternName) {
System.out.println("---- " + patternName + " ----");
String string = patternLocations.stream().map(FoundPatternLocation::toString).collect(Collectors.joining("; "));
System.out.println(string);
System.out.println("--------");
}
private static PatternRule createPatternRuleA() {
Character[][] chars = {
{'✓', '✓', '✓'}
};
return new PatternRule(chars);
}
private static PatternRule createPatternRuleB() {
Character[][] chars = {
{'✓'},
{'✓'},
{'✓'}
};
return new PatternRule(chars);
}
private static PatternRule createPatternRuleC() {
Character[][] chars = {
{'✓', '✓'},
{'✓', null}
};
return new PatternRule(chars);
}
Example of execution:
---- Matrix -----
✓ ✓ X ✓ X
✓ ✓ ✓ ✓ ✓
X X X X ✓
X ✓ X X ✓
X X ✓ ✓ ✓
-----------------
---- Pattern A ----
[1][0]; [1][1]; [1][2]; [4][2]
--------
---- Pattern B ----
[1][4]; [2][4]
--------
---- Pattern C ----
[0][0]
--------
I'm working on keyword columnar cipher and I keep getting array out of bound exception, I have tried debugging the code and try and catch to understand the problem but I couldn't!
public Decryption (String cipherText, String keyWord) {
cipherText = cipherText.replaceAll("\\s+","");
cipherText = cipherText.toUpperCase();
cipherText = cipherText.trim();
keyWord = keyWord.toUpperCase();
int column = keyWord.length();
int row = (cipherText.length() / keyWord.length());
if (cipherText.length() % keyWord.length() != 0)
row += 1;
char [][] matrix = new char [row][column];
int re = cipherText.length() % keyWord.length();
for (int i = 0; i < keyWord.length() - re; i++)
matrix[row - 1][keyWord.length() - 1 - i] = '*';
char[] sorted_key = keyWord.toCharArray();
Arrays.sort(sorted_key);
int p = 0, count = 0;
char[] cipher_array = cipherText.toCharArray();
Map<Character,Integer> indices = new HashMap<>();
for(int i = 0; i < column; i++){
int last = indices.computeIfAbsent(sorted_key[i], c->-1);
p = keyWord.indexOf(sorted_key[i], last+1);
indices.put(sorted_key[i], p);
for(int j = 0; j < row; j++){
if (matrix[j][p] != '*')
matrix[j][p] = cipher_array[count];
count++;
}}
}
I'm getting the exception in:
matrix[j][p] = cipher_array[count];
there is a problem with the loop, if I start with j = 1 it doesn't give me the exception but I don't get the correct results (It doesn't print the last row)
The cipher text that I'm trying to decrypt:
YARUEDCAUOADGRYHOBBNDERPUSTKNTTTGLORWUNGEFUOLNDRDEYGOOAOJRUCKESPY
Keyword:
YOURSELF
The result I get when I start the loop with 1:
JUDGE YOURSELF ABOUT YOUR BACKGROUND KNOWLEDGE TO UNDERSTAND CRYP
What I'm supposed to get:
JUDGE YOURSELF ABOUT YOUR BACKGROUND KNOWLEDGE TO UNDERSTAND
CRYPTOGRAPHY
I'm not precisely sure, because your code doesnt allow me to validate this (there is no easy way to check the output of the algorithm without digging in), so... I assume that solution is:
for (int j = 0; j < row; j++) {
if (matrix[j][p] != '*'){
matrix[j][p] = cipher_array[count];
count++;
}
}
instead of:
for (int j = 0; j < row; j++) {
if (matrix[j][p] != '*')
matrix[j][p] = cipher_array[count];
count++;
}
I think that the strategy of appending '*' to the string in this case is not the way to go - like what you did. Better to append some character when you are building the grid.
Following this approach here is a fixed version of your code (check the comments in the code for the changed parts):
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Decryption {
private final String result;
public Decryption(String cipherText, String keyWord) {
cipherText = cipherText.replaceAll("\\s+", "");
cipherText = cipherText.toUpperCase();
cipherText = cipherText.trim();
keyWord = keyWord.toUpperCase();
int column = keyWord.length();
int row = (cipherText.length() / keyWord.length());
if (cipherText.length() % keyWord.length() != 0)
row += 1;
int[][] matrix = new int[row][column];
// Changed to calculate the irregular columns
int re = column - (row * column - cipherText.length());
char[] sorted_key = keyWord.toCharArray();
Arrays.sort(sorted_key);
int p, count = 0;
char[] cipher_array = cipherText.toCharArray();
Map<Character, Integer> indices = new HashMap<>();
for (int i = 0; i < column; i++) {
int last = indices.computeIfAbsent(sorted_key[i], c -> -1);
p = keyWord.indexOf(sorted_key[i], last + 1);
indices.put(sorted_key[i], p);
// Changed: Detects the need of an extra character and fills it in case of need
boolean needsExtraChar = p > re - 1;
for (int j = 0; j < row - (needsExtraChar ? 1 : 0); j++) {
matrix[j][p] = cipher_array[count];
count++;
}
if(needsExtraChar) {
matrix[row - 1][p] = '-';
}
}
result = buildString(matrix);
}
public static void main(String[] args) {
System.out.println(new Decryption("EVLNE ACDTK ESEAQ ROFOJ DEECU WIREE", "ZEBRAS").result);
System.out.println(new Decryption("EVLNA CDTES EAROF ODEEC WIREE", "ZEBRAS").result);
System.out.println(new Decryption("YARUEDCAUOADGRYHOBBNDERPUSTKNTTTGLORWUNGEFUOLNDRDEYGOOAOJRUCKESPY", "YOURSELF").result);
}
private String buildString(int[][] grid) {
return Arrays.stream(grid).collect(StringBuilder::new, (stringBuilder, ints) -> Arrays.stream(ints).forEach(t -> {
stringBuilder.append((char) t);
}), (stringBuilder, ints) -> {
}).toString().replace("-", "");
}
}
If you run this, this will print:
WEAREDISCOVEREDFLEEATONCEQKJEU
WEAREDISCOVEREDFLEEATONCE
JUDGEYOURSELFABOUTYOURBACKGROUNDKNOWLEDGETOUNDERSTANDCRYPTOGRAPHY
Say I have a string x and I want to add some character x amount of times so that string x becomes of length y, how would I do this?
String x = "this_is_a_line";
//x.length() = 14;
length y = 20;
//insert character into line so String x becomes balanced to:
x = "this___is___a___line";
//x.length() = 20;
Another example:
String y = "in_it_yeah";
//y.length() = 10
length j = 15;
//inserting characters so String y becomes balanced to:
y = "in____it___yeah";
I want to avoid using StringBuilder to append characters.
My thought process:
Create a Char array of length y.
Copy the string to array.
Attempt to shift the characters one by one
from the furthest character to the right.
I hope I understood you correctly but I think this code does what you're requesting.
Edit: this one will distribute the specified character evenly and can create strings like "a__b_c" if the string isn't long enough yet.
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
String string = "this_is_a_line";
int length = string.length();
int desiredLength = 16;
int extraLengthRequired = desiredLength - length;
char characterToBeDuplicated = '_';
String[] rawPieces = string.split(Character.toString(characterToBeDuplicated));
ArrayList<String> pieces = new ArrayList<>();
int emptyIndexes = 0;
for (String piece : rawPieces) {
if(piece.equals("")) {
emptyIndexes++;
} else {
pieces.add(piece);
}
}
int numOfCharactersToBeMultiplied = pieces.size() - 1;
int numOfMultiplications = (int) Math.floor((extraLengthRequired + emptyIndexes) / numOfCharactersToBeMultiplied) + 1;
int lengthLeft = (extraLengthRequired + emptyIndexes) % numOfCharactersToBeMultiplied;
String newString = pieces.get(0);
for (int i = 1; i < pieces.size(); i++) {
newString += characterToBeDuplicated;
if(lengthLeft > 0) {
newString += characterToBeDuplicated;
lengthLeft--;
}
for (int j = 1; j < numOfMultiplications; j++) {
newString += characterToBeDuplicated;
}
newString += pieces.get(i);
}
System.out.println(newString + " - " + newString.length());
}
}
Old solution:
public class Main {
public static void main(String[] args) {
String string = "this_is_a_line";
int length = string.length();
int desiredLength = 20;
int extraLengthRequired = desiredLength - length;
char characterToBeDuplicated = '_';
String[] pieces = string.split(Character.toString(characterToBeDuplicated));
int numOfCharactersToBeMultiplied = pieces.length - 1;
int numOfMultiplications = (int) Math.floor(extraLengthRequired / numOfCharactersToBeMultiplied);
String newString = pieces[0];
for (int i = 1; i < pieces.length; i++) {
newString += characterToBeDuplicated;
for (int j = 1; j < numOfMultiplications; j++) {
newString += characterToBeDuplicated;
}
newString += pieces[i];
}
System.out.println(newString);
}
}
I did this one because when I started doing a pseudo code it was a bit challenging for me, though I'm not a fan of answering questions like this on "gimme teh codez".
I recommend you though using StringBuilder on String concatenation inside for loops because it's more efficient than actual String concatenation with +=.
Note that:
This program adds spaces to the end, that's why I print it's length trimmed.
I split it by space with a regex \\s+ instead of _ because that's how you wrote it 1st
The following code works for
a____b_c -> a___b___c (Lenght 9)
a____b_c -> a____b___c (Lenght 10)
this_is_a_line -> this___is___a___line (Lenght 20)
in_it_yeah -> in____it___yeah (Length 15)
Code:
class EnlargeString {
public static void main (String args[]) {
String x = "a b c";
int larger = 10;
int numberOfSpaces = 0;
String s[] = x.split("\\s+"); //We get the number of words
numberOfSpaces = larger - s.length; //The number of spaces to be added after each token
int extraSpaces = numberOfSpaces % s.length; //Extra spaces for the cases of 4 spaces then 3 or something like that
System.out.println(extraSpaces);
String newSpace[] = new String[s.length]; //The String array that will contain all string between words
for (int i = 0; i < s.length; i++) {
newSpace[i] = " "; //Initialize the previous array
}
//Here we add the extra spaces (the cases of 4 and 3)
for (int i = 0; i < s.length; i++) {
if (extraSpaces == 0) {
break;
}
newSpace[i] += " ";
extraSpaces--;
}
for (int i = 0; i < s.length; i++) {
for (int j = 0; j < totalSpaces / s.length; j++) {
newSpace[i] += " "; //Here we add all the equal spaces for all tokens
}
}
String finalWord = "";
for (int i = 0; i < s.length; i++) {
finalWord += (s[i] + newSpace[i]); //Concatenate
}
System.out.println(x);
System.out.println(x.length());
System.out.println(finalWord);
System.out.println(finalWord.trim().length());
}
}
Next time try to do it yourself 1st and show YOUR logic, then your question will be better received (maybe with upvotes instead of downvotes) this is called a Runnable Example. I also recommend you to take a look at String concatenation vs StringBuilder and How to ask a good question, also you might want to Take the tour
Here is my solution:
public class Main
{
public static void main(String args[]){
System.out.print("#Enter width : " );
int width = BIO.getInt();
System.out.print("#Enter line of text : " );
String line = BIO.getString().trim();
int nGaps, spToAdd, gapsLeft, modLeft, rem;
nGaps = spToAdd = gapsLeft = rem = 0;
double route = 0;
String sp = " ";
while ( ! line.equals( "END" )){
nGaps = numGaps(line);
if (nGaps == 0) { line = compLine(line, width).replace(" ", "."); }
else if (nGaps == width) { line = line.replace(" ", "."); }
else{
int posArray[] = new int[nGaps];
posArray = pos(line, nGaps);
gapsLeft = width - line.length();
spToAdd = gapsLeft / nGaps;
modLeft = gapsLeft % nGaps;
route = gapsLeft / nGaps;
sp = spGen(spToAdd);
line = reFormat(posArray, line, width, sp, spToAdd);
if (line.length() < width){
System.out.print("#OK\n");
nGaps = numGaps(line);
int posArray2[] = new int[nGaps];
posArray2 = pos(line, nGaps);
line = compFormat(posArray2, line, modLeft);
}
line = line.replace(" ", ".");
}
System.out.println(line);
System.out.println("#Length is: " + line.length());
System.out.print("#Enter line of text : " );
line = BIO.getString().trim();
}
}
public static int numGaps(String oLine){
int numGaps = 0;
for (char c : oLine.toCharArray()) { if (c == ' ') { numGaps++; } }
return numGaps;
}
public static String spGen(int count) {
return new String(new char[count]).replace("\0", " ");
}
public static String compLine(String oLine, int width){
String newLine = oLine;
int pos = oLine.length();
int numOSpace = width - oLine.length();
String sp = spGen(numOSpace);
newLine = new StringBuilder(newLine).insert(pos, sp).toString();
return newLine;
}
public static int[] pos(String oLine, int nGaps){
int posArray[] = new int[nGaps];
int i = 0;
for (int pos = 0; pos < oLine.length(); pos++) {
if (oLine.charAt(pos) == ' ') { posArray[i] = pos; i++; }
}
//for (int y = 0; y < x; ++y) { System.out.println(posArray[y]); }
return posArray;
}
public static String reFormat(int[] posArray, String oLine, int width, String sp, int spToAdd){
String newLine = oLine;
int mark = 0;
for (int i = 0; i < posArray.length; ++i){ /*insert string at mark, shift next element by the num of elements inserted*/
if (newLine.length() > width) { System.out.println("Maths is wrong: ERROR"); System.exit(1);}
else { newLine = new StringBuilder(newLine).insert(posArray[i]+mark, sp).toString(); mark += spToAdd; }
}
return newLine;
}
public static String compFormat(int[] posArray2, String mLine, int modLeft){
String newLine = mLine;
int mark = 0;
for (int i = 0; i < modLeft; ++i){
//positions
//if position y is != y+1 insert sp modLeft times
if (posArray2[i] != posArray2[i+1] && posArray2[i] != posArray2[posArray2.length - 1]){
newLine = new StringBuilder(newLine).insert(posArray2[i]+mark, " ").toString(); mark++;
}
}
return newLine;
}
}
I am trying to split a one dimensional array of display modes into a 2-dimensional string array, though I have encountered trouble where I got to the point of splitting the sorted array of display modes. My question: How can I split the single array, which is already sorted, into a two dimensional array? The code (Sorry about the weird variable names):
public static String[][] OrganizeDisplayModes (DisplayMode[] modes) {
int iter = 0;
int deltaIter = 0;
int rows = 0;
int columns = 0;
String[][] tobe;
//bubble sorting
for (int a = 0; a < modes.length - 1; a++) {
for(int i = 0; i < modes.length - 1; i++) {
if (modes[i].getWidth() < modes[i+1].getWidth()) {
DisplayMode change = modes[i];
modes[i] = modes[i+1];
modes[i+1] = change;
}
}
}
for(int i = 0; i < modes.length - 1; i++) {
if ((modes[i].getWidth() == modes[i+1].getWidth()) && (modes[i].getBitsPerPixel() < modes[i+1].getBitsPerPixel())) {
DisplayMode change = modes[i];
modes[i] = modes[i+1];
modes[i+1] = change;
}
}
for(int i = 0; i < modes.length - 1; i++) {
if ((modes[i].getWidth() == modes[i+1].getWidth()) && (modes[i].getFrequency() < modes[i+1].getFrequency())) {
DisplayMode change = modes[i];
modes[i] = modes[i+1];
modes[i+1] = change;
}
}
for(int i = 0; i < modes.length; i++) {
DisplayMode current = modes[i];
System.out.println(i + ". " + current.getWidth() + "x" + current.getHeight() + "x" +
current.getBitsPerPixel() + " " + current.getFrequency() + "Hz");
}
//fit into string array
for (int i = 0; i < modes.length - 1; i++) {
if (!(modes[i].getWidth() == modes[i+1].getWidth())) {
rows += 1;
deltaIter = i - deltaIter;
if (deltaIter > columns)
columns = deltaIter;
}
}
//split the displaymode array into the two-dimensional string one here
tobe = new String[rows][columns];
for (int i = 0; i < rows; i++) {
for (int a = 0; a < columns; a++) {
if((modes[iter].getWidth() == modes[iter+1].getWidth())) {
tobe[i][a] = iter + ". " + modes[iter].toString() + " ";
}
else
break;
if (!(iter >= 68))
iter += 1;
}
if (iter >= 68)
break;
}
tobe[rows-1][columns-1] = (iter + 1) + ". " + modes[iter].toString() + " ";
//test to see that it works
for (int i = 0; i < rows; i++) {
for (int a = 0; a < columns; a++) {
if(tobe[i][a] != null)
System.out.print(tobe[i][a]);
else
break;
}
System.out.println("");
}
System.exit(0);
return null;
}
The output looks like this:
0. 1440x900x32 75Hz
1. 1440x900x16 75Hz
2. 1440x900x32 60Hz
3. 1440x900x16 60Hz
with all of the different possible resolutions. Basically, what I'm trying to do is make a readable list of the different resolutions, so a user can select their desired one. Thank you.
How about storing the information in a different manner? When I made the transition from C to Java I used to use multi-dimensional arrays quite a bit, but it's a pain.
public class ScreenType implements Comparable {
int width;
int height;
int color; // not sure what this one was for, assuming 32/16 bit color
int hertz;
public ScreenType(int w, int h, int c, int h) {
width = w;
height = h;
color = t;
hertz = h;
}
// remember to maintain transitive property,
// see JDK documentation for Comparable
#Override
public int compareTo(Tuple other) {
}
// getters and setters and whatnot
#Override
public String toString() {
return width + "X" + height + "X" + color+ " " + hertz + "hz";
}
}
Then store your screen data like this and use an ArrayList of ScreenTypes which, if I remember right, will sort based on your overriding of compareTo()
I am working on the RSA algorithm and have made some progress but it is not working. I have the following code.
public class RSA
{
public static void main(String args[])
{
String plainText = "ITS ALL GREEK TO ME";//temp local plaintext ignoring parameter
plainText = plainText.toUpperCase();
plainText = plainText.replaceAll("\\s","");
System.out.println(plainText);
String cipherText = "";
int p = 47; //has been provided
int q = 59; //has been provided
int d = 157; //has been provided
int n = p * q;//calculate n
int w = (p - 1)*(q - 1);// calculate W
int c = 0;//we will compute this = cipher variable
int m = 920;//hardcoded for now
int e = 17;//hardcoded for now
//start of euclids
ArrayList<Integer> remainderlist=new ArrayList<Integer>();//array list to hold the remainder values in euclids algorithm from the quotient
remainderlist.add(w);// step 1 of euclids algorithm starting with value of w as above
remainderlist.add(d);// step 2 of euclids algorithm to add value of d
int remainderposition1 = 0;
int remainderposition2 = 1;
int quotient = 0;
int remainder = 0;
while (remainderlist.get(remainderposition1)%(remainderlist.get(remainderposition2))>0){
quotient = remainderlist.get(remainderposition1)/remainderlist.get(remainderposition2);
remainder = remainderlist.get(remainderposition1)%remainderlist.get(remainderposition2);
remainderlist.add(remainder);
System.out.println("Q: " +quotient);
System.out.println("R: " +remainder);
System.out.println("");
remainderposition1++;
remainderposition2++;
}
//start string processing
//loop etc
if (plainText.length()%2!=0)
{
plainText = plainText + " ";
}
for (int i = 0, i < plainText.length(); i = i+2)
{
char plTChar1 = plainText.CharAt(i);
char plTChar2 = plainText.CharAt(i + 1);
// Convert the character into an ASCII table value.
int asciiValue1 = (int) plTChar1;
int asciiValue2 = (int) plTChar2;
String numStr1 = asciiValue1.parseInt;
String numStr2 = asciiValue2.parseInt;
if (numStr.length() < 2)
{
numStr = "0" + numStr;
}
String fullNum = numStr1 + numStr2;
int m = Integer.parse(fullNum);
//start of encryption algorithm
String binarystring = Integer.toBinaryString(e);// step 1
System.out.println(binarystring);
c = 1; // step 2 of the encryption algorithm - notes
for (int i = 0; i<binarystring.length();i++)
{
c = (c*c)%n;// setp 3a
System.out.println(binarystring.charAt(i));
// step 3b notes
if (binarystring.charAt(i)=='1') {
c = (c*m)%n;
}
}
System.out.println("Cipher"+c);
}
When I build the file I get errors on the line for (int i = 0, i < plainText.length(); i = i+2) saying that quotation marks are expected and that it is an illegal start to an expression. I'm lost
You have a comma instead of a semi-colon.
for (int i = 0, i < plainText.length(); i = i+2)
Should be
for (int i = 0; i < plainText.length(); i = i+2)
Often the smallest syntax error will confuse you for hours!