Reputation: 27
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.
Upvotes: 0
Views: 892
Reputation: 3205
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 ;)
Upvotes: 1
Reputation: 30285
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++;
}
}
Upvotes: 1
Reputation: 836
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++;
}
Upvotes: 0