Ant on a Chess board - java

currently my program is only always giving me 4, how can I determine how many steps the ant took to cover the whole board? The ant can walk up down left right, but can't walk off the board, and then do this simulation 4 times.
public static void main(String args[]) {
int[][] grid = new int[8][8];
int count = 0;
int x = 0;
int y = 0; // arrays are 0 based
while(true)
{
int random = (int)Math.random()*4+1;
if (random == 1)
{
x--; // move left
}
else if (random == 2)
{
x++; // move right
}
else if (random == 3)
{
y--; // move down
}
else if (random == 4)
{
y++; // move up
}
if(x < 0 || y < 0 || x >= grid.length || y >= grid[x].length) break;
count++;
grid[x][y]++;
}
System.out.println("Number of Steps in this simulation: " + count); // number of moves before it fell
}
}

The problem is this expression:
int random = (int)Math.random()*4+1;
Through the explicit cast, only Math.random() ist casted to int. But since Math.random() returns a dobule < 1, it is casted to 0 and thus random is always 1 and the method always returns 0.
The problem can be fixed by casting Math.random() * 4:
int random = (int) (Math.random() * 4) + 1;
The parenthesis enforce that the value of Math.random() * 4 (which will be a value in the interval [0, 3)) will be casted to int.
Two remarks on your code:
I would recommend introducing an enum Direction with four values (one for each direction) and choose a random Direction by calling Direction.values()[(int) (Math.random() * 4)];
I would recommend to use a switch instead of the if-else-if cascade.
Ideone demo

The program will exit the while(true) loop once one of the 4 conditions is true. My suggestion is to move these conditions in your if(random == value) checks like this:
if( random == 1 )
{
x--;
if (x < 0 )
{
x++;
}
}
Now to exit your while(true) loop you need to have an extra condition. I would suggest to think about your board in terms of 0's and 1's. Everytime the ant cross a cell, you set the grid[x][y] = 1.
int stepsTaken = 0;
int cellsToCover = grid.length * grid[0].length ;
int coveredCells = 0;
while(true)
{
//your code here
if( random == 1 )
{
stepsTaken++;
x--;
if (x < 0 )
{
x++;
}
}
// the other if's with "stepsTaken" incremented too.
if ( grid[x][y] == 0 )
{
grid[x][y] = 1;
coveredCells++;
}
if (coveredCells == cellsToCover )
break;
}
But please notice the many ifs statements inside a while(true) loop. If you have to fill a board of 10 rows x 10 columns it would take too much until the board is filled. Instead I would suggest you to use some more efficient algorithms like backtracking, dynamic programming etc.
Edit : Added step counter.

Related

Draw stops working after if

I'm trying to create a maze with Union Find, but am unable to remove walls.
This is what I have got so far.
private void createMaze (int cells, Graphics g) {
s = new int[cells*cells]; //No unions yet setting all to -1
for(int i = 0; i < cells*cells; ++i){
s[i] = -1;
}
g.setColor(Color.yellow);
random = new Random();
while(breaker){
g.setColor(Color.yellow);
int innerWall = random.nextInt(4)+0;
int randomCellX = random.nextInt(cells-1)+0;
int randomCellY = random.nextInt(cells)+0;
if(randomCellX==cells&&innerWall==2||
randomCellX==0&&innerWall==0||
randomCellY==cells-1&&innerWall==3||
randomCellY==0&&innerWall==1){
continue;
}
else{
int location = randomCellX+(randomCellY*cells);
int neighbour = 0;
if(innerWall==0){
neighbour =location-1;
}
else if(innerWall==1){
neighbour =location-cells;
}
else if(innerWall==2){
neighbour =location+1;
}
else if(innerWall==3){
neighbour =location+cells;
}
int locationRoot =find(location);
int neighbourRoot =find(neighbour);
if(locationRoot==neighbourRoot){
breaker = checkIfDone(s);
}
union(location,neighbour);
drawWall(randomCellX,randomCellY,innerWall,g);
}
}
}
If I remove the
if(randomCellX==cells&&innerWall==2||
randomCellX==0&&innerWall==0||
randomCellY==cells-1&&innerWall==3||
randomCellY==0&&innerWall==1){
continue;
}
It removes the lines fine,but when it is added the walls are not removed. The method is called but doesn't do anything.
It seems some logical mistake have been done obviously. But can not spot specifically as you haven't given the explanation of the logic you have done. Only can help showing the path where the problem might be happening.
Since you can not reach the else block anyway, it is obvious that one or more of these conditions in if are always true.
(randomCellX == cells && innerWall == 2)
(randomCellX == 0 && innerWall == 0)
(randomCellY == cells - 1 && innerWall == 3)
(randomCellY == 0 && innerWall == 1)
That's why you are getting true for the if condition and continuing the loop without doing anything. Ensure the conditions are okay.
If these conditions are right, the next suspect might be these lines:
int innerWall = random.nextInt(4)+0;
int randomCellX = random.nextInt(cells-1)+0;
int randomCellY = random.nextInt(cells)+0;
Check whether these random values range are exactly what you want or not. For example: you are taking random values for randomCellX from 0 to cells-2, but for randomCellY the range is 0 to cells-1.

