Mini AES java issue - java

So I am having some issues running some code for a minu-AES I am making on Java. Each time I run the code I am given a null exception in thread "main" java.lanf.stringIndexOutOfBoundsException: String index out of range: 8
I wonder if this might be a memory issue.
Currently running netbeans 8.2
The code worked before I implemented the classes.
package miniaestesting;
import java.util.*;
class Tables {
public Tables() {
}
public HashMap fillSubTable(HashMap emptyTable, boolean isInverse) {
if (isInverse == false) {
emptyTable.put(0b0000, 0b1110);
emptyTable.put(0b0001, 0b0100);
emptyTable.put(0b0010, 0b1101);
emptyTable.put(0b0011, 0b0001);
emptyTable.put(0b0100, 0b0010);
emptyTable.put(0b0101, 0b1111);
emptyTable.put(0b0110, 0b1011);
emptyTable.put(0b0111, 0b1000);
emptyTable.put(0b1000, 0b0011);
emptyTable.put(0b1001, 0b1010);
emptyTable.put(0b1010, 0b0110);
emptyTable.put(0b1011, 0b1100);
emptyTable.put(0b1100, 0b0101);
emptyTable.put(0b1101, 0b1001);
emptyTable.put(0b1110, 0b0000);
emptyTable.put(0b1111, 0b0111);
}
//Call the .put method, fill the HashMap with the NibbleSub table
else {
emptyTable.put(0b0000, 0b1110);
emptyTable.put(0b0001, 0b0011);
emptyTable.put(0b0010, 0b0100);
emptyTable.put(0b0011, 0b1000);
emptyTable.put(0b0100, 0b0001);
emptyTable.put(0b0101, 0b1100);
emptyTable.put(0b0110, 0b1010);
emptyTable.put(0b0111, 0b1111);
emptyTable.put(0b1000, 0b0111);
emptyTable.put(0b1001, 0b1101);
emptyTable.put(0b1010, 0b1001);
emptyTable.put(0b1011, 0b0110);
emptyTable.put(0b1100, 0b1011);
emptyTable.put(0b1101, 0b0010);
emptyTable.put(0b1110, 0b0000);
emptyTable.put(0b1111, 0b0101);
}
return emptyTable;
}
public int[][] fillHexTable() {
int[][] table = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF},
{0, 2, 4, 6, 8, 0xA, 0xC, 0xE, 3, 1, 7, 5, 0xB, 9, 0xF, 0xD},
{0, 3, 6, 5, 0xC, 0xF, 0xA, 9, 0xB, 8, 0xD, 0xE, 7, 4, 1, 2},
{0, 4, 8, 0xC, 3, 7, 0xB, 0xF, 6, 2, 0xE, 0xA, 5, 1, 0xD, 9},
{0, 5, 0xA, 0xF, 7, 2, 0xD, 8, 0xE, 0xB, 4, 1, 9, 0xC, 3, 6},
{0, 6, 0xC, 0xA, 0xB, 0xD, 7, 1, 5, 3, 9, 0xF, 0xE, 8, 2, 4},
{0, 7, 0xE, 9, 0xF, 8, 1, 6, 0xD, 0xA, 3, 4, 2, 5, 0xC, 0xB},
{0, 8, 3, 0xB, 6, 0xE, 5, 0xD, 0xC, 4, 0xF, 7, 0xA, 2, 9, 1},
{0, 9, 1, 8, 2, 0xB, 3, 0xA, 4, 0xD, 5, 0xC, 6, 0xF, 7, 0xE},
{0, 0xA, 7, 0xD, 0xE, 4, 9, 3, 0xF, 5, 8, 2, 1, 0xB, 6, 0xC},
{0, 0xB, 5, 0xE, 0xA, 1, 0xF, 4, 7, 0xC, 2, 9, 0xD, 6, 8, 3},
{0, 0xC, 0xB, 7, 5, 9, 0xE, 2, 0xA, 6, 1, 0xD, 0xF, 3, 4, 8},
{0, 0xD, 9, 4, 1, 0xC, 8, 5, 2, 0xF, 0xB, 6, 3, 0xE, 0xA, 7},
{0, 0xE, 0xF, 1, 0xD, 3, 2, 0xC, 9, 7, 6, 8, 4, 0xA, 0xB, 5},
{0, 0xF, 0xD, 2, 9, 6, 4, 8, 1, 0xE, 0xC, 3, 8, 7, 5, 0xA}
};
// Return the hex-multiplication table used in MixColumns
return table;
}
}
class Substitutions {
private Tables tables;
private HashMap<Integer, Integer> subTable;
public Substitutions() {
this.tables = new Tables();
this.subTable = new HashMap<>();
}
public int keyNibbleSub(int nibble) {
tables.fillSubTable(subTable, false); // Call a helper method to fill the HashMap with key-value pairs
System.out.println(subTable.get(nibble)); // Get the substitution value for the nibble and return it
return 5;
}
public int[][] nibbleSub(int[][] cipherState, boolean isInverse) {
int[][] nextCipherState = new int[2][2]; // Declare and initialise empty 2x2 array
tables.fillSubTable(subTable, isInverse); // Call a helper method to fill the HashMap with key-value pairs
for (int row = 0; row < 1; row++) {
for (int col = 0; col < 1; col++) {
// For each element in block
nextCipherState[row][col] = subTable.get(cipherState[row][col]);
// Call the .get method on the HashMap, using the element as a key-lookup
// Assign the returned element to the index in returnBlock
}
}
return nextCipherState;
}
public int getKeyNibbleSub(int nibble) {
return keyNibbleSub(nibble);
}
public int[][] getNibbleSub(int[][] cipherState, boolean isInverse) {
return
nibbleSub(cipherState, isInverse);
}
}
class KeySet {
//-----------------------------//Fields//-----------------------------//
private int[][] key_0, key_1, key_2;
private Substitutions substitutions;
private Tables tables;
//-----------------------------//Constructor//-----------------------------//
public KeySet(int[][] startingKey) {
this.substitutions = new Substitutions();
this.key_0 = startingKey;
this.key_1 = genKey(key_0, 1);
this.key_2 = genKey(key_1, 2);
}
//-----------------------------//Methods//-----------------------------//
private int[][] genKey(int[][] key, int roundConst) {
int[][] newKey = new int[2][2]; // Declare an empty 2x2 array to store the new key
newKey[0][0] = key[0][0] ^ substitutions.keyNibbleSub(key[1][1]) ^
roundConst;
// For the first nibble in the new key,
// XOR the first value in the given key
// with the nibbleSub of the final value in the given key
//, and with the rounding constant variable
newKey[0][1] = key[0][1] ^ newKey[0][0];
newKey[1][0] = key[1][0] ^ newKey[0][1];
newKey[1][1] = key[1][1] ^ newKey[1][0];
// Generate the other three nibbles
return newKey;
}
//----Getter methods for full implementation---//
public int[][] getKey_0() {
return key_0;
}
public int[][] getKey_1() {
return key_1;
}
public int[][] getKey_2() {
return key_2;
}
}
class MiniAES {
private KeySet keys;
private String startingString;
private String finalString;
private int[][] character;
private int[][] cipherState;
private Substitutions substitutions;
private Tables tables;
public MiniAES(String startingString, String startKey) {
this.substitutions = new Substitutions();
this.tables = new Tables();
this.startingString = startingString;
this.keys = new KeySet(convertToArray(startKey));
}
public String encryptString() {
//ystem.out.println(startingString);
for (int i = 0; i < this.startingString.length() - 1; i++) {
character =
convertToArray(Integer.toBinaryString(startingString.charAt(i)));
cipherState = encryptChar(character);
finalString = finalString + convertToString(cipherState);
}
return finalString;
}
public static String convertToString(int[][] array) {
String[][] toFill = new String[2][2];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[0].length; j++) {
toFill[i][j] = Integer.toString(array[i][j]);
while (toFill[i][j].length() <= 3) {
toFill[i][j] = "0" +
toFill[i][j];
}
}
}
String charAsBinaryString = toFill[0][0] + toFill[0][1] + toFill[1][0]
+ toFill[1][1];
int asInteger = Integer.parseInt(charAsBinaryString, 2);
String charAsString = Character.toString((char) asInteger);
return charAsString;
}
public static int[][] convertToArray(String toConvert) {
int[][] newBlock = new int[2][2];
newBlock[0][0] = Integer.parseInt(toConvert.substring(0, 4));
newBlock[0][1] = Integer.parseInt(toConvert.substring(4, 8));
newBlock[1][0] = Integer.parseInt(toConvert.substring(8, 12));
newBlock[1][1] = Integer.parseInt(toConvert.substring(12, 16));
return newBlock;
}
private int[][] encryptChar(int[][] character) {
addRoundKey(character, keys.getKey_0());
cipherState = substitutions.nibbleSub(cipherState, false);
shiftRows();
mixColumns();
addRoundKey(cipherState, keys.getKey_1());
cipherState = substitutions.nibbleSub(cipherState, false);
shiftRows();
addRoundKey(cipherState, keys.getKey_2());
return cipherState;
}
private void addRoundKey(int[][] cipherState, int[][] key) {
int[][] nextCipherState = new int[2][2]; // Declare and initialise an empty 2x2 array
for (int row = 0; row < cipherState.length; row++) {
for (int col = 0; col < cipherState[0].length; col++) {
// For each element in cipherState
nextCipherState[row][col] = cipherState[row][col] ^ key[row]
[col]; // XOR it with the corresponding element in key
// Assign it to the same index in nextCipherState
}
}
this.cipherState = nextCipherState;
}
private void shiftRows() {
int[][] nextCipherState = new int[2][2]; // Declare and initialise new array
nextCipherState[0][0] = this.cipherState[0][0];
nextCipherState[0][1] = this.cipherState[0][1];
//Copy the values from cipherState into the top row of the new array
nextCipherState[1][0] = this.cipherState[1][1];
nextCipherState[1][1] = this.cipherState[1][0];
//Copy the values from cipherState into the bottom row of the new array, in reverse order
this.cipherState = nextCipherState;
}
private void mixColumns() {
int[][] nextCipherState = new int[2][2]; // Declare and initialise empty 2x2 array
nextCipherState[0][0] = hexSubstitution(this.cipherState[0][0],
this.cipherState[1][0], 0);
nextCipherState[1][0] = hexSubstitution(this.cipherState[0][0],
this.cipherState[1][0], 1);
nextCipherState[0][1] = hexSubstitution(this.cipherState[0][1],
this.cipherState[1][1], 0);
nextCipherState[01][1] = hexSubstitution(this.cipherState[0][1],
this.cipherState[1][1], 1);
this.cipherState = nextCipherState;
}
private int hexSubstitution(int topRowElement, int bottomRowElement, int
constRow) {
int[][] hexTable = tables.fillHexTable(); // Declare an empty 2d array and call the getHexTable() helper method to fill it
// Due to the large size of the hex table, this is implemented for readability.
int[][] constantMatrix = {
{0b0011, 0b0010},
{0b0010, 0b0011}}; // declare and fill the 2d array which stores the constant matrix
int hexCol, XOR_operand_1, XOR_operand_2; // Declare variables
hexCol = constantMatrix[constRow][0]; // Get index for the hex table lookup
XOR_operand_1 = hexTable[hexCol][topRowElement]; // Find the appropriate element in hexTable and assign to XOR_operand_1
hexCol = constantMatrix[constRow][1]; // // Get index for the hex table lookup
XOR_operand_2 = hexTable[hexCol][bottomRowElement]; // Find the appropriate elemen tin hexTable and assign to XOR_operand_2
return XOR_operand_1 ^ XOR_operand_2; // XOR the two operands and return the result
}
}
package miniaestesting;
public class MiniAESTesting {
public static void main(String[] args) {
int[][] startKey = {
{0b0011, 0b1001},
{0b0110, 0b0111}};
MiniAES encryption1 = new MiniAES("Hello", "0010101100100011");
System.out.println(encryption1.encryptString());
}
}

