Code seems to be stuck in a potential loop - java

I am writing an answer to a CCC question in java, but every time I input something it just takes infinite inputs. Can anyone help me stop this?
Your task is to write a program that verifies the validity of a well plan by verifying that the borehole will not intersect itself. A two-dimensional well plan is used to represent a vertical cross-section of the borehole, and this well plan includes some drilling that has occurred starting at (0, −1) and moving to (−1, −5). You will encode in your program the current well plan shown in the figure below:
Input Format:
The input consists of a sequence of drilling command pairs. A drilling command pair begins with one of four direction indicators (d for down, u for up, l for left, and r for right) followed by a positive length. There is an additional drilling command indicated by q (quit) followed by an integer, which indicates the program should stop the execution. You can assume that the input is such that the drill point will not:
rise above the ground, nor
be more than 200 units below ground, nor
be more than 200 units to the left of the original starting point, nor
be more than 200 units to the right of the original starting point.
Output Format:
The program should continue to monitor drilling assuming that the well shown in the figure has already been made. As we can see (−1, −5) is the starting position for your program. After each command, the program must output one line with the coordinates of the new position of the drill, and one of the two comments safe, if there has been no intersection with a previous position or DANGER if there has been an intersection with a previous borehole location. After detecting and reporting a self-intersection, your program must stop.
My code is:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<Integer> holeX = new ArrayList<>();
ArrayList<Integer> holeY = new ArrayList<>();
String direction;
boolean danger = false;
holeX.add(0);
holeX.add(0);
for (int i = 0; i < 4; i++) {
holeX.add(i);
}
holeX.add(3);
holeX.add(3);
holeX.add(4);
holeX.add(5);
holeX.add(5);
holeX.add(5);
holeX.add(6);
for (int i = -3; i > -8; i--) {
holeX.add(7);
}
for (int i = 6; i > -2; i--) {
holeX.add(i);
}
holeX.add(-1);
holeX.add(-1);
holeY.add(-1);
holeY.add(-2);
for (int i = 0; i < 4; i++) {
holeY.add(-3);
}
holeY.add(-4);
holeY.add(-5);
holeY.add(-5);
holeY.add(-5);
holeY.add(-4);
holeY.add(-3);
holeY.add(-3);
for (int i = -3; i > -8; i--) {
holeY.add(i);
}
for (int i = 6; i > -2; i--) {
holeY.add(-7);
}
holeY.add(-6);
holeY.add(-5);
do {
direction = sc.next();
int steps = sc.nextInt();
switch (direction) {
case "d":
for (int i = holeY.get(holeY.size() - 1); i > holeY.get(holeY.size() - 1) - steps; i--) {
holeY.add(i);
for (int j = 0; j < holeY.size() - 2; j++) {
if (Objects.equals(holeY.get(holeY.size() - 1), holeY.get(j)) && Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j))) {
danger = true;
}
}
}
case "u":
for (int i = holeY.get(holeY.size() - 1); i < holeY.get(holeY.size() - 1) + steps; i++) {
holeY.add(i);
for (int j = 0; j < holeY.size() - 2; j++) {
if (Objects.equals(holeY.get(holeY.size() - 1), holeY.get(j)) && Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j))) {
danger = true;
}
}
}
break;
case "l":
for (int i = holeX.get(holeX.size() - 1); i > holeX.get(holeX.size() - 1) - steps; i--) {
holeX.add(i);
for (int j = 0; j < holeX.size() - 2; j++) {
if (Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j)) && i == holeY.get(j)) {
danger = true;
}
}
}
break;
case "r":
for (int i = holeX.get(holeX.size() - 1); i < holeX.get(holeX.size() - 1) + steps; i++) {
holeX.add(i);
for (int j = 0; j < holeX.size() - 2; j++) {
if (Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j)) && i == holeY.get(j)) {
danger = true;
}
}
}
break;
default:
break;
}
if (danger == false && !"q".equals(direction)) {
System.out.println(holeX.get(holeX.size() - 1) + " " + holeY.get(holeY.size() - 1) + "safe");
System.out.print(" safe");
} else {
System.out.println(holeX.get(holeX.size() - 1) + " " + holeY.get(holeY.size() - 1) + " DANGER");
}
} while (!"q".equals(direction) && danger == false);
}
holeX and holeY are the coordinates of the drilled area.
Input:
l 2
d 2
r 1
q 0
Output:
-3 -5 safe
-3 -7 safe
-2 -7 safe