All digits in int are divisible by certain int

I am trying to figure out how to count all numbers between two ints(a and b), where all of the digits are divisible with another int(k) and 0 counts as divisible.Here is what I've made so far, but it is looping forever.
for (int i = a; i<=b; i++){
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
}
i = i / 10;
}
}
Also I was thinking about comparing if all of the digits were divisible by counting them and comparing with number of digits int length = (int)Math.Log10(Math.Abs(number)) + 1;
Any help would be appreciated. Thank you!
Once you get in to your while block you're never going to get out of it. The while condition is when i less than 10. You're dividing i by 10 at the end of the whole block. i will never have a chance of getting above 10.
Try this one
public class Calculator {
public static void main(String[] args) {
int a = 2;
int b = 150;
int k = 3;
int count = 0;
for (int i = a; i <= b; i++) {
boolean isDivisible = true;
int num = i;
while (num != 0) {
int digit = num % 10;
if (digit % k != 0) {
isDivisible = false;
break;
}
num /= 10;
}
if (isDivisible) {
count++;
System.out.println(i+" is one such number.");
}
}
System.out.println("Total " + count + " numbers are divisible by " + k);
}
}
Ok, so there are quite a few things going on here, so we'll take this a piece at a time.
for (int i = a; i <= b; i++){
// This line is part of the biggest problem. This will cause the
// loop to skip entirely when you start with a >= 10. I'm assuming
// this is not the case, as you are seeing an infinite loop - which
// will happen when a < 10, for reasons I'll show below.
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
// A missing line here will cause you to get incorrect
// results. You don't terminate the loop, so what you are
// actually counting is every digit that is divisible by k
// in every number between a and b.
}
// This is the other part of the biggest problem. This line
// causes the infinite loop because you are modifying the
// variable you are using as the loop counter. Mutable state is
// tricky like that.
i = i / 10;
}
}
It's possible to re-write this with minimal changes, but there are some improvements you can make that will provide a more readable result. This code is untested, but does compile, and should get you most of the way there.
// Extracting this out into a function is often a good idea.
private int countOfNumbersWithAllDigitsDivisibleByN(final int modBy, final int start, final int end) {
int count = 0;
// I prefer += to ++, as each statement should do only one thing,
// it's easier to reason about
for (int i = start; i <= end; i += 1) {
// Pulling this into a separate function prevents leaking
// state, which was the bulk of the issue in the original.
// Ternary if adds 1 or 0, depending on the result of the
// method call. When the methods are named sensibly, I find
// this can be more readable than a regular if construct.
count += ifAllDigitsDivisibleByN(modBy, i) ? 1 : 0;
}
return count;
}
private boolean ifAllDigitsDivisibleByN(final int modBy, final int i) {
// For smaller numbers, this won't make much of a difference, but
// in principle, there's no real reason to check every instance of
// a particular digit.
for(Integer digit : uniqueDigitsInN(i)) {
if ( !isDigitDivisibleBy(modBy, digit) ) {
return false;
}
}
return true;
}
// The switch to Integer is to avoid Java's auto-boxing, which
// can get expensive inside of a tight loop.
private boolean isDigitDivisibleBy(final Integer modBy, final Integer digit) {
// Always include parens to group sub-expressions, forgetting the
// precedence rules between && and || is a good way to introduce
// bugs.
return digit == 0 || (digit % modBy == 0);
}
private Set<Integer> uniqueDigitsInN(final int number) {
// Sets are an easy and efficient way to cull duplicates.
Set<Integer> digitsInN = new HashSet<>();
for (int n = number; n != 0; n /= 10) {
digitsInN.add(n % 10);
}
return digitsInN;
}

NthPrime- what's wrong with this while/for loop or set of if-statements?

