Need to fix for loop - java

I'm taking online classes, which makes it harder to get help, which is why I'm here. This week's lecture is on nested-loops. They are confusing the heck out of me. I am currently stuck on this problem.
Given numRows and numColumns, print a list of all seats in a theater. Rows are numbered, columns lettered, as in 1A or 3E. Print a space after each seat, including after the last. Use separate print statements to print the row and column. Ex: numRows = 2 and numColumns = 3 prints:
1A 1B 1C 2A 2B 2C
>
I have tried many possible solutions which have yield many wrong results. This is my current solution
int numRows;
int numColumns;
int currentRow;
int currentColumn;
char currentColumnLetter;
numRows = scnr.nextInt();
numColumns = scnr.nextInt();
currentColumnLetter = 'A';
for (currentRow = 1; currentRow <= numRows; currentRow++)
{
for (currentColumn = 1; currentColumn < numColumns; currentColumn++)
{
System.out.print(currentRow);
System.out.print(currentColumnLetter + " ");
}
if( currentColumn == numColumns)
{
currentColumnLetter++;
}
}
The code yields this result
1A 1A 2B 2B
The desired result is
1A 1B 2A 2B
I've been going at it for two days and its making me seriously frustrated. Thanks in advance for any help.

You're pretty close.
However, you're not handling the column name correctly. As each row starts, you need to go back to A, and increment by one with each column:
for (currentRow = 1; currentRow <= numRows; currentRow++) {
currentColumnLetter = 'A'; //Starting a new row, reset the column to `A`
for (currentColumn = 1; currentColumn < numColumns; currentColumn++){
System.out.print(currentRow);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++;
}
}
It's also pretty weird to be using 1-based indexing. Indexing in Java (as well as many other languages) should be started at 0. Your column loop doesn't perform enough iterations as a result - if you set numColumns to 2, you'll only print a single column.
It would be more idiomatic to write the loops like this:
for (currentRow = 0; currentRow < numRows; currentRow++) {
currentColumnLetter = 'A';
for (currentColumn = 0; currentColumn < numColumns; currentColumn++) {
System.out.print(currentRow + 1);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++;
}
}

Yo, the thing is deeper than one might think. I always found these loop over character examples nasty, i got it at my last job interview. So here we go:
If the exercise would be this way: rows got from 1..n, columns for 1..n, output should be "1/1, 1/2...3/1, 3/2...", it would be straight forward, wouldn't it?
public void seatnumbersNumbersOnly() {
int numRows = 3;
int numColumns = 3;
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (int currentColumn = 1; currentColumn < numColumns; currentColumn++) {
System.out.print(currentColumn + "/" + currentRow + " ");
}
}
}
But the task is different, they want letters for the columns. Let's brute force it on the same basis.
public void seatnumbersNumbersMappedAgain() {
String[] seatLetters = new String []{"A", "B", "C"}; // so many letters as there are columns. Note: array index is 0-based
int numRows = 3;
int numColumns = 3;
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (int currentColumn = 1; currentColumn < numColumns; currentColumn++) {
// seatLetters[i] is a string "s", not a char 'c', so everything's fine
System.out.print(seatLetters[currentColumn - 1] + currentRow + " "); // -1: seatLetters indexing is zero based
}
}
}
But then: in Java char and byte are interchangeable as long as you're in the ascii-range, you can assign a char literal to a byte and the other way round.
#Test
public void charByteEquivalence() {
// check out http://www.asciitable.com/
char ca = 'A';
byte ba = 0x41;
assertEquals(ca, ba);
ca = 0x41;
ba = 'A';
assertEquals(ca, ba);
}
This means, you also can use the char variable directly for looping. But watch out, building the output string becomes messy, since you have to watch what gets "+"ed with what. You want String/char values for columns and numbers for rows. A "string" + char/byte/int ... becomes a string. char + int becomes and int? a byte? a char? Just certainly not a String. Disclosure: I trial-and-errored the string concatenation, and it becomes an int. Some examples for implicit type conversions are here, the official reference is here.
public void seatnumbersChar() {
int numRows = 3;
int numColumns = 3;
char firstColumnLetter = 'A';
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (char currentColumn = firstColumnLetter; currentColumn < firstColumnLetter + numColumns; currentColumn++) {
// at this point you have to watch out currentColumn + currentRow + " " will get evaluated left to right
// currentRow is an int
// currentColumn becomes an int when "+"ed with currentRow
// so currentRow + currentColumn would add two numbers instead of concatenating 2 strings, therefore
// an explicit conversion to string is needed for one of the arguments
System.out.print(currentColumn + String.valueOf(currentRow) + " ");
}
}
}
The same example going the byte route, similar mess with string concatenation, but not quite the same.
public void seatnumbersByte() {
int numRows = 3;
int numColumns = 3;
byte firstColumnLetter = 'A';
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (byte currentColumn = firstColumnLetter; currentColumn < firstColumnLetter + numColumns; currentColumn++) {
// same case other trick: (currentRow + " ") forces the result to be a string due to the + " "
// currentColumn here is declared as byte, when concatenated to a string the numeric representation would be taken (wtf...?)
// therefore a cast to char is needed "(char) currentColumn"
// what's left now ? (currentRow + " ") is a string
// "(char) currentColumn" is a char
// a char "+" a string is a string
System.out.print((char) currentColumn + (currentRow + " "));
}
}
}
Hope I got my revenge on that last interview. Have gotten the job anyway ;)