Related

Determining if a knight can pass through all cells in a 2d array - if so print board

I need an advice regarding this problem called "Knight Path".
Given an n*n board whose cells are initialized to 0, I need to determine, given an arbitrary Knight's position, if the knight can pass through every cell on the board exactly once, where every cell the Knight had visited will be marked as counter, counting from: 1 - n^2.
If a path is possible, I need to print the board. I need to print all the valid boards.
The knight, for those who do not know the rules for chess, can move either up or down one square vertically and over two squares horizontally OR up or down two squares vertically and over one square horizontally.
For example given a 5*5 board, starting at (0,0) the method should print:
{{1,16,11,6,21},
{10,5,20,15,12},
{17,2,13,22,7},
{4,9,24,19,14},
{25,18,3,8,23}};
The above out put would be one of few, as there could be different other ways considering different initial positions.
I've written the below code but it doesn't print anything. I need to spot the logic flaws here so I can make it work.
public class KnightDemo {
static int counter = 1;
public static void KnightPath(int[][] b, int i, int j) {
b[i][j] = counter;
if (counter == b.length * b[0].length) {
printMatrix(b);
return;
} else {
counter++;
if (isValid(b, i - 1, j + 2) && b[i - 1][j + 2] == 0) {
KnightPath(b, i - 1, j + 2);
} else {
return;
}
if (isValid(b, i - 2, j + 1) && b[i - 1][j + 1] == 0) {
KnightPath(b, i - 2, j + 1);
} else {
return;
}
if (isValid(b, i - 1, j - 2) && b[i - 1][j - 2] == 0) {
KnightPath(b, i - 1, j - 2);
} else {
return;
}
if (isValid(b, i - 2, j - 1) && b[i - 2][j - 1] == 0) {
KnightPath(b, i - 2, j - 1);
} else {
return;
}
if (isValid(b, i + 2, j - 1) && b[i + 2][j - 1] == 0) {
KnightPath(b, i + 2, j - 1);
} else {
return;
}
if (isValid(b, i + 1, j - 2) && b[i + 1][j - 2] == 0) {
KnightPath(b, i + 1, j - 2);
} else {
return;
}
if (isValid(b, i + 1, j + 2) && b[i + 1][j + 2] == 0) {
KnightPath(b, i + 1, j + 2);
} else {
return;
}
if (isValid(b, i + 2, j + 1) && b[i + 2][j + 1] == 0) {
KnightPath(b, i + 2, j + 1);
} else {
return;
}
}
}
public static boolean isValid(int[][] a, int i, int j) {
if (i > a.length - 1 || i < 0 || j > a[0].length - 1 || j < 0) {
return false;
}
return true;
}
public static void main(String[] args) {
int[][] b = new int[5][5];
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b[0].length; j++) {
KnightPath(b, i, j);
}
}
}
public static void printMatrix(int[][] matrix) {
for (int[] rows: matrix) {
StringBuilder buff = new StringBuilder();
buff.append("[");
for (int i = 0; i < rows.length; i++) {
int value = rows[i];
buff.append(value);
if (i < rows.length - 1) {
buff.append(", ");
}
}
buff.append("]");
System.out.println(buff.toString());
}
}
}
The output is
[1, 2, 3, 4, 5]
[6, 7, 8, 9, 10]
[11, 12, 13, 14, 15]
[16, 17, 18, 19, 20]
[21, 22, 23, 24, 25]
Based on the OP's explanation in the comments section, the goal is to map out all possible paths a knight can take from a location on the board. Basically, given the knight's location b[i][j], calculate all legal paths.
If a knight is at {0, 0}, the knight has only two legal paths that end in {1, 2} and {2, 1}. The idea here is to capture that in a map. Then, move on to the next location on the board (i.e. {1, 0}) and repeat the process. Since each board location can be identified as an integer (counter), we can use it to map the paths...
0=[{1, 2}, {2, 1}]
1=[{2, 2}, {1, 3}, {2, 0}]
...
n=[{n^-2 - 3, n^-2 - 2}, {n^-2 - 2, n^-2 - 3}] // last location is always a corner
To make it simple, I decided to create a Java record of coordinates to store the {x, y} coordinates of the end location of a given path, making my map <Integer, Set<Coordinates>>
The logic here is quite simple. First, seed the map with empty lists for each one corresponding location in the matrix. Then, iterate through the matrix (2D array) and calculate all the legal paths a knight can take from this location. For each legal path, add the Coordinates of the end location of the path. I used a Set to eliminate duplicate coordinates.
My solution (perhaps not optimal) is as follows (used OP code as baseline) - Need Java 15 or later to run. For Java 14 or earlier, replace Coordinates with an Integer[] of length 2, and store the coordinates in it.
public class KnightDemo {
static int counter = 0;
static Map<Integer, Set<Coordinates>> map = new HashMap<>();
public static void KnightPath(int[][] b, int i, int j) {
Set<Coordinates> paths = map.get(counter);
if (isValid(b, i - 1, j + 2)) {
paths.add(new Coordinates(i - 1, j + 2));
map.put(counter, paths);
}
if (isValid(b, i - 2, j + 1)) {
paths.add(new Coordinates(i - 2, j + 1));
map.put(counter, paths);
}
if (isValid(b, i - 1, j - 2)) {
paths.add(new Coordinates(i - 1, j - 2));
map.put(counter, paths);
}
if (isValid(b, i - 2, j - 1)) {
paths.add(new Coordinates(i - 2, j - 1));
map.put(counter, paths);
}
if (isValid(b, i + 2, j - 1)) {
paths.add(new Coordinates(i + 2, j - 1));
map.put(counter, paths);
}
if (isValid(b, i + 1, j - 2)) {
paths.add(new Coordinates(i + 1, j - 2));
map.put(counter, paths);
}
if (isValid(b, i + 1, j + 2)) {
paths.add(new Coordinates(i + 1, j + 2));
map.put(counter, paths);
}
if (isValid(b, i + 2, j + 1)) {
paths.add(new Coordinates(i + 2, j + 1));
map.put(counter, paths);
}
counter++;
}
public static boolean isValid(int[][] a, int i, int j) {
return i >= 0 && i < a.length && j >= 0 && j < a[0].length;
}
public static void main(String[] args) {
int[][] b = new int[5][5];
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b[0].length; j++) {
map.put(counter, new HashSet<>()); // add a new set before calculating paths
KnightPath(b, i, j);
}
}
map.entrySet().stream().forEach(System.out::println);
}
private static record Coordinates(int row, int col) {
#Override
public String toString() {
return "{" + row + ", " + col + "}";
}
}
}
The program outputs:
0=[{1, 2}, {2, 1}]
1=[{2, 2}, {1, 3}, {2, 0}]
2=[{2, 3}, {1, 4}, {2, 1}, {1, 0}]
3=[{2, 2}, {1, 1}, {2, 4}]
4=[{2, 3}, {1, 2}]
5=[{2, 2}, {0, 2}, {3, 1}]
6=[{2, 3}, {0, 3}, {3, 0}, {3, 2}]
7=[{0, 0}, {3, 3}, {2, 4}, {0, 4}, {3, 1}, {2, 0}]
8=[{0, 1}, {3, 4}, {3, 2}, {2, 1}]
9=[{3, 3}, {2, 2}, {0, 2}]
10=[{1, 2}, {0, 1}, {4, 1}, {3, 2}]
11=[{0, 0}, {3, 3}, {1, 3}, {0, 2}, {4, 0}, {4, 2}]
12=[{0, 1}, {3, 4}, {1, 4}, {0, 3}, {4, 1}, {3, 0}, {1, 0}, {4, 3}]
13=[{1, 1}, {4, 4}, {0, 2}, {0, 4}, {4, 2}, {3, 1}]
14=[{1, 2}, {0, 3}, {4, 3}, {3, 2}]
15=[{2, 2}, {1, 1}, {4, 2}]
16=[{2, 3}, {1, 2}, {1, 0}, {4, 3}]
17=[{1, 1}, {4, 4}, {2, 4}, {1, 3}, {4, 0}, {2, 0}]
18=[{1, 2}, {1, 4}, {4, 1}, {2, 1}]
19=[{2, 2}, {1, 3}, {4, 2}]
20=[{3, 2}, {2, 1}]
21=[{3, 3}, {2, 2}, {2, 0}]
22=[{3, 4}, {2, 3}, {3, 0}, {2, 1}]
23=[{2, 2}, {2, 4}, {3, 1}]
24=[{2, 3}, {3, 2}]
UPDATE: Can you use this in a real game of chess?
Yes, you can! Suppose you seed the matrix with black and white. You could enhance the logic so that, if the end location corresponds to your color, you don't add as a valid path since it is blocked by one of your pieces.
SECOND UPDATE: Same code but using Coordinate object as key
public class KnightDemo {
static int counter = 0;
static Map<Coordinates, Set<Coordinates>> map = new HashMap<>();
public static void KnightPath(int[][] b, Coordinates coordinates) {
Set<Coordinates> paths = map.get(coordinates);
if (isValid(b, coordinates.row() - 1, coordinates.col() + 2)) {
paths.add(new Coordinates(coordinates.row() - 1, coordinates.col() + 2));
map.put(coordinates, paths);
}
if (isValid(b, coordinates.row() - 2, coordinates.col() + 1)) {
paths.add(new Coordinates(coordinates.row() - 2, coordinates.col() + 1));
map.put(coordinates, paths);
}
if (isValid(b, coordinates.row() - 1, coordinates.col() - 2)) {
paths.add(new Coordinates(coordinates.row() - 1, coordinates.col() - 2));
map.put(coordinates, paths);
}
if (isValid(b, coordinates.row() - 2, coordinates.col() - 1)) {
paths.add(new Coordinates(coordinates.row() - 2, coordinates.col() - 1));
map.put(coordinates, paths);
}
if (isValid(b, coordinates.row() + 2, coordinates.col() - 1)) {
paths.add(new Coordinates(coordinates.row() + 2, coordinates.col() - 1));
map.put(coordinates, paths);
}
if (isValid(b, coordinates.row() + 1, coordinates.col() - 2)) {
paths.add(new Coordinates(coordinates.row() + 1, coordinates.col() - 2));
map.put(coordinates, paths);
}
if (isValid(b, coordinates.row() + 1, coordinates.col() + 2)) {
paths.add(new Coordinates(coordinates.row() + 1, coordinates.col() + 2));
map.put(coordinates, paths);
}
if (isValid(b, coordinates.row() + 2, coordinates.col() + 1)) {
paths.add(new Coordinates(coordinates.row() + 2, coordinates.col() + 1));
map.put(coordinates, paths);
}
}
public static boolean isValid(int[][] a, int i, int j) {
return i >= 0 && i < a.length && j >= 0 && j < a[0].length;
}
public static void main(String[] args) {
int[][] b = new int[5][5];
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b[0].length; j++) {
Coordinates coordinates = new Coordinates(i, j);
map.put(coordinates, new HashSet<>());
KnightPath(b, coordinates);
counter++;
}
}
map.entrySet().stream().forEach(System.out::println);
}
private static record Coordinates(int row, int col) {
#Override
public String toString() {
return "{" + row + ", " + col + "}";
}
}
}
Outputs:
{0, 0}=[{1, 2}, {2, 1}]
{2, 2}=[{0, 1}, {3, 4}, {1, 4}, {0, 3}, {4, 1}, {3, 0}, {1, 0}, {4, 3}]
{4, 4}=[{2, 3}, {3, 2}]
{0, 1}=[{2, 2}, {1, 3}, {2, 0}]
{2, 3}=[{1, 1}, {4, 4}, {0, 2}, {0, 4}, {4, 2}, {3, 1}]
{0, 2}=[{2, 3}, {1, 4}, {2, 1}, {1, 0}]
{2, 4}=[{1, 2}, {0, 3}, {4, 3}, {3, 2}]
{0, 3}=[{2, 2}, {1, 1}, {2, 4}]
{0, 4}=[{2, 3}, {1, 2}]
{3, 0}=[{2, 2}, {1, 1}, {4, 2}]
{3, 1}=[{2, 3}, {1, 2}, {1, 0}, {4, 3}]
{1, 0}=[{2, 2}, {0, 2}, {3, 1}]
{3, 2}=[{1, 1}, {4, 4}, {2, 4}, {1, 3}, {4, 0}, {2, 0}]
{1, 1}=[{2, 3}, {0, 3}, {3, 0}, {3, 2}]
{3, 3}=[{1, 2}, {1, 4}, {4, 1}, {2, 1}]
{1, 2}=[{0, 0}, {3, 3}, {2, 4}, {0, 4}, {3, 1}, {2, 0}]
{3, 4}=[{2, 2}, {1, 3}, {4, 2}]
{1, 3}=[{0, 1}, {3, 4}, {3, 2}, {2, 1}]
{1, 4}=[{3, 3}, {2, 2}, {0, 2}]
{4, 0}=[{3, 2}, {2, 1}]
{4, 1}=[{3, 3}, {2, 2}, {2, 0}]
{2, 0}=[{1, 2}, {0, 1}, {4, 1}, {3, 2}]
{4, 2}=[{3, 4}, {2, 3}, {3, 0}, {2, 1}]
{2, 1}=[{0, 0}, {3, 3}, {1, 3}, {0, 2}, {4, 0}, {4, 2}]
{4, 3}=[{2, 2}, {2, 4}, {3, 1}]
They don't print in the same order, but you can tell that coordinates {2, 2} is the same set as counter==12 in the previous example. Cell {2, 2} is the 13th cell from the top-left.
To solve for all paths, you need to reset the placed values of paths you've exhausted so that newer paths can access them. Additionally, your counter should reflect how deep you've gone, so that if you back out to try another path, your counter should roll back, too. I would recommend passing a counter as a parameter rather than using a static counter. Also, if you want to try all valid possibilities, then you need to avoid those return statements whenever one possibility is deemed invalid.
public static void KnightPath(int[][] b, int i, int j, int counter) {
...
if (isValid(b, i - 1, j + 2) && b[i - 1][j + 2] == 0) {
KnightPath(b, i - 1, j + 2, counter+1);
}
...
b[i][j] = 0;
}
public static void main(String[] args) {
...
KnightPath(b, i, j, 1);
...
}

