I have a string of characters for which I want to encrypt by loading into a 2D array by rows and then printing the array by column. Such that:
|A|B|
|C|D|
|E|
encrypts to "ACEBD".
However I cant seem to be able to avoid dropping characters in the last row in my output getting "ACBD". Any idea how to solve this?
public static void main(String[] args) throws FileNotFoundException {
if (handleArguments(args))
System.out.println("encrypt");
// get input
Scanner input = new Scanner(inputFile);
String line = input.nextLine();
// calculate height of the array
int height = line.length() / width;
// Add one to height if there's a partial last row
if (line.length() % width != 0)
height += 1;
loadUnloadGrid(line, width, height);
}
static void loadUnloadGrid(String line, int width, int height) {
// make an empty array
char grid[][] = new char[height][width];
// fill the array row by row with character from line
int charCount = 0;
for (int r = 0; r < height - 1; r++) {
for (int c = 0; c < width; c++) {
// check to make sure accessing past end of the line
if (charCount < line.length()) {
grid[r][c] = line.charAt(charCount);
charCount++;
}
}
}
// print to standard output the characters in array
System.out.printf("Grid width %d: \"", width);
for (int r = 0; r < width; r++) {
for (int c = 0; c < height; c++) {
System.out.print(grid[c][r]);
}
}
// !!Special handling for last row!!
int longColumn = line.length() % width;
if (longColumn == 0)
longColumn = width;
for (int c = 0; c < longColumn; c++) {
System.out.print(grid[height - 1][c]);
}
System.out.println();
}
You need to loop the rows before you loop the columns, i.e., just the way you usually don't do it.
for (int i = 0; i < array[0].length; i++) {
for (int j = 0; j < array.length; j++) {
// prints columns before rows
}
}
However, be aware that you cannot check whether one row has less columns than another within the loop. Usually array[i].length avoids any NPEs. In this case you might want to define a check whether the array at row j even has column i. This could be done within the second loop by checking:
if (array[j].length > i)
// System.out.println(...);
else
break;
Edit: I see your loop should be working correctly. Most likely height is only 1 instead of 2 and thus, the last row gets cut off. My code as it is works for your input and your loop should be working the same way. Try to print height and check if it is correct or debug your program and go through it step by step.
Related
I'm having trouble with an algorithm, suppose the following:
A cinema has n rows, each row consists of m seats (n and m do not exceed 20). A two-dimensional matrix stores the information on the sold tickets, number 1 means that the ticket for this place is already sold, the number 0 means that the place is available. You want to buy k tickets to the neighboring seats in the same row. Find whether it can be done.
Input data
On the input, the program gets the number of n rows and m seats. Then, there are n lines, each containing m numbers (0 or 1) separated by spaces. The last line contains a number k.
Output data
The program should output the number of the row with k consecutive available seats. If there are several rows with k available seats, output the first row with these seats. If there is no such a row, output the number 0.
Code
import java.util.Scanner;
class Main {
static int findRowWithAvailableSeat(int[][] matrix, int tickets) {
final int rows = matrix.length;
final int columns = matrix[0].length;
int seatCounter = 0;
for (int r = 1; r <= rows; r++) {
for (int c = 1; c <= columns; c++) {
if (matrix[r][c] == 1) {
continue;
} if (matrix[r][c] == matrix[r][c + 1]) {
seatCounter++;
if (seatCounter == tickets) {
return r;
}
}
}
}
return 0;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int rows = scanner.nextInt();
int columns = scanner.nextInt();
int[][] matrix = new int[rows][columns];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
matrix[r][c] = scanner.nextInt();
}
}
int kTickets = scanner.nextInt();
int rowWithAvailableSeats = findRowWithAvailableSeat(matrix, kTickets);
System.out.println(rowWithAvailableSeats);
}
}
I know the problem is somewhere in findRowWithAvailableSeat method. I would like a hint on how to solve the problem, not the actual solution. Thank you very much.
EDIT
I could finally solve it (or at least it works as intended, I'm not sure if it's the best implementation). Thanks you all for your tips.
static int findRowWithAvailableSeat(int[][] matrix, int tickets) {
final int rows = matrix.length;
final int columns = matrix[0].length;
int seatCounter;
for (int r = 0; r < rows; r++) {
seatCounter = 0;
for (int c = 0; c < columns; c++) {
if (matrix[r][c] == 1) {
seatCounter = 0;
continue;
}
if (matrix[r][c] == 0) {
seatCounter++;
if (seatCounter == tickets) {
return r + 1;
}
}
}
}
return 0;
}
Here are the 4 tips you need:
Don't compare matrix[r][c] == matrix[r][c + 1]. Plainly compare to 0:
matrix[r][c] == 0. To avoid ArrayIndexOutOfBoundsException
As DarkSigma already pointed, start your loops iterator from 0, not 1: for (int r = 0; r < rows...
Re-init your seatCounter to 0 for each row.
And! When you print out System.out.println(rowWithAvailableSeats), remember that row counting starts from 0.
Hope this helps
on main() method, you set matrix from index 0 to rows-1, and from index 0 to columns-1. But on findRowWithAvailableSeat(), you start from index 1. So index 0 will never be accessed.
} if (matrix[r][c] == matrix[r][c + 1]) { this line will try to access index c+1, will result index out of bound exception. either you need to check whether or not c+1 is less than column size or compare matrix[r][c] with 0 (matrix[r][c] == 0).
if you looking for neighboring seats, then you need to reset the seatCounter when you visit the sold seat (matrix[r][c] == 1)
you also need to reset seatCounter for each row.
I would put each row in a string and all rows in a string array a[m], then do a[i].contains(k) on each row:
"1001101110100010110010".contains("000")
Your for loops start at 1 instead of 0
for (int r = 1; r <= rows; r++) {
for (int c = 1; c <= columns; c++) {
if (matrix[r][c] == 1) {
The first index of the matrix array is being skipped. So you're not checking the first row and the first seat of each row.
Also, seatCounter is not being reset for each row. It currently retains any seats counted from previous rows.
I'm also not sure what this is for
if (matrix[r][c] == matrix[r][c + 1])
I have a.txt file with 400 lines, I need that every 100th line in the sequence it breaks into a new column, so I'd have 4 columns of 100 in a sequence.
The sequence i want is something like: 1->101->201->301 next line: 2->102->202-> etc...
Instead im getting 1->2->3->4 next line: 5->6->7->8
The y represents another sequence that I'm working at the same time, where I want to space at every 6 lines read.
Here's my code so far:
int x = 0;
int y = 0;
int z = 0;
int xfinal = 100;
int yfinal = 6;
int zfinal = 4;
int fim= (xfinal*zfinal)+1;
PrintWriter output = new PrintWriter("C:\\path\\file.txt");
try {
for (x = 0; x < xfinal; x++){
for (y = 0; y < yfinal; y++){
for (z = 0; z < zfinal; z++) {
int pos = (zfinal * yfinal) * x + (zfinal * y) + z;
if (pos >= fim) {
output.print("\t");
continue;
}
output.print(lines.get(pos) + "\t");
}
output.print("\r\n");
}
output.print("\r\n");
}
} catch(Exception e) {
e.printStackTrace();
}
I've been going around this for quite a while and can't understand how to get the order right since I'm new to java.
you will need something like this (assume lines is the array with all a.txt lines):
//read file a.txt into the array lines
String lines[] = raedFileIntoArray("a.txt");
int numberOfLines = lines.length;
int numberOfCols = 4;
int maxNumOfLines = numberOfLines / numberOfCols;
for (int row = 0; row < maxNumOfLines; ++row) {
for (int col = 0; col < numberOfCols; ++col) {
System.out.print(lines[maxNumOfLines * col + row]);
if (col + 1 < numberOfCols)
System.out.print("\t");
}
System.out.print("\n");
}
As far as i understand you problem try to use if statment like this:
for (int x=0; x<xfinal; x++){
if(x%100==0){
output.print("\n");
}
}
This way every 100 x of loop will make new line,
You can do similar with tab every 6 lines.
I created a program which asks the User to specify the width, height and characters for a grid. However, when it prints the grid, it is all on one line and not 2D.
public static void main(String[] args) {
System.out.println("A B C - create a new grid with Width A, Height B and Character C to fill grid);
Scanner scan = new Scanner(System.in);
int Width = scan.nextInt();
int Height = scan.nextInt();
char C = scan.next().charAt(0);
char [][] grid = new char [Width][Height];
for (int row = 0; row < Width-1 ; row++) {
for (int col = 0; col < Height-1; col++) {
grid[row][col] = C;
System.out.print(grid[row][col]);
}
}
}
You need to print a new line '\n' character after each line. Otherwise the console will not know when a row has finished.
Also you didn't name your variables correctly. The outer loop should iterate over your rows and go from 0 to height - 1 and the inner (columns) should go from 0 to width - 1. If this is confusing, think of another common way of indexing pixels: x and y. while x denotes in which column you are, why y denotes in which row you are.
int width = scan.nextInt();
int height = scan.nextInt();
char c = scan.next().charAt(0);
char [][] grid = new char [width][height];
for (int row = 0; row < height - 1; col++) {
for (int col = 0; col < width - 1; row++) {
grid[col][row] = c;
System.out.print(grid[col][row]);
}
System.out.print("\n");
}
In addition please note that I took the liberty and named your variables with lower letters (height and width) to bring them in line with the java naming conventions.
I'm fairly new to java but, I'm making an encryption program that places each character in a grid. In this case I'll just be using "abcde" as my string. When put through the program, it's supposed to place each character in a 3x2 (height x width) grid. The program reads the grid from top to bottom then moving on to the next row and it'll be read as, "acebd." This part of the program is loading each character into char [height][width].
line length: 5, height: 3, width: 2, longColumn: 1
//longColumn -- the number of valid columns in the last row
static char[][] loadGrid(String line, int width, int height, int longColumn) {
char grid[][] = new char[height][width];
int charCount = 0;
for (int i = 0; i <= line.length()-1; i++){
if (i < line.length()-1) {
for (int c = 0; c < width; c++) {
for (int r = 0; r < height; r++) {
if (r < height - 1 || c < longColumn) {
grid[r][c] = line.charAt(charCount);
charCount += 1;
}
}
}
}
}
return grid;
}
When I run it I get this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at GridEncrypt.loadGrid(GridEncrypt.java:93)
at GridEncrypt.processInput(GridEncrypt.java:65)
at GridEncrypt.main(GridEncrypt.java:19)
To my understanding the charCount isn't going to 4, just staying at 3. I've tired messing around with it but it either just stays at 3 or goes to 5. Also, I'm thinking that it goes through the first two for loops once and then just doesn't go back to it after it runs through the 3rd loop. Which then the 3rd loop is the only one that's being looped properly. Any help is appreciated. Thanks.
I don't see the point of longColumn, and I think you wanted something like
static char[][] loadGrid(String line, int width, int height) {
char grid[][] = new char[height][width];
int charCount = 0;
for (int r = 0; r < height; r++) {
for (int c = 0; c < width; c++) {
if (charCount < line.length()) {
grid[r][c] = line.charAt(charCount);
charCount++;
}
}
}
return grid;
}
I would recommend using the debugger, and stepping through the program. Make sure to keep track of array sizes and variables (especially r and c). The error is being caused by (r,c) being outside the array. Also, a few other things.
1.charcount += 1; can be replaced with charcount++;
2. Remember that when dealing with integers, if (r < height - 1) is essentially the same as if(r <= height - 2)
3. The variables i and charcount are saying the same thing anyways, so you can combine those variables.
I'm working on a Java program that checks if a sudoku puzzle is solved or not. I have finished the horizontal and vertical number check part. But when trying to check squares, I can't do anything. Here is how my check system works.
This is what I want to make. Hope someone helps because I'm on a hard situation with square check.
int[][] SudokuBoard = new int[9][9];
// I didn't wrote the sudoku board completely hope you understood how sudoku table looks like.
public static boolean checkSquares(int[][] SquareBoard) {
int retr = false;
int loop = 0;
int[] extraboard = new int[9];
int[] truelist ={1,2,3,4,5,6,7,8,9};
for(int i = 1; i <=9 ; I++) {
//here , extraboard will have the numbers in " i " numbered sudoku square.( i is like first //,second)
Arrays.sort(extraboard);
for(int j = 0; j < 9; j++) {
if(extraboard[j] == truelist[j])
loop += 1;
}
extraboard = new int[9];
}
if(loop == 81)
retr == true;
return retr;
}
You could do
int count = 0;
for(int k = 0; k < 9; k++) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
extraboard[count++] = SquareBoard[i+3*k/3][j+k%3*3];
}
}
Arrays.sort(extraboard);
for(int j = 0; j < 9; j++) {
if(extraboard[j] == truelist[j])
loop += 1;
}
extraboard = new int[9];
count = 0;
}
The actual formula to calculate the location in the box is quite simple. As the board is split into rows and column, getting the location of the row and column needs to get offset based on the location of the box in the full area.
i here counts the index within the box of the row. As each row of boxes has a length of 3 in a 9x9 sudoku we need to increase the row number by 3 each time we get 3 boxes in. To figure out and only add 3 we can use some integer division.
For example:
i+i.length*k/i.length
This is obviously an syntax error as i doesn't have length but can consider it as the limit of i in the loop (in this case 3).
This would then get the current row in the box (the first i) and add that to the offset of boxes in the sudoki. That is for every 3 boxes k/i.length becomes 1 more, and we then multiply that with 3 to get the offset of 3.
In the column part we have a bit of an bigger issue as we need to offset it for every 3 we move left in the array and reset it when we get back to boxes on the far left.
So the forumla would become
j + (k%i.length)*j.length
This would give us the column in the box we are in, then we offset by the box location with k%i.length. The reason we use the i.length and not the j.length is that we need to calculate the offset by rows and then offset it by the length of the box column wise.
With this you can then apply to this to any size board. 2x2, 2x3, 3x2, 3x3 or bigger even.
public static boolean checkSquares(int[][] SquareBoard) {
int i=0, extraboard=0;
for (;i<9;i++,extraboard=0) {
for (int j=0;j<9;j++)
extraboard+=1<<(SquareBoard[i/3*3+j/3][i%3*3+j%3]-1);
if (extraboard!=(1<<9)-1) // 511, binary(511) = 111111111
break;
}
return i==9;
}
This is a solution i came up with. it uses 4 nested loops but the time complexity is still O(n^2). Basically i check the first 3 boxes on top, then the 3 boxes in the middle, then the last 3 boxes.
for (int l = 0; l < 9; l+= 3){
for (int i = 0; i < 9; i += 3){
HashSet<Character> set = new HashSet<>();
for (int j = l; j < l+3; j++){
for (int k = i; k < i+3; k++){
if (!set.contains(board[j][k])){
if (board[j][k] != '.')
set.add(board[j][k]);
}
else
return false;
}
}
}
}
return true;
and note that the sudoku might not be complete, and the missing numbers are replaced by ' . '