You need to increment the currentColumnLetter inside the inner loop. Remember for each row, you need to traverse each column. That's the reason you are nesting loops, right?
Try this:
for (currentRow = 1; currentRow <= numRows; currentRow++) {
currentColumnLetter = 'A';
for (currentColumn = 1; currentColumn <= numColumns; currentColumn++) {
System.out.print(currentRow);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++
}
}
You do not need this condition in the outer loop:
if( currentColumn == numColumns)
{
currentColumnLetter++;
}

Related

How to print the right number of asterix in columns and rows?

I want to print asterix which is equals the number of rows - (they should begin from the right side). It should begin with 9 spaces and 1 * at the first line, then 2 * and 8 spaces at the second line and so on until the tenth row which should have 10 * and 0 spaces like the image below:
I can print the right number of spaces at each line and 1 * at the right position. For example it prints 9 spaces and 1 * at the first line. But then at the second line it prints 8 spaces and 1 * at the ninth position instead of two?? I can't see what I have missed in my code:
for (int row = 1; row <= 10; row++) {
for (int col = 10; col > row; col--) {
System.out.print(" ");
if (col <= row) {
System.out.print("*");
}
}
System.out.println("*");
}
There are several solutions:
1) Either you create two inner loops for each row: one to write the spaces and another to write the stars
final int rows = 10;
for(int row = 1; row <= rows; row++) {
for(int i = 0; i < (rows - row); i++) {
System.out.print(" ");
}
for(int i = 0; i < (row); i++) {
System.out.print("*");
}
System.out.println();
}
2) Or you create one inner loops for each row and check the index to consider if you have to print a star or a blank.
final int rows = 10;
for(int row = 1; row <= rows; row++) {
for(int col = 1; col <= rows; col++) {
System.out.print((col <=(rows - row))? " " : "*");
}
System.out.println();
}
3) Or you can use string manipulation with subString (this is ugly but why not):
final int rows = 10;
final String stars = "************************";
final String blanks = " ";
for(int row = 1; row <= rows; row++) {
System.out.print(blanks.substring(0, rows - row));
System.out.println(stars.substring(0, row));
}
This might also be helpful:
int n = 10;
int k = 2 * n - 2; // number of spaces
// outer loop to handle number of rows
for (int i = 1; i <= n; i++) {
// inner loop to handle number spaces
for (int j = 1; j <= k; j++) {
System.out.print(" "); // printing spaces
}
k = k - 2; // decrementing k after each loop
// inner loop to handle number of columns
for (int j = 1; j <= i; j++) {
System.out.print("* "); // printing stars
}
// ending line after each row
System.out.println();
}

How do I remove empty spaces from a (5x5) 2d array in java, thus shifting values in the array?