Well yes, you have an infinite loop. Let's take case "l" for example.
I used l and then 2.
for (int i = holeX.get(holeX.size() - 1); i > holeX.get(holeX.size() - 1) - steps; i--) {
holeX.add(i)...
You add something to the list and the condition gets re-evaluated, which leads to an infinite loop.
I don't know if it is what you want to do, but what helps is to extract the condition first into a variable, then the infinite loop stops.

Related

Some test cases not running but some are in terms of probability

I have a program in which it rolls five dice and assigns a hand to the rolls. i.e. nothing, a pair, two pair, three of a kind, full house, four of a kind, five of a kind. The code runs 1000000 times and gives percentage chances for each roll. Below I have attached general percentages my code should output near:
Case 1, None alike, is 0.092533
Case 2, One pair, is 0.462799
Case 3, Two pair, is 0.231789
Case 4, Three of a kind, is 0.154192
Case 5, Full house, is 0.038595
Case 6, Four of a kind, is 0.019316
Case 7, Five of a kind, is 0.000776
However my code gives the following output:
Case 1, None alike is 0.093099
Case 2, One pair is 0.384768
Case 3, Two pair is 0.076921
Case 4, Three of a kind is 0.15485
Case 5, Full House is 0.270349
Case 6, Four of a kind is 0.019281
Case 7, Five of a kind is7.33E-4
I don't understand why my programs percentages are off for one pair, two pairs, and full house. I have gone through and tested my logic but it is sound from what I have seen. Originally, my one pair was correct but my two pair was 0.0. Below is my original logic which causes the two pair to be 0 and my pair to be correct.
I, however, changed it to the current logic to get the current output. I would appreciate another set of eyes to take a look and let me know if they could catch something. Below is my code:
Change 1 :
if (hand < 6) {
int counter3 = 0;
int counter2 = 0;
for (int j = 0; j < length; j++) {
if (counts[j] == 3) {
counter3++;
}
if (counts [j] == 2) {
counter2++;
}
}
if (counter3 == 1 && counter2 == 1) {
hand = 5;
}
}
Change 2:
if (hand < 4) {
int newcounter = 0;
for (int j = 0; j < length; j++) {
if (counts[j] == 2) {
newcounter++;
}
}
if (newcounter==2) {
hand = 3;
}
if (newcounter == 1) { hand = 2; }
}
Change 3 :
Please remove if( hand < 3) part of code.
Updated my answer. In your code the counter variable (when you're trying to check "full house") was becoming 2 due to two pairs (ex : counts = 020200) not due to full house (ex: counts = 300200). Hence, it wasn't counting the two pairs in the following code where it was supposed to because hand was already becoming 5, so it didn't go inside any other if parts below although it was supposed to go inside if(hand<3). Hope it will fix the issue.
See comment in code
if (hand < 4) {
int newcounter = 0;
boolean firstp = false;
boolean secondp = false;
for (int j = 0; j < length; j++) {
firstp = false;
secondp = false;
if (counts[j] == 2) {
firstp = true; <---- THIS
}
if (counts[j] == 2) {
secondp = true; <---- AND THIS will always hit together as j never changes from the first if to second if
// break;
}
}
if (firstp && secondp) {
hand = 3; <---- firstp always equal to secondp, I would be surprised to see hand ever = 2
}
}
I modified your code. The original logic is a little bit messy. I made some slight improvement but hopefully better. Not perfect though.
import java.util.*;
public class PokerDice {
public static void main(String[] args) {
double none = 0;
double pair = 0;
double twop = 0;
double threep = 0;
double full = 0;
double fourp = 0;
double fivep = 0;
for (int i = 0; i<=1000000; i++) {
int [] rolls = new int[5];
for (int j = 0; j < 5; j++) {
rolls[j] = (int)(1 + (Math.random()*(6)));
}
int[] counts = Counts(rolls);
boolean has_two = false;
boolean has_three = false;
none++;
for (int j = 0; j < counts.length; j++) {
if (counts[j] == 4) {
fourp++;
none--;
break;
}
if (counts[j] == 5) {
fivep++;
none--;
break;
}
if (counts[j] == 3) {
has_three = true;
if (has_two) {
full++;
pair--;
break;
} else {
none--;
threep++;
}
}
if (counts[j] == 2) {
if (has_two) {
twop++;
pair--;
break;
}
else if (has_three) {
full++;
threep--;
break;
} else {
has_two = true;
pair++;
none--;
}
}
}
}
fivep/=1000000;
fourp/=1000000;
full/=1000000;
threep/=1000000;
twop/=1000000;
pair/=1000000;
none/=1000000;
System.out.println("Poker Dice Probability Calculator");
System.out.println("Running 1,000,000 trials");
System.out.println();
System.out.println("Case 1, None alike is "+none);
System.out.println("Case 2, One pair is "+pair);
System.out.println("Case 3, Two pair is "+twop);
System.out.println("Case 4, Three of a kind is "+threep);
System.out.println("Case 5, Full House is "+full);
System.out.println("Case 6, Four of a kind is "+fourp);
System.out.println("Case 7, Five of a kind is"+fivep);
}
public static int[] Counts (int [] rolled) {
int one = 0;
int two = 0;
int three = 0;
int four = 0;
int five = 0;
int six = 0;
int len = rolled.length;
int [] rolltimes = new int[6];
for (int i = 0; i<len; i++) {
if (rolled [i] == 1) {
one++;
}
else if (rolled [i] == 2) {
two++;
}
else if (rolled [i] == 3) {
three++;
}
else if (rolled [i] == 4) {
four++;
}
else if (rolled [i] == 5) {
five++;
}
else if (rolled [i] == 6) {
six++;
}
}
rolltimes[0] = one;
rolltimes[1] = two;
rolltimes[2] = three;
rolltimes[3] = four;
rolltimes[4] = five;
rolltimes[5] = six;
return rolltimes;
}
}

ArrayIndexOutOfBoundsException - (36. Valid Sudoku on Leetcode)

all.
I am working on this problem which comes from Leetcode.
Here is the link if anyone want to see the problem: https://leetcode.com/problems/valid-sudoku/
I think I almost solve this problem, but something wrong with the "java.lang.ArrayIndexOutOfBoundsException" which I used capital comment in my code to mark it out, ==> "if (brain[((int) board[x][y]) - 1])"
I checked it many times and I think the indexes should be perfectly fine within 0~8 by doing "for( int i = 0, i < 9; i++)" and I could not find the reason.
I guess this must be easy stupid question, but I kinda spend a lot of time to find it out. Can someone help me out?
BIG THANKS to whoever help!
public class Solution {
public boolean isValidSudoku(char[][] board) {
if (board.length > 9 || board[0].length > 9 || board == null) {
return false;
}
boolean[] brain;
// 9 digits are corresponding to 1 ~ 9 ==> 0 - 1, 1 - 2 ... 8 - 9
// ex: brain[2] is checking for digit "3" , so using brain[3-1] to check "3"
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
if (board[x][y] != '.') {
// THE NEXT LINE IS THE PROBLEM!!!
if (brain[((int) board[x][y]) - 1]) {
// my condition failed by using:
// brain[board[x][y] - 1]
// other's condition Partially passed by using
// (still failed for final submission:
// brain[(int) (board[x][y] - '1')]
// need to compare the difference
return false;
} else {
brain[((int) board[x][y]) - 1] = true;
}
}
}
}
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
if (board[x][y] != '.') {
if (brain[((int) board[y][x]) - 1]) {
return false;
} else {
brain[((int) board[y][x]) - 1] = true;
}
}
}
}
for (int block = 0; block < 9; block++) {
// Reset brain
brain = new boolean[9];
for (int r = block / 3 * 3; r < block / 3 * 3 + 3; r++) {
for (int c = block % 3 * 3; c < block % 3 * 3 + 3; c++) {
if (board[r][c] != '.') {
if (brain[((int) board[r][c]) - 1]) {
return false;
} else {
brain[((int) board[r][c]) - 1] = true;
}
}
}
}
}
return true;
}
}
You are trying to cast a char as int. Try to manually cast these values and you will notice that 0=48 and 9=57, which i guess should be the cause of your exception.
You might want to check if the value in there represents a number and get the numeric value of the char by using the Character#getNumericValue method.
if (Character.isDigit(board[x][y]) &&
brain[Character.getNumericValue(board[x][y])) - 1]) {
...
}

