Int variables NOT being updated in a recurring input? - java

Link to specific problem: https://hyperskill.org/projects/48/stages/258/implement#comment
public class Main {
private static Scanner input = new Scanner(System.in);
public static void edit(char[][] matrix){
System.out.print("Enter the coordinates: ");
String coords = input.nextLine();
String coords2 = coords.replaceAll("\\s", "");
int coordsNum = Integer.parseInt(coords2);
int compare = coordsNum % 10;
int compare2 = coordsNum / 10;
for(int i = 0; i < coords2.length(); i++){
if(compare < 1 || compare > 3 || compare2 < 1 || compare2 > 3){
//Code
edit(matrix);
}
//Check if input are numbers
if(!Character.isDigit(coords2.charAt(i))){
//Code
edit(matrix);
}
}
}
When I the recursion occurs, and I type a new String, the variables coordsNum, compare, and compare2 are not updated from my input. They remain the same whenever my input is below 0 or above 3. I tried making the variables into one single input line but that did not work. There is nothing wrong with the logic either.
Ex) Input: 4 1 -> Recur -> 1 3 -> Print out values, prints 4,1 instead of 1,3

This code is quite strange.
So lets look at what happens:
edit#1 prints "Enter the coordinates: "
You read "4 2" as a whole line into the variable coords.
You create coords2 to "42" by removing whitespace from coords.
you create cordsnum = 42 and compare = 2 and compare2 = 4
You start a for loop of 2 iterations (edit#1for#1)
in edit#1for i = 0 you check bounds for compare and compare2 where compare2 > 3
edit#2 prints "Enter the coordinates: "
You read "2 2" as a whole line into variables coords.
You create coords2 to "22" by removing whitespace from coords.
you create cordsnum = 22 and compare = 2 and compare2 = 2
You start a for loop of 2 iterations (edit#2for)
in edit#2for i = 0 you check bounds for compare and compare2 where non matches
you check if !Character.isDigit("22".charAt(0)), which is false
in edit#2for i = 1 you check bounds AGAIN for compare and compare2 where non matches
you check if !Character.isDigit("22".charAt(1)), which is false
method returns to edit#1, here coord2 is "42", coordnum=42, compare = 2, and compare2 = 4
you check !Character.isDigit("42".charAt(0)), which is false
in edit#1for i = 1 you check AGAIN bounds for compare and compare2 where compare2 > 3
edit#3 prints "Enter the coordinates: "
...
So what I'm not sure why you check if compare2 contains numbers since if it didn't Integer.parseInt(coords2) would throw an exception and you never get to check it. Also checking compare < 1 || compare > 3 || compare2 < 1 || compare2 > 3 twice is the reason why you end up doing another round even when you inputed ok data.
What I want to to understand is that when a method returns it resumes from the callee. It does not care if it called itself since it is a different version of itself with their own variables. When it returns it returns one step and continues just as you would assume with a non recursive call. No difference there at all.
Good luck with your challenge!

Related

How would I add two int that are in the same array to each other and convert them into an int. In the Luhn Algorithm

I am trying to add two parts of an array together to go into an int value. I am using Luhn algorithm to figure out of a credit card is a valid credit card. We are only using 6 digit credit card's just to make sure no one enter's a real credit card number. The part I am confused on is when I go to split a number that is above 10 and add it together. Example if the algorithm was to give me 12 I would need to separate it into 1 and 2 and then add them together to equal 3. I believe I am splitting it currently in the code but when I go to add them together I get some number that makes no since. here is a section of the code with some notes about it.
I have printed out numbers in certain places to show myself what is going on in certain places. I have also added in some comments that say that either the number that is printed out is what is expected, and some comments for when there isn't something I expected
int[] cardNumber = new int[]{ 1,2,3,4,5,5};
int doubleVariablesum = 0;
int singleVariablesum = 0;
int totalSum = 0;
int cutOffVar = 0;
String temp2;
for (int i = cardNumber.length - 1; i >= 0;) {
int tempSum = 0;
int temp = cardNumber[i];
temp = temp * 2;
System.out.println("This is the temp at temp * 2: " + temp);
temp2 = Integer.toString(temp);
if (temp2.length() == 1) {
System.out.println("Temp2 char 0: "+ temp2.charAt(0));
// this prints out the correct number
// Example: if there number should be 4 it will print 4
tempSum = temp2.charAt(0);
System.out.println("This is tempSum == 1: " + tempSum);
// when this goes to add temp2.charAt(0) which should be 4 it prints out //something like 56
} else {
System.out.println("TEMP2 char 0 and char 1: " + temp2.charAt(0) + " " + temp2.charAt(1));
// this prints out the correct number successfully spited
tempSum = temp2.charAt(0) + temp2.charAt(1);
System.out.println("This is tempSum != 1: " + tempSum);
// but here it when I try to add them together it is giving me something
// like 97 which doesn't make since for the numbers I am giving it
}
doubleVariablesum = tempSum + doubleVariablesum;
System.out.println("This is the Double variable: " + doubleVariablesum);
System.out.println();
i = i - 2;
}
Since you are converting the number to a string to split the integer, and then trying to add them back together. You're essentially adding the two characters numerical values together which is giving you that odd number. You would need to convert it back to an integer, which you can do by using
Integer.parseInt(String.valueOf(temp2.charAt(0)))
When adding char symbols '0' and '1' their ASCII values are added - not numbers 0 and 1.
It is possible to use method Character::getNumericValue or just subtract '0' when converting digit symbol to int.
However, it is also possible to calculate sum of digits in a 2-digit number without any conversion to String and char manipulation like this:
int sum2digits = sum / 10 + sum % 10; // sum / 10 always returns 1 if sum is a total of 2 digits
Seems like charAt() type casts into integer value, but the ascii one. Hence for the characters '0' and '1', the numbers 48 and 49 are returned resulting in a sum of 97. To fix this, you could just assign temp2 to (temp / 10) + (temp % 10). Which actually splits a two digit integer and adds their sum.
You need to be aware of the following when dealing with char and String
Assigning the result of charAt(index) to an int will assign the ASCII value and not the actual integer value. To get the actual value you need to String.valueOf(temp2.charAt(0)).
The result of concatenating chars is the sum of the ASCII values.
eg if char c = '1'; System.out.println(c + c); will print "98" not "11".
However System.out.println("" + c + c); will print "11". Note the "" will force String concatenation.

"while" loop not iterating correctly

I am supposed to print the following output by using loops:
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
6 5 4 3 2 1
7 6 5 4 3 2 1
The highest number in this pattern (in this example, 7) is determined by user input. Here is the applicable code for the pattern:
index=patternLength+1; n=1; //These values are all previously intitialized
while (index!=1) {
index--;
printSpaces((index*2)-2); //A static method that prints a certain number of spaces
while(n!=1) {
n--;
System.out.print(n + " ");
}
System.out.print("\n");
n=patternLength+1-index;
}
And here is the incorrect output for the user input "7":
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
There are two blank lines preceding the incorrect output; these lines have the correct number of spaces necessary for the complete/correct pattern, but for some reason, the actual numbers start printing too "late" in the loop. In other words, the spaces that appear before the "1, 2 1" in the correct example are in the incorrect output. It's some of the numbers that are missing and make the incorrect example incorrect.
OK, I got it.
index=patternLength+1; n=1;int nSetter=1;
//Loop C
System.out.println("Pattern C:");
while (index!=1) {
index--;
printSpaces((index*2)-2);
while(n!=0) {
System.out.print(n + " ");
n--;
}
System.out.print("\n");
nSetter++;
n = nSetter;
}
My problem was that my "n" needed to go both up and down, so the extra variable "nSetter" seems to have solved that, although this may be a round-about solution. Whatever. Thanks to #Andreas for pointing me in the correct direction and #JohnKugelman for the helpful edit.
Please try this code your second while loop is not correct.
int index = patternLength + 1;
int n = 2; //These values are all previously intitialized
int i = 1;
while (index != 1) {
index--;
printSpaces((index * 2) - 2); //A static method that prints a certain number of spaces
while (n != 1) {
n--;
System.out.print(n + " ");
}
System.out.print("\n");
i++;
n = i+1;
}

Why does this while loop run after the condition is met?

When I do a regular while loop like this
int x = 0;
while (x < 2) {
System.out.println(x);
x = x + 1;
}
it prints
0
1
but this second while loop runs one more time after the condition is met.
class Hobbits {
String name;
public static void main(String [] args) {
Hobbits [] which = new Hobbits[3];
int number = -1;
while (number < 2) {
number = number + 1;
which[number] = new Hobbits();
which[number].name = "bilbo";
if (number == 1) {
which[number].name = "frodo";
}
if (number == 2) {
which[number].name = "sam";
}
System.out.print(which[number].name + " is a ");
System.out.println("good Hobbit name");
}
}
}
so the result is
bilbo is a good Hobbit name
frodo is a good Hobbit name
sam is a good Hobbit name
shouldn't it stop printing at "frodo is a good Hobbit name"
I set the condition for x < 2 so how does "sam" print if the while loop was supposed to stop at x == 1?
Edit: ohhh I get it now lol I was thinking like the increment was at the end of the code and the start was 0
Here's your test case more closely matching your code:
class Test {
public static void main(String[] args) {
int x = -1;
while (x < 2) {
x = x + 1;
System.out.println(x);
}
}
}
It does indeed print:
$ java Test
0
1
2
Your loop is not designed to stop when number is 2, it's designed to stop before the next iteration if the number is 2. Since you increment number early on in the loop, it will continue with that value until it's time to choose whether to iterate again.
Before the first iteration, number = -1 which is <2 so it should iterate.
Before the second iteration, number = 0, which is <2 so iterate.
Before the third iteration, number = 1, which is <2 so iterate.
Before the fourh iteration, number = 2, which is NOT <2 so stop.
You therefore get 3 iterations.
Your original test case had the right idea -- it's better to increment as the last step in the loop. That way, you start at 0 instead of -1, and you stop the loop based on the new value rather than the previous value.
I will try to trace through it for you.
First case this is what happens.
x = 0
is 0 < 2? yes
print 0
0 <- 0 + 1 // here it becomes 1
is 1 < 2? yes
print 1
1 <- 1 + 1 // here it becomes 2
is 2 < 2? no
exit program
second loop works a bit more like this
number = -1
is number < 2? yes
number <- -1 + 1 // here it becomes 0
make hobbit "bilbo" at index 0
0 does not equal either 1 or 2
print hobbit at index 0 who is "bilbo"
is 0 < 2? yes
0 <- 0 + 1 // here it becomes 1
number equals 1 so make "frodo" at index 1
print hobbit at index 1 who is "frodo"
is 1 < 2? yes
1 <- 1 + 1 // becomes 2
number equals 2 so make "sam" at index 2
print hobbit at index 2 who is "sam"
is 2 < 2? no
end program
There's nothing wrong in that behaviour. You set number = -1 and then you do a loop that will iterate while number < 2. So, -1, 0 and 1. Three iterations. What's the problem? Let's do a simple trace:
number = -1
(-1 < 2)? Yes. Execute code inside while.
number = number + 1 (0)
(0 < 2)? Yes. Execute code inside while.
number = number + 1 (1)
(1 < 2)? Yes. Execute code inside while.
number = number + 1 (2)
(2 < 2)? No. Continue with the next instruction after the while block.
you can solve this easily with replace
int number = -1;
to
int number = 0;
Because! -1 + 1 = 0;
Because you have 3 iterations that are true:
-1 < 2 == true
0 < 2 == true
1 < 2 == true
2 < 2 == false
Cheers

Checking if a list of numbers are divisible by the two inputs?

I'm writing a program where you input two divisors and a list of numbers you want to check are divisible by the two numbers you inputed.
Here's an example of how the output should look like:
Please input a command: A
A [Create a new divisible test]
[Type two divisors]: 2 6
[Input a list of numbers in one single line]: 2 4 6 9 15 18 19 25 30
Please input a command: D
D [Display the information]
( 2 4 6 9 15 18 19 25 30 ) are numbers to check
( 2 4 6 18 30 ): are divisible by 2
( 6 18 30 ): are divisible by 6
( 6 18 30 ): are divisible by both 2 and 6
My problem is it won't check which number is divisible by the two divisors, instead it prints out
( 2 4 6 9 15 18 19 25 30 ) are numbers to check
( 2 4 6 9 15 18 19 25 30 ): are divisible by 2
( 2 4 6 9 15 18 19 25 30 ): are divisible by 6
( 2 4 6 9 15 18 19 25 30 ): are divisible by both 2 and 6.
here's my code:
class Divisible {
private int divisor1;
private int divisor2;
public String numbers;
public Divisible() {
divisor1 = (Integer) null;
divisor2 = (Integer) null;
numbers = " ";
}
public Divisible(int div1, int div2, String num) {
this.divisor1 = div1;
this.divisor2 = div2;
this.numbers = num;
}
private boolean isDivisible1(int input) {
boolean isDivisible1 = true;
return (input % divisor1 == 0);
}
private boolean isDivisible2(int input) {
boolean isDivisible2 = true;
return (input % divisor2 == 0);
}
public String printDivisible1() {
if (this.isDivisible1(divisor1)) {
System.out.println();
System.out.println("are divisible by " + divisor1);
}
return numbers;
}
public String printDivisible2() {
if (this.isDivisible2(divisor2)) {
System.out.println(" are divisible by " + divisor2);
}
return numbers;
}
public String printDivisibleBoth() {
if (this.isDivisible1(divisor1) && this.isDivisible2(divisor2))
System.out.println(" are divisible by " + divisor1 + " and " + divisor2);
return numbers;
}
}
It looks to me like you're missing a few steps in your code!
To solve this problem we need to:
Break the string of numbers up, and convert them into integers, and enter them into a list or array.
Iterate over this list when printing, applying your isDivisible() function to determine if it should go to output.
First I think maybe we could make your program a bit more modular. In particular your isDivisible(int input) functions could be changed to something like:
private boolean isDivisible(int input, int divisor) {
return (input%divisor==0);
}
this means we can use the same function for both our divisors! Like isDivisble(30, 6) and isDivisble(30, 2)
Now we need to focus on your string of numbers to check. You'll notice our new function requires an integer for the input, but we currently have a huge string containing all our numbers. We could probably try a function like:
String[] numArray = num.split(" ");
to take our String 'num' and split it up into pieces wherever there is a space (" "), and put those pieces into the elements of the 'numArray' array.
Ok, now we have our array of inputs. All that's left is to convert these elements into Integers so they can be used as inputs to our isDivisible() function. We can use the Integer.valueOf(str s) function to do this!
And that's all the tools we need to finish this problem! Put together, a rough solution would look like:
String[] numArray = num.split(" ");
for (int i = 0; i < numArray.length; i++) {
if (isDivisible(Integer.valueOf(numArray[i]), div1)) {
System.out.print(numArray[i] + " ");
}
}
System.out.println("): are divisible by " + div1);
UPDATE
No arrays!? Ok, in that case I think your teacher wants you to iterate through the input, checking if they are divisible, and if they are, concatenating some output strings.
So let's start by adding a couple of Strings that will later become our output to the top of our code:
class Divisible {
private String outputDiv1 = "( ";
private String outputDiv2 = "( ";
private String outputBoth = "( ";
Now, for each of these outputs we want to concatenate only the divisible numbers. We can do this without arrays by looping through the characters of our String num, and breaking apart the numbers whenever we find spaces like:
//Since we're checking for spaces, we should probably add one to the end of our string, so we can find the last number!
num += " ";
//We need to keep a record of the previous space!
int lastSpace = -1;
for (int i = 0; i < num.length(); i++) {
if (num.charAt(i) == ' ') {
//If the current character is a space, we know everything before it and the last space was a number
//Our logic will go here!
//Currently converts our string into an Integer and prints it out
int currentNumber = Integer.parseInt(num.substring(lastSpace, i));
System.out.println(currentNumber);
//Update where the last space we found was
//The '+ 1' is so we skip the spaces!
lastSpace = i + 1;
}
}
Ok, no we are iterating through our string and breaking them apart without using any arrays! All that's left to do is apply the tool we made earlier isDivisible().
Something like:
if (isDivisible(currentNum, div1)) {
outputDiv1 += currentNum;
}
Can be put into //Our logic goes here section to determine whether a number should be added to our output list or not!
Finally, we print off our finished lists:
System.out.println(outputDiv1 + " ): are divisble by " + div1);

Minesweeper - revealing all empty tiles instead of only some

NOTE: I apologize for the text wall, but I'm stuck getting my own code to work. I've dug through the other similar questions, but I'm not seeing why I can't get this code to search through everything. I WILL accept semi-cryptic answers that at least point me in the right direction in thanks.
To practice java, and answer a running question I have about minesweeper, I decided to try to build a minesweeper bot to find out exactly what the best possible winning percentage is for a given game start. I'm still working on getting the right behavior in the game portion of the code though, specifically where I have the game revealing squares that don't have adjacent mines. I end up with 0's on the edge of the revealed space, instead of my code searching the tiles around it, like below:
Printing Field:
-
-
-
-
-
-
-
-
-
- 1 1 2 1
- 0 0 0 0 0 1
- 1 0 0 0 1 2 3
- 1 0 0 0 0 0 0 0
- 2 1 0 0 0 0 0
- 1 0 0 0 0 0
- 1 0 0 0 0 0
I am tracking the actual field in a 2 dimensional Character array, and then tracking the revealed spaces in a same-sized Boolean array. I am including the method below that I am running once another method has found a '0', which marks a space without a bomb. I have another method which handles printing the revealed parts out to the current field, and can share that if anyone is curious.
private void checkAround(int x, int y)
{
//this pattern is used to parse out the comma to get the coordinates.
String regex = "[,]";
Pattern pat = Pattern.compile(regex);
ArrayList<String> to_check = new ArrayList<String>(); //the list of coordinates to check.
to_check.add("" + x + "," + y);
revealed_field[x][y] = true; //marking the coordinates as revealed.
do //iterates through the to_check list until nothing is in it.
{
//these next 2 sections handle pulling the next item from to_check
String temp = to_check.get(0);
to_check.remove(0);
String[] xy = pat.split(temp);
int a = Integer.parseInt(xy[0]); //local declaration of x
int b = Integer.parseInt(xy[1]); //local declaration of y
//if either a or b are outside the bounds of the respective axis, we skip the coordinate and move on.
if (b > height-1 || b < 0) continue;
if (a > width-1 || a < 0) continue;
if (bomb_field[b][a] == '0') //if this is not adjacent to a bomb
{
if (a > 0 && revealed_field[b][a-1] == false) //adds the square above to to_check
{
to_check.add("" + (b) + "," + (a-1));
revealed_field[b][a-1] = true;
}
if (b > 0 && revealed_field[b-1][a] == false) //adds the square left to to_check
{
to_check.add("" + (b-1) + "," + (a));
revealed_field[b-1][a] = true;
}
if (b < height-1 && revealed_field[b+1][a] == false) //adds the square right to to_check
{
to_check.add("" + (b+1) + "," + (a));
revealed_field[b+1][a] = true;
}
if (a < width-1 && revealed_field[b][a+1] == false) //adds the square below to to_check
{
to_check.add("" + (b) + "," + (a+1));
revealed_field[b][a+1] = true;
}
}
}
while (to_check.size() > 0); //ends once we have nothing to check.
}
You are storing b first in the list, then a, in the entries in the list. But you are interpreting the entries as if they contain a first, then b.
For example, if the start point is x=4, y=10:
You add "4,10" to the list.
You remove "4,10" from the list.
You check the cell at x=4, y=10.
You add "11,4", "9,4", "10,5" and "10,3" to the list - instead of "4,11", "4,9", "5,10" and "3,10".

Categories

Resources