I have a 5x5 array and I am trying to 1) remove characters based on characters entered by user's String (accomplished) and 2) shift the array values to the right, thus opening up array space at the front for the user input String (not accomplished).
Right now, if I type in "Jake" the user input is:
bcd
fgh
lmnop
qrstu
vwxyz
(this is because 'j' 'a' 'k' and 'e' have been removed .. please ignore the absence of 'i' because the assignment uses 'i' and 'j' as the same character in order to squeeze into a 5x5 array)
I want 'b' to be at the end of the first row (and at grid[0][4]) so that I can fit "Jake" into the beginning. Please let me know how to modify my code to make this work, thus "trimming" the graph down and to the right, if you will. Any help is appreciated!!
`
grid = new char[5][5];
char ch = 'a';
for (row = 0; row < 5;row++)
{
for (col = 0; col < 5; col++)
{
if(ch=='i') // if we are at i
{
grid[row][col] = ch; // add i to grid
ch+=2; // increment ch twice (k)
}
else // if we are not dealing with i/j
{
grid[row][col] = ch; // add the char
ch++;
}
}
}
for(row = 0; row < 5; row++)
{
for(col = 0; col < 5; col++)
{
if(key.indexOf(grid[row][col]) >= 0 || (key.indexOf('j') >= 0 && grid[row][col] == 'i'))
{
if(grid[row][col] == 'i' && key.indexOf('j') >= 0)
{
grid[row][col] = '\0';
}
else
{
grid[row][col] = '\0';
}
}
}
`
It is much easier if you represent the matrix as a String. Then you can use .replaceAll to remove the chars in the key:
public static void main(String[] args) {
String key = "Jake";
// Build string
String str = "";
char ch = 'a';
for (int c = 0; c < 25; c++) {
str += ch;
ch++;
if (ch == 'i') {
ch++;
}
}
System.out.println(str);
// Remove chars from key
String modifiedKey = key.toLowerCase().replace('i', 'j');
for (int i = 0; i < key.length(); i++) {
str = str.replaceAll("" + modifiedKey.charAt(i), "");
}
System.out.println(str);
// Add key in the beginning
str = key.toLowerCase() + str;
System.out.println(str);
// Print out
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 5; col++) {
System.out.print(str.charAt(row * 5 + col));
}
System.out.println();
}
}
To achieve that, you can traverse the matrix from the last element i.e. # [5][5]
If you find empty character, push the first non-empty character you find forward to fill the gap.
For example, start at z
bcd
fgh
lmnop
qrstu
vwxyz
You will find first non-empty at [2][5] , so you push h to [2][5]. You get empty at [2][4] again, so you push g to [2][4]. Keep doing this till you reach [1][1].
(assume indexing starts from [1][1])
Hope that helps.
First, I recommend to take the line grid[row][col] = ch; out of the if/else block, as it appears twice:
grid = new char[5][5];
char ch = 'a';
for (row = 0; row < 5;row++)
{
for (col = 0; col < 5; col++)
{
grid[row][col] = ch; // add i to grid
if(ch=='i') // if we are at i
{
ch+=2; // increment ch twice (k)
}
else // if we are not dealing with i/j
{
ch++;
}
}
}
Next, have a method to right shift characters in a table:
private char[][] rightShift(char[][] table) {
int rows = table.length;
int columns = table[0].length;
char[][] result = new char[rows][columns];
int outputIndex = rows*columns - 1;
for (int inputIndex = rows*columns - 1; inputIndex <= 0; inputIndex--) {
int inputRow = inputIndex / rows;
int inputColumn = inputIndex % columns;
int outputRow = outputIndex / rows;
int outputColumn = outputIndex % columns;
if (table[inputRow][inputColumn] != ' ') {
result[outputRow][outputColumn] = table[inputRow][inputColumn];
outputIndex--;
}
}
for (int i = 0 ; i < outputIndex - inputIndex; i++) {
int outputRow = i / rows;
int outputColumn = i % columns;
result[outputRow][outputColumn] = ' ';
}
return result;
}

Finding the sum of columns in a Two Dimensional Array with rows of different lengths