Detecting groups without recursion or stacks/queues

I was trying out this algorithm for detecting groups of like pieces on a grid. It is a simple game demo that drops pieces randomly on a 12x10 grid and after each piece drop checks the grid for any groups that are three or more adjacent pieces. I am using the following code in an attempt to do this without flood fill, recursion, or stacks/queues. It seems to almost work, but will destroy squares that are not of the same type sometimes, or leave squares that should be destroyed. So, is the logic of the algorithm wrong, or is the implementation/coding wrong?
EDIT: I think this works now. See comment
public void checkMatches(int type)
{
/*
* Step 1: Iterate through each square to see how many of the same type are adjacent to it
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].getType() == type) // EDITED IN CODE. Make sure current square is of correct type
{
if (i > 0) // Bounds checking
if (grid[i - 1][j].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
if (i < PIECES_WIDE - 1) // Bounds checking
if (grid[i + 1][j].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
if (j > 0) // Bounds checking
if (grid[i][j - 1].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
if (j < PIECES_TALL - 1) // Bounds checking
if (grid[i][j + 1].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
}
}
}
/*
* Step 2: If there are 2 or more adjacent squares with the same type then it is part of a blob and to be destroyed
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].getAdj() >= 2)
grid[i][j].setDestroy(true);
}
}
/*
* Step 3: If there is only 1 adjacent, then check to see if any adjacent squares have been marked to be destroyed (part
* of a group). If so, set these to be destroyed as well.
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].getAdj() == 1)
{
if (i > 0) // Bounds checking
if (grid[i - 1][j].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
if (i < PIECES_WIDE - 1) // Bounds checking
if (grid[i + 1][j].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
if (j > 0) // Bounds checking
if (grid[i][j - 1].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
if (j < PIECES_TALL - 1) // Bounds checking
if (grid[i][j + 1].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
}
}
}
/*
* Step 4: Iterate through grid and destroy the squares marked for destruction and reset all squares to 0 adjacent and
* destroy flag to false
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].isDestroy())
destroyPiece(grid[i][j]);
grid[i][j].setAdj(0);
grid[i][j].setDestroy(false);
}
}
}
You can find groups faster when you sort the items into a bucket. You can use a spatial index for example a kd-tree.

Small Straight - Method

I've been stuck on this method for a couple of days now. This method checks to see if the roll of 5 dice == a small straight. It works for some numbers. If I roll a
1, 2, 4, 3, 6
it will work. However, if I roll a
1, 2, 4, 3, 3
it will not work. I think it's because of the duplicate 3 in there. I need to move it to the end somehow.
A small straight is when there are four consecutive die face values, such as 1, 2, 3, 4 or 3, 4, 5, 6. It can be in any order such as 2, 3, 1, 4
int counter = 0;
int score = 0;
boolean found = false;
Arrays.sort(die);
for (int i = 0; i < die.length - 1; i++)
{
if (counter == 3)
found = true;
if (die[i + 1] == die[i] + 1)
{
counter++;
}
else if (die[i + 1] == die[i])
{
continue;
}
else
{
counter = 0;
}
}
if (found)
{
score = 30;
}
else
{
score = 0;
}
return score;
}
The duplicate 3 is not what is throwing off the algorithm. The issue is that you check for the straight during the iteration AFTER it occurs. Thus, if the last die is part of the straight, it won't be recognized.
To fix this, move
if (counter == 3) found = true;
to the END of the loop. Should work.
EDIT: So it looks like this.
for (/*...*/) {
/* Everything else */
if (counter == 3) {
found = true;
break;
}
}
EDIT: First, if a small straight is three in a row, then you want to see if the counter gets to 2, not to 3. 3 would demand a four in a row.
Edit the start of the for loop as follows:
for (int i = 0; i < die.length ; i++)
{
if (counter == 2)
found = true;
if (i == die.length - 1) break;
//method continues here
Reasoning: I imagine that when you started coding this method, it was throwing IndexOutOfBoundsExceptions when it got to the last die in the array, tried to compare it to the nonexistant sixth die and died. So, you made the loop stop one short. But if it stops one short and the small straight is finished on the very last dice, then you never got into the loop again to confirm that the counter was 3 and a small straight had occured. By editing the start of the loop this way it goes all the way to the last element, checks and then breaks.
Alternatively, do one last check after the loop ends:
for (int i = 0; i < die.length - 1; i++)
{
if (counter == 2)
found = true;
if (die[i + 1] == die[i] + 1)
{
counter++;
}
else if (die[i + 1] == die[i])
{
continue;
}
else
{
counter = 0;
}
}
found = (counter == 2); // or counter >= 2 if you want larger straights to be found too
//continue method here
This should calculate the longest sequence:
int longestSequence(int[] a) {
Arrays.sort(a);
int longest = 0;
int sequence = 0;
for (int i = 1; i < a.length; i++) {
int d = a[i] - a[i - 1];
switch (d) {
case 0:
// Ignore duplicates.
break;
case 1:
sequence += 1;
break;
default:
if (sequence > longest) {
longest = sequence;
}
break;
}
}
return Math.max(longest, sequence);
}
You could add code such as
for (int i = 0; i < (die.length-1); i++)
{
if (die [i] == die[i+1])
{
die[i+1] =1;
}
}
Arrays.sort(die);
This will set the code for example from 1,2,3,3,4 to 1,1,2,3,4 so your code should then work.

how to manage different vertices in triangle

in the inner for loop I have 0<p1,p2,p3<3 and they are integer. I want this for loop to assign value from 0 till 3 to each parameter in demoMethod.i.e., once the for loop executes it will send parameter like (1,2,3) to demomethod and for the second time it will send parameter (2,3,0) to the demoMethod. also the order of these three numbers are not important and they must be different .it means that after two times that for loop executes it doesn't send parameter like (1,2,3) and (2,3,1). thanks
public void Points(List<Point> pointList) {
int n = pointList.size();
if (n <= 2) {
System.out.println("null");
} else if (n == 3) {
drawingLine();
} else {
for(int i = 0;i<n;i++){
for(int j = 1;j<=(n-1)*(n-2)*(n-3)/6;j++){
demoMethod(p1,p2,p3);
}
}
}
}
I am not entirely sure what you are trying to do, but if I understand you correctly, you want to do something like this (?):
for(int i = 0;i<n;i++){
for(int j = 1;j<=(n-1)*(n-2)*(n-3)/6;j++){
int p1 = j % 4;
int p2 = (j + 1) % 4;
int p3 = (j + 2) % 4;
demoMethod(p1,p2,p3);
}
}

Categories

Resources