Sudoku solver using recursion and backtracking

I am trying to implement a Sudoku solver using Java. This is the code I've written as of now. If I try to run it, it goes on to an endless loop that keeps on printing the first row of the Sudoku board, and that too with an incorrect solution. I guess I'm implementing backtracking the incorrect way over here. I think I am printing the final and wrong as well, as only the first row is printed every time. Can someone please help me fix my code and tell me as to where I am going wrong?
public static void display(int[][] board) {
for(int[] arr : board) {
System.out.println(Arrays.toString(arr));
return;
}
}
public static boolean isSafe(int[][] board, int row, int col, int i) {
//check row
for(int a=0; a<board.length; a++) {
if(board[a][col]==i) {
return false;
}
}
//check col
for(int b=0; b<board.length; b++) {
if(board[row][b]==i) {
return false;
}
}
//check cell
int strow = row-(row%3);
int stcol = col-(col%3);
for(int x=strow; x<strow+3; x++) {
for(int y=stcol; y<stcol+3; y++) {
if(board[x][y]==i) {
return false;
}
}
}
return true;
}
public static void sudoku(int[][] board, int row, int col) {
if(row==board.length) {
display(board);
System.out.println();
return; //modify this to print ans
}
if(col==board.length) {
sudoku(board, row+1, 0);
return;
}
if(board[row][col]==0) {
for(int i=1; i<=9; i++) {
if(isSafe(board, row, col, i)) {
board[row][col]=i;
sudoku(board, row, col+1);
board[row][col]=0;
}
}
}
sudoku(board, row, col+1);
}
public static void main(String args[]) {
int[][] board=
{ {3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0} };
sudoku(board, 0, 0);
}
A bactracking algorithm can be applied here and the problem happens in your sudoku method.
First of all we can just pass the board and we don't want to pass the row and col.
We can just pass the board and the just traverse through each and every cell.
Only consider those cells that are 0's.
We don't want to consider any other cells as 0"s are the cells we are interested in.
Now if we see a cell which is 0, we try to find all the different possibilites from 1 to 9 which can fit in that cell and apply the 'isSafe()` logic which will just do the same check.
And we backtrack and continue with our checking.
public static void display(int[][] board) {
for(int[] arr : board) {
System.out.println(Arrays.toString(arr));
}
}
public static boolean isSafe(int[][] board, int row, int col, int i) {
//check row
for(int a=0; a<board.length; a++) {
if(board[a][col]==i) {
return false;
}
}
//check col
for(int b=0; b<board.length; b++) {
if(board[row][b]==i) {
return false;
}
}
//check cell
int strow = row-(row%3);
int stcol = col-(col%3);
for(int x=strow; x<strow+3; x++) {
for(int y=stcol; y<stcol+3; y++) {
if(board[x][y]==i) {
return false;
}
}
}
return true;
}
public static boolean sudoku(int [][] board) {
for (int i=0; i<9; i++) {
for (int j=0; j<9; j++) {
int current = board[i][j];
if (current == 0) {
for (int ch = 1; ch <= 9; ch++) {
if (isSafe(board, i, j, ch)) {
board[i][j] = ch;
if (sudoku(board)) {
return true;
}
board[i][j] = 0;
}
}
return false;
}
}
}
return true;
}
public static void main(String args[]) {
int[][] board=
{ {3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0} };
sudoku(board);
display(board);
}
Here is the output after the change
[3, 1, 6, 5, 7, 8, 4, 9, 2]
[5, 2, 9, 1, 3, 4, 7, 6, 8]
[4, 8, 7, 6, 2, 9, 5, 3, 1]
[2, 6, 3, 4, 1, 5, 9, 8, 7]
[9, 7, 4, 8, 6, 3, 1, 2, 5]
[8, 5, 1, 7, 9, 2, 6, 4, 3]
[1, 3, 8, 9, 4, 7, 2, 5, 6]
[6, 9, 2, 3, 5, 1, 8, 7, 4]
[7, 4, 5, 2, 8, 6, 3, 1, 9]
Note : I changed the return type to true or false inorder to make sure that a particular cell can be filled with a number say x. If its possible we return true and continue with the next cell which is 0, other wise we backtrack and check for other possibilities.
Updates :
The only change you are missing is an else block at the very end because even if the cell is 0 or any other number you are doing recursion sudoku(board, row, col+1);. So just enclose that statement in the else block and will give the desired output.
Code change without changing the return type:
public static void display(int[][] board) {
for(int[] arr : board) {
System.out.println(Arrays.toString(arr));
}
}
public static boolean isSafe(int[][] board, int row, int col, int i) {
//check row
for(int a=0; a<board.length; a++) {
if(board[a][col]==i) {
return false;
}
}
//check col
for(int b=0; b<board.length; b++) {
if(board[row][b]==i) {
return false;
}
}
//check cell
int strow = row-(row%3);
int stcol = col-(col%3);
for(int x=strow; x<strow+3; x++) {
for(int y=stcol; y<stcol+3; y++) {
if(board[x][y]==i) {
return false;
}
}
}
return true;
}
public static void sudoku(int[][] board, int row, int col) {
if(row==board.length) {
display(board);
System.out.println();
return; //modify this to print ans
}
if(col==board.length) {
sudoku(board, row+1, 0);
return;
}
if(board[row][col]==0) {
for(int i=1; i<=9; i++) {
if(isSafe(board, row, col, i)) {
board[row][col]=i;
sudoku(board, row, col+1);
board[row][col]=0;
}
}
}
else
sudoku(board, row, col+1);
}
public static void main(String args[]) {
int[][] board=
{ {3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0} };
sudoku(board, 0, 0);
}
Output :
[3, 1, 6, 5, 7, 8, 4, 9, 2]
[5, 2, 9, 1, 3, 4, 7, 6, 8]
[4, 8, 7, 6, 2, 9, 5, 3, 1]
[2, 6, 3, 4, 1, 5, 9, 8, 7]
[9, 7, 4, 8, 6, 3, 1, 2, 5]
[8, 5, 1, 7, 9, 2, 6, 4, 3]
[1, 3, 8, 9, 4, 7, 2, 5, 6]
[6, 9, 2, 3, 5, 1, 8, 7, 4]
[7, 4, 5, 2, 8, 6, 3, 1, 9]