So i'm having a bit of trouble with my code in returning the sum of the columns in a two dimensional array with rows of different lengths. For example a 2X2 array works perfectly to calculate the sum of the columns. But if I were to have for example a 2X3 array it gives me an out of bounds error. I want it to work for any numbers given by the user for rows and columns not just a fixed number that I said as an example. Can somebody help me resolve this issue? much thanks!
here is my code:
public static void columnSum(int[][]anArray) {
int totalcol = 0;
for(int col =0; col < anArray.length; col++){
totalcol = 0;
for(int row = 0; row < anArray[col].length; row++) {
totalcol += anArray[row][col];
}
System.out.println("Sum of column " + col + " = " + totalcol);
}
}
Your indices are flipped. Your for loops are written for column-major ordering, but your totalizer is written for row-major order. You need to reverse one or the other.
You have a problem in the for loop
for(int row = 0; row < anArray[col].length; row++) {
totalcol += anArray[row][col];
}
If the array is 2X3 then in this for loop when you are using the col = 0 Then anArray[col].length returns value 3. So your row variable can have values 0 - 2 in the for loop. So when the value of row is 2 and the value of column is 0 (as stated earlier), anArray[row][col] will throw an ArrayOutOfBoundException as anArray[2][0] does not exists.
So try out this instead:
for(int row = 0; row < anArray.length; row++) {
totalcol += anArray[row][col];
}
I think this will work.
The question does not specify the order of the array elements. There are two possiblities:
anArray[i][j] represents the element at row i and column j (row-major)
anArray[i][j] represents the element at column i and row j (column-major)
The easier task to solve is finding column sums in a column-major array, or---completely equivalently---row sums in a row-major array. The proposed solution in the question only needs to replace totalcol += anArray[row][col] with totalcol += anArray[col][row] and would already work for this case.
It is a bit more difficult to compute column sums in a row-major array, or---again equivalently---row sums in a column-major array. The rest of this answer shows how to compute column sums for a row-major array. In this case, anArray.length is the number of rows, and anArray[i].length is the number of columns in row i.
In the more usual case where all your rows have the same number of columns, you could do this:
int numrows = anArray.length;
int numcols = (numrows > 0) ? anArray[0].length : 0; // Guard against 0x0 array
for(int col = 0; col < numcols; col++) {
int totalcol = 0;
for(int row = 0; row < numrows; row++) {
totalcol += anArray[row][col];
}
System.out.println("Sum of column " + col + " = " + totalcol);
}
If your rows may each have a different number of columns (as suggested by the question title), you need to:
Determine when there are no more columns to sum over.
When computing the sum of column col, make sure to skip rows that are too short
One way would be:
int numrows = anArray.length;
for(int col = 0; /* not known a priori*/; col++) {
int totalcol = 0;
boolean emptySum = true; // At first, assume no rows are long enough
for(int row = 0; row < numrows; row++) {
if(anArray[row].length <= col ) continue; // Skip short row
emptySum = false; // Mark assumption as wrong
totalcol += anArray[row][col];
}
// Exit the loop if we did not sum anything, i.e. no row had a column with index col
if(emptySum) break;
System.out.println("Sum of column " + col + " = " + totalcol);
}
Instead of using the awkward emptySum flag to quit the loop, you could determine the maximal column length in a preliminary pass:
int numrows = anArray.length;
int maxnumcols = (numrows > 0) ? anArray[0].length : 0; // Guard against 0x0 array
for(int row = 1; row < numrows; row++) {
maxnumcols = Math.max(maxnumcols, anArray[row].length);
}
for(int col = 0; col < maxnumcols; col++) {
int totalcol = 0;
for(int row = 0; row < numrows; row++) {
if(anArray[row].length <= col) continue; // Skip short row
totalcol += anArray[row][col];
}
System.out.println("Sum of column " + col + " = " + totalcol);
}
Finally, if you are allowed to store the sums (instead of immediately outputting them), this would be an even cleaner solution (note the row-major order of iteration, which fits nicely to the row-major order of the array itself):
int numrows = anArray.length;
int maxnumcols = (numrows > 0) ? anArray[0].length : 0; // Guard against 0x0 array
for(int row = 1; row < numrows; row++) {
maxnumcols = Math.max(maxnumcols, anArray[row].length);
}
int[] colsums = new int[maxnumcols]; // In Java, all elements are initialized to zero
for(int row = 0; row < numrows; row++) {
for(int col = 0; col < anArray[row].length; col++) {
colsums[col] += anArray[row][col];
}
}
for(int col = 0; col < colsums.length; col++) {
System.out.println("Sum of column " + col + " = " + colsums[col]);
}

