Bulls and Cows Java code explanation - java

I've been searching for the source code of this game and found this one. However, I didn't understand the hasDupes method at the end of the code.
Could you explain it to me?
Source code - here
public static boolean hasDupes(int num){
boolean[] digs = new boolean[10];
while(num > 0){
if(digs[num%10]) return true;
digs[num%10] = true;
num/= 10;
}
return false;

So let's step through it:
boolean[] digs = new boolean[10];
In Java, all the items in an array declaration are given a default value. In the case of boolean, it is false. So this creates an array of 10 elements where each element is false
while(num > 0){
if(digs[num%10]) return true;
digs[num%10] = true;
num/= 10;
}
Modding a number by 10 (num % 10) and then dividing by 10 (num/= 10) is a common way to "pop" off the last digit from a number. For example,
int someNum = "1357";
int lastDigit = mod % 10; // lastDigit is 7
someNum /= 10; // someNum is now 135
As you can see, the 7 gets removed. So the while loop is just popping of each digit of num until all the digits are processed. Now, for each digit that is being removed, digs[num%10] = true; is simply keeping track of the digits already removed. By keeping track of these, if(digs[num%10]) return true; will return true from the method if a digit has already been processed.
So, in much simpler words, this method just checks to see if a number contains more than 1 of the same digit.
12345 will return false
12341 will return true

Just make a pen & paper test. Our number system has 10 digits: 0 to 9. digs represents, whether a digit has occured already. with num % 10 you get the last digit of num. So let's say num has an 1 at the least significant position. That means: digs[i] will be set to true (digs[num%10] = true;). Now let's look on: with num /= 10 you remove the last digit from an integer. For example, 3211 /= 10 will be 321 (integer arithmetics, I know you cannot apply /= to literals, but it is only a demonstration to explain the semantics). Since num is > 0, the loop is executed again. This time, the if-condition will be true (because we set digs[1] to true one iteration before), we found a duplicate digit. If the method is able to leave the loop without entering the if, num has pairwise unequal digits. That's it.

It's checking if any value in base 10 has duplicated digits.
So 9019 has duplicated digits (9) when written as a decimal value. 123 does not.

In the context of the game, it basically checks to see if the given integer, num, has duplicated digits. It does so by creating an array of 10 boolean values, such that two digits that are duplicated will be dropped into the same cell in the array. The algorithm uses
An array of 10 boolean values to represent each digit in our base 10 number system. So if you are dealing with base 16 number system, you will need an array of 16 boolean values.
num modulo 10 to extract the least significant digit of num until all digits have been examined. Again, it uses modulo 10 because it is assuming a base 10 number system.
The moment that duplicated digits are detected, the method returns true:
if(digs[num%10]) return true;
If you look at the main() method in your sample codes, the algorithm will attempt to keep generating random number, until one with no duplicated digits is found.
while(hasDupes(target= (gen.nextInt(9000) + 1000)));

Related

Divisor value in for loop is mysteriously (?) changing

So I have been at this for hours, and I'm honestly completely stuck. I've wrote a for loop that counts the amount of numbers in an integer, but I've found that the divisor value changes once i enter a number above 10 digits, and I can't figure out why. I've searched the internet to no avail, so I would appreciate any help or tips if you have any. Thank you!
public static int getNumberOfDigits(long creditCardNumber)
{
//problem with 0's at beginning and more than 10 digits
int nDigitsInCard = 0;
int divisor = (int) creditCardNumber;
for(int i = 0; i <= creditCardNumber; i++){
while(divisor!=0){
divisor/=10;
++nDigitsInCard;
}
}
// return the number of digits in nDigitsInCard
return nDigitsInCard;
}
ints can't hold numbers greater than 2,147,483,647. You need to stick to longs to work with larger numbers.
Integers can only hold numbers up to 2 ^ 32 - 1. Also, why are you casting the input parameter to an integer?
Another thing is that you are counting the number of digits in every number leading up to divisor since you are looping from 0 all the way up to creditCardNumber in the for(int i = 0; i <= creditCardNumber; i++){ ... }. So for example 10000 would return the number of digits in 1, the number of digits in 2, all the way up to 10000.
Lastly, the whole function can be done in one line with
return Long.toString(creditCardNumber).length();
or
return creditCardNumber.toString().length();
if you change creditCardNumber to a Long instead of a long, but you would have to call it with an l suffix at the end.
If you want something even shorter, you can do
return (creditCardNumber+"").length();
When you have the number greater than 10 digits, the conversion to an integer doesn't complete because the integer can't hold valures greater than 2^31 - 1, or 2,147,483,647, which is a number with only 10 digits. I recommend sticking with long.

Using recursion to determine the number of digits

I'm currently stuck on one line of code that I'm not fully understanding.
So, I'm reading example codes from the book, and one of "programs" used recursion to determine the number of digits in an integer n. The one line of code that I got stuck at and do not fully understand is:
if (number >= 10) {
return numberOfDigits(number / 10) + 1;
For an example, this makes the number 42 return 2, which it's supposed to do. But how exactly does the function return 2? 42 divided by 10 is equal to 4,2 or 4. That plus 1 is 5, so how does it return 2?
Recursion is a way to get one call of the method to perform some of the work, while deferring the remainder of the work to making another recursive call. Here, a "number of digits" recursive method says that the number of digits in a number is equal to 1 for the last digit plus the number of digits remaining after the last digit is removed.
In the return statement, the + 1 counts the last digit in the number, while number / 10 performs truncating integer division to remove the last digit. The recursive call counts the digits in the number with the last digit removed.
What you haven't shown is the base case of the recursion, when the number is single-digit (not greater than or equal to 10). That is simply 1 digit. The value 4 is not figured into the calculation. The method effectively counts the digits, one at a time, until there are no more digits left. There is one recursive method call per digit.
The full method probably looks something like this:
public int numberOfDigits(int number) {
if (number >= 10) {
return numberOfDigits(number / 10) + 1;
}
// base case: only one digit
return 1;
}
By inspection, if we pass a two digit number, the if statement will be hit, which will return whatever the recursive call of the input / 10 is, plus one. Let's say the input were 42. In this case, it would return numberOfDigits(42 / 10) + 1. We know that numberOfDigits(4) returns 1, so this would return a total of 2, which is correct.
Using inductive reasoning, we can build up to convince ourselves of any number of arbitrary length.
Side note: In my travels, I have more often seen the base case handled first using an if statement, with the inductive case happening by default. So, I would have expected to see this code:
public int numberOfDigits(int number) {
if (number < 10) return 1;
return numberOfDigits(number / 10) + 1;
}

Sorting by least significant digit

I am trying to write a program that accepts an array of five four digit numbers and sorts the array based off the least significant digit. For example if the numbers were 1234, 5432, 4567, and 8978, the array would be sorted first by the last digit so the nest sort would be 5432, 1224, 4597, 8978. Then after it would be 1224, 5432, 8978, 4597. And so on until it is fully sorted.
I have wrote the code for displaying the array and part of it for sorting. I am not sure how to write the equations I need to compare each digit. This is my code for sorting by each digit so far:
public static void sortByDigit(int[] array, int size)
{
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size; j++)
{
}
for(i = 0; i < size; i++)
{
System.out.println(array[i]);
}
}
}
I am not sure what to put in the nested for loop. I think I need to use the modulus.
I just wrote this to separate the digits but I don't know how to swap the numbers or compare them.
int first = array[i]%10;
int second = (array[i]%100)/10;
int third = (array[i]%1000)/10;
int fourth = (array[i]%10000)/10;
Would this would go in the for loop?
It seems like your problem is mainly just getting the value of a digit at a certain index. Once you can do that, you should be able to formulate a solution.
Your hunch that you need modulus is absolutely correct. The modulo operator (%) returns the remainder on a given division operation. This means that saying 10 % 2 would equal 0, as there is no remainder. 10 % 3, however, would yield 1, as the remainder is one.
Given that quick background on modulus, we just need to figure out how to make a method that can grab a digit. Let's start with a general signature:
public int getValueAtIdx(int value, int idx){
}
So, if we call getValueAtIdx(145, 2), it should return 1 (assuming that the index starts at the least significant digit). If we call getValueAtIdx(562354, 3), it should return 2. You get the idea.
Alright, so let's start by using figuring out how to do this on a simple case. Let's say we call getValueAtIdx(27, 0). Using modulus, we should be able to grab that 7. Our equation is 27 % x = 7, and we just need to determine x. So 27 divided by what will give us a remainder of 7? 10, of course! That makes our equation 27 % 10 = 7.
Now that's all find and dandy, but how does 10 relate to 0? Well, let's try and grab the value at index 1 this time (2), and see if we can't figure it out. With what we did last time, we should have something like 27 % x = 27 (WARNING: There is a rabbit-hole here where you could think x should be 5, but upon further examination it can be found that only works in this case). What if we take the 10 we used earlier, but square it (index+1)? That would give us 27 % 100 = 27. Then all we have to do is divide by 10 and we're good.
So what would that look like in the function we are making?
public int getValueAtIdx(int value, int idx){
int modDivisor = (int) Math.pow(10, (idx+1));
int remainder = value % modDivisor;
int digit = remainder / (modDivisor / 10);
return digit;
}
Ok, so let's to back to the more complicated example: getValueAtIdx(562354, 3).
In the first step, modDivisor becomes 10^4, which equals 10000.
In the second step, remainder is set to 562354 % 10000, which equals 2354.
In the third and final step, digit is set to remainder / (10000 / 10). Breaking that down, we get remainder / 1000, which (using integer division) is equal to 2.
Our final step is return the digit we have acquired.
EDIT: As for the sort logic itself, you may want to look here for a good idea.
The general process is to compare the two digits, and if they are equal move on to their next digit. If they are not equal, put them in the bucket and move on.