Java add array to array special mode

I am working on a game in Java and I need to cache some position-based information. If I have the following array:
int[][] array = {
{1, 2, 3},
{1, 2, 3},
{1, 2, 3}
};
And then I have this other array:
int[][] otherArray = {
{4, 5, 6},
{4, 5, 6},
{4, 5, 6}
};
Now I want to combine them in a special way. I want to add otherArray to the left of array. So the result would look like this:
int[][] combinedArray = {
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3}
};
Then I have this other combined array:
int[][] otherCombinedArray = {
{30, 17, 139, 65, 335, 99},
{50, 43, 57, 53, 423, 534},
{90, 67, 78, 24, 99, 67}
};
Now I want to add it to the top of the original combined array. So the final result would look like this:
int[][] finalCombinedArray = {
{30, 17, 139, 65, 335, 99},
{50, 43, 57, 53, 423, 534},
{90, 67, 78, 24, 99, 67},
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3}
};
Can someone point me to a good library or built in method for doing this? I also wanted to note that the method shouldn't be too computationally heavy (like looping through all the arrays multiple times, and it shouldn't use too much memory, like 80MB).
Thank you for the help!
On it's own, Java does not provide concatenation methods, but we can use System.arraycopy (as suggested by #user16320675 above)
With System.arraycopy you specify the array to copy + the destination array -> you have array A of size 10 and B of size 2, and you use the command to copy your B array into A.
int[] source = { 1,2,3,4,5 };
int[] destination = new int[10];
// You can play with the numbers below
int COPY_AT_INDEX = 0; // Start to copy at position destination[0]
int AMOUNT_TO_COPY = 5; // Copying from 0 to source.length
System.arraycopy(source, 0, destination, COPY_AT_INDEX, AMOUNT_TO_COPY);
System.out.println(Arrays.toString(source)); // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(destination)); // [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
Now, if we use arraycopy, seems you have to determine when to copy as rows, and when to copy as columns.
// Assuming a[][] and b[][] have the same size.
public int[][] mergeAsColumns(int[][] a, int[][] b) {
int rows = a.length;
int columns = a[0].length;
int[][] merged = new int[rows][2 * columns];
for (int i = 0; i < a.length; i++) {
System.arraycopy(a[i], 0, merged[i], 0, columns);
System.arraycopy(b[i], 0, merged[i], rows, columns);
}
return merged;
}
Merging as Rows is similar to the other one, but changes in which positions you want to affect and how you create the merged array.
// Assuming a[][] and b[][] have the same size.
public int[][] mergeAsRows(int[][] a, int[][] b) {
int rows = a.length;
int columns = a[0].length;
int[][] merged = new int[2 * rows][columns];
for (int i = 0; i < rows; i++) {
System.arraycopy(a[i], 0, merged[i], 0, columns);
System.arraycopy(b[i], 0, merged[rows + i], 0, columns);
}
return merged;
}