Nested loops: Print seats in java

Given numRows and numCols, print a list of all seats in a theater. Rows are numbered, columns lettered, as in 1A or 3E. Print a space after each seat, including after the last. Use separate print statements to print the row and column. Ex: numRows = 2 and numCols = 3 prints:
1A 1B 1C 2A 2B 2C
My code's like:
public static void main(String[] args) {
int numRows = 2;
int numCols = 3;
int rows = 0;
int cols = 1;
char col;
while (rows < numRows) {
rows++;
col='A';
while (cols <= numCols) {
System.out.print("" + rows + col + " ");
col++;
cols++;
}
}
System.out.println(" ");
return;
}
}
And my output's like:
1A 1B 1C
I tried to make it like:
1A 1B 1C 2A 2B 2C
Why my loop stop at 1?
Here's what I came up with for this particular ZyBooks challenge (I used my own iterables instead of their pre-defined ones out of habit):
import java.util.Scanner;
public class NestedLoops {
public static void main (String [] args) {
Scanner scnr = new Scanner(System.in);
int numRows;
int numColumns;
int currentRow;
int currentColumn;
char currentColumnLetter;
numRows = scnr.nextInt();
numColumns = scnr.nextInt();
for (int i = 1; i <= numRows; i++) {
currentColumnLetter = 'A';
for (int x = 1; x <= numColumns; x++) {
System.out.print(i);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++;
}
}
System.out.println("");
}
}
add a line cols = 1; just after rows++;
You didn't reset the value of cols in the outer loop. So the second time through the outer loop, the inner loop never gets run at all. Also consider using a for loop:
for (int rows = 0; rows < numRows; ++rows) {
// ...
for (int cols = 0; cols < numCols; ++cols) {
// ...
}
}
On the first iteration, when it goes over the inner while, you update the value of "cols".
So when this while is done, cols = 3.
Then on the second iteration, you still have cols=3 which is > numCols so it doesn't execute the while loop.
As said Parasu just add "cols = 1;" before the inner loop and it'll works.
This uses a for loop
public class NestedLoops {
public static void main (String [] args) {
int numRows = 2;
int numCols = 3;
int i = 0;
int j = 0;
char rows;
char columns;
rows = '1';
for (i = 0; i < numRows; ++i) {
columns = 'A';
for (j = 0; j < numCols; ++j) {
System.out.print("" + rows + columns + " ");
columns++;
}
rows++;
}
System.out.println("");
return;
}
}
public class NestedLoops_2 {
public static void main (String [] args) {
int numRows = 2;
int numCols = 5;
for (int i = 1; i <= numRows; i++){
char abc = 'A';
for (int j = 1; j <= numCols; ++j) {
System.out.print("" + i + abc + " ");
++abc;
}
}
System.out.println("");
return;
}
}
You have to just make a small change in your code. After the inner while loop but just inside the outer while loop write cols=1;... because the next time when the loop reaches the same inner while loop cols have to again start at 1 and not at some other value .
Just change the position of cols = 1;
public static void main(final String[] args){
int numRows = 2;
int numCols = 3;
int rows = 0;
while (rows < numRows) {
rows++;
int cols = 1;
char col = 'A';
while (cols <= numCols) {
System.out.print("" + rows + col + " ");
col++;
cols++;
}
}
System.out.println(" ");
}
I know this is late, but I am going through this same challenge in zybooks. My initial code is a little different and the answers above were a little off from what the IDE was testing for. So I decided to copy and paste my code in case anyone needs a little help with this challenge.
import java.util.Scanner;
public class NestedLoops {
public static void main (String [] args) {
Scanner scnr = new Scanner(System.in);
int numRows;
int numColumns;
int currentRow;
int currentColumn;
char currentColumnLetter;
numRows = scnr.nextInt(); // user input for how many rows
numColumns = scnr.nextInt(); // user input for many columns
/* Your solution goes here */
currentRow = 0; // Must be intialized to 0 or a "2" will print before "1"
while (currentRow < numRows) { // Intialized the loop
currentRow++; // increments the currentRow
currentColumnLetter = 'A'; // Sets the first column to char 'A'
currentColumn = 1; // Define to intialize inner loop
while (currentColumn <= numColumns) { // Will initial for any positive input 1 +
System.out.print(currentRow); // Asked specifically for 2 printouts
System.out.print(currentColumnLetter + " "); // 2nd printout with space at end.
currentColumnLetter++; // increments the Letter
currentColumn++; // increments the column
}
}
System.out.println("");
}
}
I hope this helps anyone needing a little help with this assignment.
import java.util.Scanner;
public class NestedLoops {
public static void main (String [] args) {
Scanner scnr = new Scanner(System.in);
int numRows;
int numColumns;
int currentRow;
int currentColumn;
char currentColumnLetter; //not needed
numRows = scnr.nextInt();
numColumns = scnr.nextInt();
String currentColumnL;
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
for(currentRow = 1; currentRow <= numRows; currentRow = currentRow + 1) {
for(currentColumn = 1; currentColumn <= numColumns; currentColumn = currentColumn + 1) {
currentColumnL = Character.toString(alphabet[currentColumn-1]);
System.out.print("" + currentRow + currentColumnL + " ");
}
}
System.out.println("");
}
}
This is my solution to 4.7.2: Nested loops: Print seats, I did not use char currentColumnLetter
This was my solution. This one was really tough!
One thing to point out, you cannot print the string and the char within the same print statement. I'm not sure why but it will not run if you do.
import java.util.Scanner;
public class NestedLoops {
public static void main (String [] args) {
Scanner scnr = new Scanner(System.in);
int numRows;
int numColumns;
int currentRow;
int currentColumn;
char currentColumnLetter;
numRows = scnr.nextInt();
numColumns = scnr.nextInt();
for(currentRow = 1; currentRow <= numRows; currentRow++){
// Set the starting column letter
currentColumnLetter = 'A';
for(currentColumn = 0; currentColumn < numColumns; currentColumn++){
System.out.print(currentRow);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++;
}
}
System.out.println("");
}
}