Issue with implementation of Fermat's little therorm

Here's my implementation of Fermat's little theorem. Does anyone know why it's not working?
Here are the rules I'm following:
Let n be the number to test for primality.
Pick any integer a between 2 and n-1.
compute a^n mod n.
check whether a^n = a mod n.
myCode:
int low = 2;
int high = n -1;
Random rand = new Random();
//Pick any integer a between 2 and n-1.
Double a = (double) (rand.nextInt(high-low) + low);
//compute:a^n = a mod n
Double val = Math.pow(a,n) % n;
//check whether a^n = a mod n
if(a.equals(val)){
return "True";
}else{
return "False";
}
This is a list of primes less than 100000. Whenever I input in any of these numbers, instead of getting 'true', I get 'false'.
The First 100,008 Primes
This is the reason why I believe the code isn't working.
In java, a double only has a limited precision of about 15 to 17 digits. This means that while you can compute the value of Math.pow(a,n), for very large numbers, you have no guarantee you'll get an exact result once the value has more than 15 digits.
With large values of a or n, your computation will exceed that limit. For example
Math.pow(3, 67) will have a value of 9.270946314789783e31 which means that any digit after the last 3 is lost. For this reason, after applying the modulo operation, you have no guarantee to get the right result (example).
This means that your code does not actually test what you think it does. This is inherent to the way floating point numbers work and you must change the way you hold your values to solve this problem. You could use long but then you would have problems with overflows (a long cannot hold a value greater than 2^64 - 1 so again, in the case of 3^67 you'd have another problem.
One solution is to use a class designed to hold arbitrary large numbers such as BigInteger which is part of the Java SE API.
As the others have noted, taking the power will quickly overflow. For example, if you are picking a number n to test for primality as small as say, 30, and the random number a is 20, 20^30 = about 10^39 which is something >> 2^90. (I took the ln of 10^39).
You want to use BigInteger, which even has the exact method you want:
public BigInteger modPow(BigInteger exponent, BigInteger m)
"Returns a BigInteger whose value is (this^exponent mod m)"
Also, I don't think that testing a single random number between 2 and n-1 will "prove" anything. You have to loop through all the integers between 2 and n-1.
#evthim Even if you have used the modPow function of the BigInteger class, you cannot get all the prime numbers in the range you selected correctly. To clarify the issue further, you will get all the prime numbers in the range, but some numbers you have are not prime. If you rearrange this code using the BigInteger class. When you try all 64-bit numbers, some non-prime numbers will also write. These numbers are as follows;
341, 561, 645, 1105, 1387, 1729, 1905, 2047, 2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681, 5461, 6601, 7957, 8321, 8481, 8911, 10261, 10585, 11305, 12801, 13741, 13747, 13981, 14491, 15709, 15841, 16705, 18705, 18721, 19951, 23001, 23377, 25761, 29341, ...
https://oeis.org/a001567
161038, 215326, 2568226, 3020626, 7866046, 9115426, 49699666, 143742226, 161292286, 196116194, 209665666, 213388066, 293974066, 336408382, 376366, 666, 566, 566, 666 2001038066, 2138882626, 2952654706, 3220041826, ...
https://oeis.org/a006935
As a solution, make sure that the number you tested is not in this list by getting a list of these numbers from the link below.
http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
The solution for C # is as follows.
public static bool IsPrime(ulong number)
{
return number == 2
? true
: (BigInterger.ModPow(2, number, number) == 2
? (number & 1 != 0 && BinarySearchInA001567(number) == false)
: false)
}
public static bool BinarySearchInA001567(ulong number)
{
// Is number in list?
// todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
// Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}

Can someone please explain how this implementation works? Also, can it be made better? How?

public class Main {
public static void main(String args []){
long numberOfPrimes = 0; //Initialises variable numberOfPrimes to 0 (same for all other variables)
int number = 1;
int maxLimit = 10000000;
boolean[] sieve = new boolean[maxLimit]; //creates new boolean array called sieve and allocates space on the
//stack for this array which has maxLimit spaces in it
for ( int i = 2; i < maxLimit; i++ ) { //for statement cycling from 2 to 10000000, does not execute the rest
//of the block if the boolean value in the array is true
if ( sieve[i] == true ) continue;
numberOfPrimes++; //otherwise it increments the number of prime numbers found
if ( numberOfPrimes == 10001 ) { //if 10001st prime number is found, break from loop
number = i;
break;
}
for ( int j = i+i; j < maxLimit; j += i ) //do not understand the point of this loop logically
sieve[j] = true; //testing if the value in the array is true again?
}
System.out.println("10001st prime: "+ number);
}
}
I don't really understand what is going on in this program and was hoping somebody could explain it to me? I have commented the specific lines causing me trouble/what I understand lines to be doing. Thank you very much for all the help! :)
Make yourself familiar with Eratosthenes' Sieve algorithm. Wikipedia even has animated gif demonstrating the process. And your code is just a straightforward implementation of it.
Yes, this is your basic implementation of Eratosthenes' Sieve. There are quite a few ways in which you can improve it, but let's go over the basic principle first.
What you are doing is creating an array of boolean values. The INDEX in the array represents the number which we are testing to see if it is a prime or not.
Now you are going to start checking each number to see if it is a prime. First off, the definition of a prime is "all numbers divisible ONLY by itself and 1 without fractioning".
for ( int i = 2; i < maxLimit; i++ )
You start with the INDEX 2 (the number 3) because depending on your definition, 1 and 2 are always prime. (Some definitions say 1 is not a prime).
if ( sieve[i] == true ) continue;
If a number has been marked as a non-prime previously, we don't bother with the current iteration.
numberOfPrimes++;
if ( numberOfPrimes == 10001 ) {
number = i;
break;
}
If the INDEX we are at currently has not been marked as being a prime, it has to be one, so we increment the number of primes we have found. The next piece of code I'm assuming is part of the requirements of the program which states that if 10001 primes have been found, the program must exit. That part can be left out if you actually want to check for primes up to the maximum number defined in stead of for a specific number of primes.
for ( int j = i+i; j < maxLimit; j += i )
sieve[j] = true;
This is where the actual magic of the sieve starts. From the definition of a prime, a number cannot be a prime if it is divisible by anything other than itself and 1. Therefore, for any new number we find that is a prime, we can mark all it's factors as NOT being prime. For example, the first iteration of the for loop, we start with 3. Because sieve[2] is false (have not visited before), it is a prime (AND 3 IS A PRIME!). Then, all other factors of 3 CANNOT be primes. The above mentioned for loop goes through the entire sieve and marks all factors of 3 as false. So that loop will do: sieve[5] = true; sieve[8] = true ... up until the end of the sieve.
Now, when you reach the first number greater than the maximum defined initially, you can be certain that any number that has a factor has been marked as not being a prime. What you end up with is a boolean array, where each index marked as false, represents a prime number.
You can probably get a much better description on wikipedia, but this is the jist of it. Hope it helps!
for ( int j = i+i; j < maxLimit; j += i ) //dont understand the point of this loop logically
sieve[j] = true; //testing if the value in the array is true again ?
This is not a testing, but rather a setting. This loop is setting all the items in the array with indexes multiple of i to true. When i is 2, then the items 4, 6, 8 ... will be set to true. When i is 3, the items 6, 9, 12 ... will be set to true and so on.
And as you can deduce by the first if,
if ( sieve[i] == true ) continue;
... all the items that are true correspond to non-prime numbers.
I find the easiest way to understand something is to deconstruct it. Therefore, lets go through the loop a few times, shall we?
Dawn of the First Iteration
− 9999998 Values Remain −
i = 2
sieve[2] is false, so we keep going in the current iteration.
numberOfPrimes = 1 and thus we continue processing
Set every multiple of 2 to true in sieve[].
Dawn of the Second Iteration
− 9999997 Values Remain −
i = 3
sieve[3] is false, so we keep going in the current iteration.
numberOfPrimes = 2 and thus we continue processing
Set every multiple of 3 to true in sieve[].
Dawn of the Third Iteration
− 9999996 Values Remain −
i = 4
sieve[4] is true (from first iteration). Skip to next iteration.
etc... but in this case, the moon doesn't crash into Termina.
The loop in question isn't checking for true values, it's setting true values.
It's going through each multiple of the prime and marking it as non-prime up to maxLimit. You'll notice there's no other math in the code to determine what's prime and what's not.
This is the algorithm to find the prime numbers between 1 and the maximum limit given.
And the loop added 2nd is to make true for the number which is divisible by any other number. so for the first outer loop all the number divisible by two ll be set to true then divisible by 3 then by 4 and so on.. and the numbers for which the boolean array contains false are the prime numbers.

Categories