How to delete last element in array and put new in front?

I have a question concerning Java. I started up new to Java and my google search brought many results but non was the final help.
I created a class to track historical information. I have different values for different days and need to update them un a regular basis. I want to keep track of the last 30 days and created an array with 30 elements. When I call my 'shift' function I want to drop the last n elements and put zeros in front. Here is a minial example for 5 days:
public class Testclass {
private int[] histInfo;
public Element()
{
this.histInfo = new int[5];
}
public void shift_histInfo(long m)
{
//do magic
}
}
What I want shift to do is
INPUT:
histInfo = [50,21,1,45,901]
OPERATION:
shift_histInfo(2);
RESULT:
histInfo = [0,0,50,21,1]
I am thankfull for every kind of help you can support as well for thought-provoking impulses if you think that there is a way more elegant or efficient way.
Best :-)
Unless there are very tight performance constraints using the standard Collection classes will get the job done. Have a look at java.util.LinkedList.
As a programming exercise you might consider creating a ring buffer. The idea being to avoid copying the array on every insertion.
Keep a oldestIndex value.
When writing simply replace item[oldestIndex] and increment oldestIndex.
To iterate you start at oldestIndex and use an increment method to deal with wrapping round to the start of the array.
int nextIndex(int current) {
return (current + 1) % arrayLength;
}
Writing a nice encapsulating class to hide all this would be a good exercise.
You can try this :
public static void shift_histInfo(long m)
{
int[] myIntArray = {50,21,1,45,901};
int[] myIntArray2 = {50,21,1,45,901};
for (int j=0 ;j< myIntArray.length ; j++){
int temp = (int) (j+m);
if (temp >= myIntArray.length){
temp = temp - myIntArray.length;
myIntArray2[temp] = 0;
} else {
myIntArray2[temp] = myIntArray[j];
}
}
for (int j=0 ;j< myIntArray2.length ; j++){
System.out.println(myIntArray2[j]);
}
}
Output :
when shift_histInfo(2) ,
[0,0,50,21,1]
int[] array={1,2,3,4,5,6};
int removelength=2;
int e=1;
while(e<=removelength) {
for(int i=1;i<array.length;i++)
array[array.length-i]=array[array.length-i-1];
e++;
}
for(int i=0;i<removelength;i++) {
array[i]=0;
}
for(int g:array)
{
System.out.print(g);
}
For constraints that you wanted, although I did initialise the data in the same method instead of Element(). I don't know why the parameter is of type long so I left it and made an int local variable.
All it does is copy the index value over to the new array starting at m then increments/iterates until the end of the array.
You can also make the method return type int[] and then simply return changedInfo array. Instead of histInfo = changedInfo.clone();
private int[] histInfo;
public void shift_histInfo(long m) {
int n = (int) m;
this.histInfo = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15};
int length = this.histInfo.length;
int[] changedInfo = new int[length];
if (length - n >= 0) System.arraycopy(histInfo, 0, changedInfo, n + 0, length - n); //Edit: shortened to one line.
histInfo = changedInfo.clone();
System.out.println("Remove: " + n + " - " + Arrays.toString(changedInfo) + "\n");
}
public static void main(String[] args) {
Main main = new Main();
main.shift_histInfo(0);
main.shift_histInfo(30);
main.shift_histInfo(1);
main.shift_histInfo(15);
main.shift_histInfo(29);
}
println:
Remove: 0 - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Remove: 30 - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Remove: 1 - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Remove: 15 - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Remove: 29 - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]