Having trouble understanding what's wrong in the code.
I'm also trying to avoid using multiple methods if possible and just keep the functionality within the while loop.
public class NthPrime {
public static void main(String[] args) {
int n;
System.out.println("Which nth prime number do you want?");
n = IO.readInt();
if(n <= 0) {
IO.reportBadInput();
return;
}
if(n == 1) {
System.out.println("Nth prime number is: 2");
return;
}
int primeCounter = 1;
int currentNum = 3;
int primeVal = 0;
while(primeCounter < n) {
for(int x = 2; x < currentNum; x++) {
if(currentNum % x == 0) {
continue;
} else {
primeVal = currentNum;
primeCounter++;
}
}
currentNum++;
}
System.out.println(primeVal);
}
}
Your code assumes that every time it encounters a number coprime to the number it's checking, it has a prime. That is to say, your if block:
if(currentNum % x == 0) {
continue;
} else {
primeVal = currentNum;
primeCounter++;
}
says "If it's composite (i.e. divisble by x), then there's no point in continuing to test this number. However, if it's not composite, then we have a prime!" This is faulty because if there's a composite number above the coprime number, your code doesn't care.
This faulty test also gets run for every single coprime number below the number you're checking.
You may be able to fix this by moving the code that updates primeVal and increments primeCounter to the place where you're certain that currentNum is prime. This would be after the for loop is done checking all the numbers below currentNum.
General hint: Speed up your code by looping to the square root of currentNum, not currentNum itself. It's equivalent to what you have now, but faster.

Very simple prime number test - I think I'm not understanding the for loop