Why in this JUnit test it shows wrong number?

So here is my solution code:
public int count_two_char(String s, char c, char d){
int count = 0;
int count1 = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == c) {
count = count + 1;
}
for (int i1 = 0; i1 < s.length(); i1++) {
if (s.charAt(i1) == d) {
count1 = count1 + 1;
}
}
}
return count + count1;
}
And here is my test code:
#Test
public void tests3() {
code.Solution s = new code.Solution();
String input = "llss";
int expected = 4;
char c ='l';
char d ='s';
int actual = s.count_two_char(input, c, d);
assertTrue("Expected was" +expected+"but the actual was" +actual , expected == actual);
}
But when I test it. It shows a error which is expected was 4 but the actual was 10. why?? I'm so confuse right now.
Because your braces aren't indented well, it appears that you have 2 separate for loops. But after lining them up better:
for(int i=0; i<s.length(); i++){
if(s.charAt(i) == c){
count = count + 1;
}
for(int i1=0; i1<s.length(); i1++){
if(s.charAt(i1) == d){
count1 = count1 + 1;
}
}
}
You can see that the second for loop is nested inside the first for loop, so your count1 will be higher than expected.
Move that last brace between the for loops and they will be unnested. That should reduce the count returned so that your test passes.
This is because you have a for loop that you do not need. Both ifs should go into the same loop, like this:
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == c) {
count = count + 1;
}
if (s.charAt(i) == d) {
count1 = count1 + 1;
}
}
As it stands, the number of d characters is multiplied by the length of the string, producing 2+4*2=10.
You can make your code more idiomatic to the language if you replace count = count+1 with the equivalent count++. You could also drop count1 altogether, because you add the two counts at the end anyway.

Categories

Resources