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;
}
Related
Hello I'm currently coding something for class. We are basically making a credit card checker to pull the numbers from a text file. The rules we have to follow for the check digit are the following.
Drop the last digit from the card number. The last digit is the check
digit.
Reverse the digits.
Multiply the digits in odd positions (1, 3, 5, etc.) by 2.
Subtract 9 from any result higher than 9.
Sum all the digits.
The check digit (the last number of the card) is the amount that you
would need to add to get a multiple of 10 (Modulo 10)
So I pulled the check digit away by setting a new variable and taking the card # /10. It's in a long so no decimals so this gets rid of the last digit. I then stored that digit as my check digit using %10 of the original number. I then used a loop to reverse the digits which can be seen as:
long lcards = Long.parseLong(cards);
long lastDigit = lcards % 10;
long newCard = lcards / 10;
long reverseCard = 0;
while (newCard != 0)
{
reverseCard = reverseCard * 10;
reverseCard = reverseCard + (newCard % 10);
newCard = newCard / 10;
}
I'm now stuck on the next step :/. How would I do this? Thanks!
Next step:
Multiply the digits in odd positions (1, 3, 5, etc.) by 2.
That requires you to iterate all digits in your input number. And there are two ways to do that:
More or less the same as your first attempt to get rid of the last digit - you can use modulo/division operations to "access" each digit in your number in a similar way as you did before!
Or, instead of working on one number, consider turning the whole number into an array of int values for example; like shown here. Now you can just iterate that array and make the necessary computations.
And in the end, just "merge" the array back into a single number. You could even do that upfront, to get rid of the last digit.
Hope that helps to get you going on the rest of the exercise!
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)));
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.
Consider the following method:
public static boolean isPrime(int n) {
return ! (new String(new char[n])).matches(".?|(..+?)\\1+");
}
I've never been a regular expression guru, so can anyone fully explain how this method actually works? Furthermore, is it efficient compared to other possible methods for determining whether an integer is prime?
First, note that this regex applies to numbers represented in a unary counting system, i.e.
1 is 1
11 is 2
111 is 3
1111 is 4
11111 is 5
111111 is 6
1111111 is 7
and so on. Really, any character can be used (hence the .s in the expression), but I'll use "1".
Second, note that this regex matches composite (non-prime) numbers; thus negation detects primality.
Explanation:
The first half of the expression,
.?
says that the strings "" (0) and "1" (1) are matches, i.e. not prime (by definition, though arguable.)
The second half, in simple English, says:
Match the shortest string whose length is at least 2, for example, "11" (2). Now, see if we can match the entire string by repeating it. Does "1111" (4) match? Does "111111" (6) match? Does "11111111" (8) match? And so on. If not, then try it again for the next shortest string, "111" (3). Etc.
You can now see how, if the original string can't be matched as a multiple of its substrings, then by definition, it's prime!
BTW, the non-greedy operator ? is what makes the "algorithm" start from the shortest and count up.
Efficiency:
It's interesting, but certainly not efficient, by various arguments, some of which I'll consolidate below:
As #TeddHopp notes, the well-known sieve-of-Eratosthenes approach would not bother to check multiples of integers such as 4, 6, and 9, having been "visited" already while checking multiples of 2 and 3. Alas, this regex approach exhaustively checks every smaller integer.
As #PetarMinchev notes, we can "short-circuit" the multiples-checking scheme once we reach the square root of the number. We should be able to because a factor greater than the square root must partner with a factor lesser than the square root (since otherwise two factors greater than the square root would produce a product greater than the number), and if this greater factor exists, then we should have already encountered (and thus, matched) the lesser factor.
As #Jesper and #Brian note with concision, from a non-algorithmic perspective, consider how a regular expression would begin by allocating memory to store the string, e.g. char[9000] for 9000. Well, that was easy, wasn't it? ;)
As #Foon notes, there exist probabilistic methods which may be more efficient for larger numbers, though they may not always be correct (turning up pseudoprimes instead). But also there are deterministic tests that are 100% accurate and far more efficient than sieve-based methods. Wolfram's has a nice summary.
The unary characteristics of primes and why this works has already been covered. So here's a test using conventional approaches and this approach:
public class Main {
public static void main(String[] args) {
long time = System.nanoTime();
for (int i = 2; i < 10000; i++) {
isPrimeOld(i);
}
time = System.nanoTime() - time;
System.out.println(time + " ns (" + time / 1000000 + " ms)");
time = System.nanoTime();
for (int i = 2; i < 10000; i++) {
isPrimeRegex(i);
}
time = System.nanoTime() - time;
System.out.println(time + " ns (" + time / 1000000 + " ms)");
System.out.println("Done");
}
public static boolean isPrimeRegex(int n) {
return !(new String(new char[n])).matches(".?|(..+?)\\1+");
}
public static boolean isPrimeOld(int n) {
if (n == 2)
return true;
if (n < 2)
return false;
if ((n & 1) == 0)
return false;
int limit = (int) Math.round(Math.sqrt(n));
for (int i = 3; i <= limit; i += 2) {
if (n % i == 0)
return false;
}
return true;
}
}
This test computes whether or not the number is prime up to 9,999, starting from 2. And here's its output on a relatively powerful server:
8537795 ns (8 ms)
30842526146 ns (30842 ms)
Done
So it is grossly inefficient once the numbers get large enough. (For up to 999, the regex runs in about 400 ms.) For small numbers, it's fast, but it's still faster to generate the primes up to 9,999 the conventional way than it is to even generate primes up to 99 the old way (23 ms).
This is not a really efficient way to check if a number is prime(it checks every divisor).
An efficient way is to check for divisors up to sqrt(number). This is if you want to be certain if a number is prime. Otherwise there are probabilistic primality checks which are faster, but not 100% correct.
Theres an exercise from a Java book I'm reading that has me confused:
A Fibonacci sequence is the sequence of numbers 1, 1, 2, 3, 5, 8,
13, 21, 34, etc., where each number (from the third on) is the sum
of the previous two. Create a method that takes an integer as an
argument and displays that many Fibonacci numbers starting from the
beginning. If, e.g., you run java Fibonacci 5 (where Fibonacci is
the name of the class) the output will be: 1, 1, 2, 3, 5.
I could have swore that it would need an array or some way of storing the previous numbers but when I saw the answer it wasn't the case:
import java.util.*;
public class Fibonacci {
static int fib(int n) {
if (n <= 2)
return 1;
return fib(n-1) + fib(n-2);
}
public static void main(String[] args) {
// Get the max value from the command line:
int n = Integer.parseInt(args[0]);
if(n < 0) {
System.out.println("Cannot use negative numbers"); return;
}
for(int i = 1; i <= n; i++)
System.out.print(fib(i) + ", ");
}
}
Would someone be able to explain how using a function within itself produces this?
The code you gave is an example of a recursive solution. When the function is called for the first time, it executes until it calls itself. Its state is stored on the stack, and the code begins executing again with new input data. This process repeats until the input is less than 2, at which point 1 is returned, and the answer returns to the previous caller.
For example, calling fib(5) results in the following execution:
fib(5):
fib(4):
fib(3):
fib(2): 1
fib(1): 1
fib(2): 1
fib(3):
fib(2): 1
fib(1): 1
Note that you are partially correct. Intermediate results are stored on the stack in this solution. That is one of the reasons why the recursive solution is so expensive. The other is its O(2^n) complexity. However, if is possible to compute Fibonacci(n) iteratively and without storing all previous results. All you really need is to store the last to results and count from 1 up to n.
This is a recursive solution. A recursive function calls itself until a given stop condition is met. Then each call exits until only the first call remains. That first call outputs the result.
In your solution, the stop condition is :
if (n <= 2)
return 1;
until this condition is met, the function will make successive calls to itself. Each call reduces the int passed as a parameter. When it reaches 2, the stop condition dictates that the function returns with value 1 (the result of n=1 and n=2 in fibonacci(n) ).
Because the fibonacci is the sum of the last two numbers, the recursive part of the function,
return fib(n-1) + fib(n-2);
does a sum of n-1 and n-2 (as I said, the two last numbers of the sequence). When the n equals 2, these calls to function fib will finally have a value, and will be returned.
Example, if n = 3, the recursive part will call fib(2) and fib(1), both are equal or less than 2, so both calls will return 1. So the printf will print 1, 1, 2.
2 is the sum of 1 + 1 (I know it's obvious, but sometimes stating the obvious helps).
F(n)
/ \
F(n-1) F(n-2)
/ \ / \
F(n-2) F(n-3) F(n-3) F(n-4)
/ \
F(n-3) F(n-4)
Important point to note is this algorithm is exponential because it does not store the result of previous calculated numbers. eg F(n-3) is called 3 times.
For more details refer algorithm by dasgupta chapter 0.2
This is the standard example for an recursive function.
The Fibonacci Numbers are declared recursive, too.
Both fib(1) and fib(2) are declared as 1. All others are calculated by adding the last two fibonacci numbers, so fib(3)=fib(2)+fib(1).
Compare this to the calculation method which does exactly this:
static int fib(int n) {
if (n <= 2)
return 1;
return fib(n-1) + fib(n-2);
}
By the way, this is a very slow way to calculate the fibonacci numbers, using two variables (you don't need all of them for the last one, only the last two!) and a loop is in O(n), the recursive function above has O(2^n) operations.