I am practicing past exam papers for a basic java exam, and I am finding it difficult to make a for loop work for testing whether a number is prime. I don't want to complicate it by adding efficiency measures for larger numbers, just something that would at least work for 2 digit numbers.
At the moment it always returns false even if n IS a prime number.
I think my problem is that I am getting something wrong with the for loop itself and where to put the "return true;" and "return false;"... I'm sure it's a really basic mistake I'm making...
public boolean isPrime(int n) {
int i;
for (i = 2; i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
The reason I couldn't find help elsewhere on stackoverflow is because similar questions were asking for a more complicated implementation to have a more efficient way of doing it.
Your for loop has a little problem. It should be: -
for (i = 2; i < n; i++) // replace `i <= n` with `i < n`
Of course you don't want to check the remainder when n is divided by n. It will always give you 1.
In fact, you can even reduce the number of iterations by changing the condition to: - i <= n / 2. Since n can't be divided by a number greater than n / 2, except when we consider n, which we don't have to consider at all.
So, you can change your for loop to: -
for (i = 2; i <= n / 2; i++)
You can stop much earlier and skip through the loop faster with:
public boolean isPrime(long n) {
// fast even test.
if(n > 2 && (n & 1) == 0)
return false;
// only odd factors need to be tested up to n^0.5
for(int i = 3; i * i <= n; i += 2)
if (n % i == 0)
return false;
return true;
}
Error is i<=n
for (i = 2; i<n; i++){
You should write i < n, because the last iteration step will give you true.
public class PrimeNumberCheck {
private static int maxNumberToCheck = 100;
public PrimeNumberCheck() {
}
public static void main(String[] args) {
PrimeNumberCheck primeNumberCheck = new PrimeNumberCheck();
for(int ii=0;ii < maxNumberToCheck; ii++) {
boolean isPrimeNumber = primeNumberCheck.isPrime(ii);
System.out.println(ii + " is " + (isPrimeNumber == true ? "prime." : "not prime."));
}
}
private boolean isPrime(int numberToCheck) {
boolean isPrime = true;
if(numberToCheck < 2) {
isPrime = false;
}
for(int ii=2;ii<numberToCheck;ii++) {
if(numberToCheck%ii == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
}
With this code number divisible by 3 will be skipped the for loop code initialization.
For loop iteration will also skip multiples of 3.
private static boolean isPrime(int n) {
if ((n > 2 && (n & 1) == 0) // check is it even
|| n <= 1 //check for -ve
|| (n > 3 && (n % 3 == 0))) { //check for 3 divisiable
return false;
}
int maxLookup = (int) Math.sqrt(n);
for (int i = 3; (i+2) <= maxLookup; i = i + 6) {
if (n % (i+2) == 0 || n % (i+4) == 0) {
return false;
}
}
return true;
}
You could also use some simple Math property for this in your for loop.
A number 'n' will be a prime number if and only if it is divisible by itself or 1.
If a number is not a prime number it will have two factors:
n = a * b
you can use the for loop to check till sqrt of the number 'n' instead of going all the way to 'n'. As in if 'a' and 'b' both are greater than the sqrt of the number 'n', a*b would be greater than 'n'. So at least one of the factors must be less than or equal to the square root.
so your loop would be something like below:
for(int i=2; i<=Math.sqrt(n); i++)
By doing this you would drastically reduce the run time complexity of the code.
I think it would come down to O(n/2).
One of the fastest way is looping only till the square root of n.
private static boolean isPrime(int n){
int square = (int)Math.ceil((Math.sqrt(n)));//find the square root
HashSet<Integer> nos = new HashSet<>();
for(int i=1;i<=square;i++){
if(n%i==0){
if(n/i==i){
nos.add(i);
}else{
nos.add(i);
int rem = n/i;
nos.add(rem);
}
}
}
return nos.size()==2;//if contains 1 and n then prime
}
You are checking i<=n.So when i==n, you will get 0 only and it will return false always.Try i<=(n/2).No need to check until i<n.
The mentioned above algorithm treats 1 as prime though it is not.
Hence here is the solution.
static boolean isPrime(int n) {
int perfect_modulo = 0;
boolean prime = false;
for ( int i = 1; i <= n; i++ ) {
if ( n % i == 0 ) {
perfect_modulo += 1;
}
}
if ( perfect_modulo == 2 ) {
prime = true;
}
return prime;
}
Doing it the Java 8 way is nicer and cleaner
private static boolean isPrimeA(final int number) {
return IntStream
.rangeClosed(2, number/2)
.noneMatch(i -> number%i == 0);
}

Why does my isFullHouse() method also accept a simple three-of-a-kind?

I am having problems with my full house method. I thought it was as simple as checking for three of a kind and a pair. But with my current code i am getting a full house with only a three of a kind. Code for isFullHouse() isThreeOfAKind() and isPair() is below thanks for all the help!
public boolean isPair() {
Pips[] values = new Pips[5];
int count =0;
//Put each cards numeric value into array
for(int i = 0; i < cards.length; i++){
values[i] = cards[i].getPip();
}
//Loop through the values. Compare each value to all values
//If exactly two matches are made - return true
for(int x = 1; x < values.length; x++){
for(int y = 0; y < x; y++){
if(values[x].equals(values[y])) count++;
}
if (count == 1) return true;
count = 0;
}
return false;
}
public boolean isThreeOfAKind() {
Pips[] values = new Pips[5];
int counter = 0;
for(int i = 0; i < cards.length; i++){
values[i] = cards[i].getPip();
}
//Same process as isPair(), except return true for 3 matches
for(int x = 2; x < values.length; x++){
for(int y = 0; y < x; y++){
if(values[x].equals(values[y]))
counter++;
}
if(counter == 2) return true;
counter = 0;
}
return false;
}
public boolean isFullHouse(){
if(isThreeOfAKind() && isPair())
return true;
return false;
}
Check to make sure that the pair is of a different rank than the three of a kind. Otherwise, your isPair() function will find the same cards as the three of a kind. Maybe like this:
public boolean isFullHouse(){
int three = isThreeOfAKind();
int pair = isPair();
if (three != 0 && pair != 0 && three != pair) {
return true;
}
return false;
}
(I used int, but you could change to use your Pips type if you like.)
Can I suggest a way of making your logic dramatically simpler?
Consider a helper method named partitionByRank():
public class RankSet {
private int count;
private Rank rank;
}
/**
* Groups the hand into counts of cards with same rank, sorting first by
* set size and then rank as secondary criteria
*/
public List<RankSet> partitionByRank() {
//input e.g.: {Kh, Qs, 4s, Kd, Qs}
//output e.g.: {[2, K], [2, Q], [1, 4]}
}
Getting the type of hand is really easy then:
public boolean isFullHouse() {
List<RankSet> sets = partitionByRank();
return sets.length() == 2 && sets.get(0).count == 3 && sets.get(1).count() == 2;
}
public boolean isTrips() {
//...
return sets.length() == 3 && sets.get(0).count = 3;
}
This will also help later on when you inevitably need to check whether one pair is greater than another pair, e.g.
You have to remove the three of a kind cards from the five card hand first. Three of a kind is true implies two of a kind is true. The sets need to be disjoint.
You are missing a third condition: the triple needs to be different cards than the pair. Soo... since you have this shared "cards" array, you probably could "mark" the cards as counted, and reset the counted status for each pass:
//Same process as isPair(), except return true for 3 matches
for(int x = 2; x < values.length; x++){
cards[x].setCounted(true); // by default, count the start card
for(int y = 0; y < x; y++){
// make sure the card isn't already counted:
if(!cards[y].isCounted() && values[x].equals(values[y])) {
counter++;
cards[x].setCounted(true); // count it
}
}
if(counter == 2) return true;
counter = 0;
// reset counted cards
for(int z=0, zlen=values.length; z < zlen; z++) { cards[z].setCounted(false); }
}
because three of a kind has a pair as well (actually would probably be 2 pairs in your code)
one way to do this is to sort the hand by rank, then its just conditionals to detect a boat.
if ( ((c1.rank == c2.rank == c3.rank) && (c4.rank == c5.rank)) ||
(c1.rank == c2.rank) && (c3.rank == c4.rank == c5.rank))
ther emight be an extra ( in there but you get the idea...
You need to make sure the pair is a different two cards than the three of a kind. If the hand is A A A 7 8, then both ThreeOfAKind and isPair return true because you have three aces (and a pair of aces).
Your isPair() method will always return true when there are three cards of a kind because your inner loop always tests the y values only up to x.
so with this data AAA78, when x = 1 y = 0 you will get count == 1 in the inner loop and return true although there are three of a kind. It's better to loop over the entire array and count values when
if(values[x].equals(values[y]) && x != y)
Besides - it's better to use one function in the form of isNOfAKind() which gets the amount of cards as a parameter since these two methods essentially do the same.
Just an idea, wouldn't it be easier to do something like this:
int[] count=new int[13];//size of all ranks
for (i=0;i<5;i++)
count[ card[i].rank ] ++;
So you will have for example: 0 0 0 0 0 3 0 0 0 2 0 0 0 0 for a full house. A straight would look like 5 ones in a row: 0 0 0 0 1 1 1 1 1 0 0 0.
Since the methods are public, I would not like the isPair() method to return true if there is a pair. It should only return true if there is nothing better than one pair.
A better general approach to the problem - this is C#, but converting it to Java should be straightforward:
int[] countOfRank = new int[13];
int[] countOfSuit = new int[4];
for(int i = 0; i < cards.length; i++)
{
countOfRank[cards[i].Rank]++;
countOfSuit[cards[i].Suit]++;
}
for (int i=0; i < countOfSuit.length; i++)
{
isFlush = isFlush || countOfSuit[i] == 5;
}
int[] countOfTuple = new int[5];
int runLength=0;
for (int i=0; i < countOfRank.length; i++)
{
if (countOfRank[i] == 1)
{
runLength++;
isStraight = (isStraight || runLength == 5);
}
else
{
runLength=0;
}
countOfTuple[countOfRank[i]]++;
}
isPair = (countOfTuple[2] == 1 && countOfTuple[3] == 0);
isTwoPair = (countOfTuple[2] == 2);
isFullHouse = (countOfTuple[2] == 1 && countOfTuple[3] == 1);
isThreeOfAKind = (countOfTuple[2] == 0 && countOfTuple[3] == 1);
isFourOfAKind = (countOfTuple[4] == 1);
isStraightFlush = (isStraight && isFlush);
isStraight = (isStraight && !isStraightFlush);
isFlush = (isFlush && !isStraightFlush);
isRoyalFlush = (isStraightFlush && countOfRank[12] == 1);
isStraightFlush = (isStraightFlush && !isRoyalFlush);
If you're only dealing with five-card hands, counting the number of pairs should yield one for a pair, two for two-pair, three for three-of-a-kind (e.g. if one has As, Ad, and Ac, the pairs are As-Ad, As-Ac, and Ad-Ac), four for a full house, and six for four-of-a-kind. This logic will not work with seven card hands, since it would count three for e.g. A-A-K-K-Q-Q-J (which should only count as two-pair, not three-of-a-kind), and six for A-A-A-K-K-K-Q (which should count as a full house, not four-of-a-kind).
According to your code inlined comments (exactly two matches words) maybe you are trying to implement isPair method in such a way that it will return false in case of three of a kind combination. If so, you need change your isPair method to iterate over all items in the array, like this:
//Loop through the values. Compare each value to all values
//If exactly two matches are made - return true
for(int x = 0; x < values.length; x++){
for(int y = 0; y < values.length; y++){
if(y != x && values[x].equals(values[y])) count++;
}
if (count == 1) return true;
count = 0;
}

Categories

Resources