Checking for number repetition in a line or column in a grid

I have to make a Sudoku board and have the grid but am confused as how to check for any repetitions across a line or column. The code for my grid is.
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
grid[i][j] = new JTextField();
BoardPanel.add(grid[i][j]);
So basically i want to check for repetition across i and then down j
Here is the code with an example to show it.
This program will tell if there are two equal numbers in vertical and horizontal bars.
public static void main(String args[]) {
// store your puzzle in puzzle variable.
int puzzle[][] = {
{0, 9, 0, 0, 0, 0, 0, 0, 8},
{0, 0, 3, 2, 0, 7, 0, 9, 0},
{0, 6, 0, 0, 0, 0, 7, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 6},
{0, 0, 5, 4, 3, 2, 1, 0, 0},
{4, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 7, 0, 0, 0, 0, 3, 0},
{0, 2, 0, 9, 0, 8, 6, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 4, 0}
};
testHorizontal(puzzle);
testVertical(puzzle);
}
public static void testHorizontal(int[][] puzzle) {
for (int[] arr : puzzle) {
test(arr);
}
}
public static void testVertical(int[][] puzzle) {
int[] cols = new int[puzzle.length];
for (int i = 0; i < puzzle.length; i++) {
for (int j = 0; j < puzzle.length; j++) {
cols[j] = puzzle[i][j];
test(cols);
}
}
}
public static boolean test(int arr[]) {
boolean flag = false;
for (int a : arr) {
for (int b : arr) {
if (a == b) {
flag = true;
System.out.println("equal numbers found.");
break;
}
}
}
return flag;
}

Categories