Natural Numbers Sum of Digits using recursion - java

Im trying to implement a function that returns a natural number which is the sum of the digits within an entered natural number. I just keep on getting an infinite loop. I know i have to return the recursive call but i cant figure this out. Here is what i have so far:
private static NaturalNumber sumOfDigits(NaturalNumber n) {
NaturalNumber zero = new NaturalNumber2(0);
if (n.compareTo(zero) == 0) {
return zero;
} else {
NaturalNumber z = new NaturalNumber2(n.divideBy10());
n.divideBy10();
z.add(sumOfDigits(n));
// return ___;
}
}
What am i supposed to return? Returning z doesn't work

You are making the recursive call with n, the same number that was passed into your procedure. If you strip off a digit for z, then the recursive call has to be made with the rest of the digits.
You can strip off a digit with mod 10 and then get the rest of the digits by divide by 10. If you were using ints it would be:
return (n % 10) + sumOfDigits(n / 10);

z.add(sumOfDigits(n)); should be z.add(sumOfDigits(n.divideBy10()));. The main point is in the recursion you only want to process the remainder of the answer, not the whole problem.

Related

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;
}

Printing random even value between two values using inheritance

I am trying to print a list of random even numbers (5 times) using a bounds. Example being from 0 to 30 (including both those numbers). This is what I have so far (this is in its own class):
public int nextEven(int h){
int n = rand.nextEven(h) % 2;
return n;
}
This is where it would print from my main method:
System.out.println("Random Even:");
for (int i = 0; i < 5; i++){
System.out.println(rand.nextEven(30));
}
When I run the program it gives me an error and I am not quite sure how to solve this. This is an example of the desired output of even numbers from 0 to 30:
4
26
12
10
20
It isn't clear why taking the remainder of 2 would yield an even number. Instead, generate a number in the range 0 to h / 2 and then multiply the result of that by 2. Like,
public int nextEven(int h){
int n = ThreadLocalRandom.current().nextInt(1 + (h / 2)); // 0 to (h / 2) inclusive
return n * 2; // n * 2 is even (or zero).
}
What exactly is rand? Is it the Random class or an instance of your own class?
Since you want to do something with inheritance I guess you want to overwrite a method, but if rand is an instance of the java Random class this won't work.
The error probably comes from recursively calling nextEven method forever.
If you could clarify what exactly you want to do?
I see at least two solutions.
The first one supposes that random + 1 = random. I mean, that if you add or subtract a random number you still get a valid random number. That's why you can use Random class to generate a value in the desired period and then add or subtract one it the number is odd.
The second approach is just to generate an array of even values for the desired period. Then take a random value from this array.
The mod operator % will give you the remainder of the first value divided by the second.
value % 2
... will return 0 if value is even, or 1 if value is odd.
Since rand is a reference to an instance of the class containing your code, you have an infinite recursion. What you really need is something like:
public int nextEven(int h){
int evenRandomValue;
do {
evenRandomValue = (int)(Math.random() * (h + 1));
} while(evenRandomValue % 2 == 1);
return evenRandomValue;
}
Here is a quite explicit way to achieve this using streams:
List<Integer> myRandomInts = Random.ints(lower, upper + 1)
.filter(i -> i % 2 == 0)
.limit(5).boxed()
.collect(Collectors.toList());
This can be read as 'generate an infinite stream of random numbers between given bounds, filter out odds, take the first 5, turn into Integer objects and then collect into a list.

Luhn checksum validation in Java

I have to replicate the luhn algorithm in Java, the problem I face is how to implement this in an efficient and elegant way (not a requirement but that is what I want).
The luhn-algorithm works like this:
You take a number, let's say 56789
loop over the next steps till there are no digits left
You pick the left-most digit and add it to the total sum. sum = 5
You discard this digit and go the next. number = 6789
You double this digit, if it's more than one digit you take apart this number and add them separately to the sum. 2*6 = 12, so sum = 5 + 1 = 6 and then sum = 6 + 2 = 8.
Addition restrictions
For this particular problem I was required to read all digits one at a time and do computations on each of them separately before moving on. I also assume that all numbers are positive.
The problems I face and the questions I have
As said before I try to solve this in an elegant and efficient way. That's why I don't want to invoke the toString() method on the number to access all individual digits which require a lot of converting. I also can't use the modulo kind of way because of the restriction above that states once I read a number I should also do computations on it right away. I could only use modulo if I knew in advance the length of the String, but that feels like I first have to count all digits one-for-once which thus is against the restriction. Now I can only think of one way to do this, but this would also require a lot of computations and only ever cares about the first digit*:
int firstDigit(int x) {
while (x > 9) {
x /= 10;
}
return x;
}
Found here: https://stackoverflow.com/a/2968068/3972558
*However, when I think about it, this is basically a different and weird way to make use of the length property of a number by dividing it as often till there is one digit left.
So basically I am stuck now and I think I must use the length property of a number which it does not really have, so I should find it by hand. Is there a good way to do this? Now I am thinking that I should use modulo in combination with the length of a number.
So that I know if the total number of digits is uneven or even and then I can do computations from right to left. Just for fun I think I could use this for efficiency to get the length of a number: https://stackoverflow.com/a/1308407/3972558
This question appeared in the book Think like a programmer.
You can optimise it by unrolling the loop once (or as many times are you like) This will be close to twice as fast for large numbers, however make small numbers slower. If you have an idea of the typical range of numbers you will have you can determine how much to unroll this loop.
int firstDigit(int x) {
while (x > 99)
x /= 100;
if (x > 9)
x /= 10;
return x;
}
use org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit . isValid()
Maven Dependency:
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.4.0</version>
</dependency>
Normally you would process the numbers from right to left using divide by 10 to shift the digits and modulo 10 to extract the last one. You can still use this technique when processing the numbers from left to right. Just use divide by 1000000000 to extract the first number and multiply by 10 to shift it left:
0000056789
0000567890
0005678900
0056789000
0567890000
5678900000
6789000000
7890000000
8900000000
9000000000
Some of those numbers exceed maximum value of int. If you have to support full range of input, you will have to store the number as long:
static int checksum(int x) {
long n = x;
int sum = 0;
while (n != 0) {
long d = 1000000000l;
int digit = (int) (n / d);
n %= d;
n *= 10l;
// add digit to sum
}
return sum;
}
As I understand, you will eventually need to read every digit, so what is wrong with convert initial number to string (and therefore char[]) and then you can easily implement the algorithm iterating that char array.
JDK implementation of Integer.toString is rather optimized so that you would need to implement your own optimalizations, e.g. it uses different lookup tables for optimized conversion, convert two chars at once etc.
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// Requires positive x
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
This was just an example but feel free to check complete implementation :)
I would first convert the number to a kind of BCD (binary coded decimal). I'm not sure to be able to find a better optimisation than the JDK Integer.toString() conversion method but as you said you did not want to use it :
List<Byte> bcd(int i) {
List<Byte> l = new ArrayList<Byte>(10); // max size for an integer to avoid reallocations
if (i == 0) {
l.add((byte) i);
}
else {
while (i != 0) {
l.add((byte) (i % 10));
i = i / 10;
}
}
return l;
}
It is more or less what you proposed to get first digit, but now you have all you digits in one single pass and can use them for your algorythm.
I proposed to use byte because it is enough, but as java always convert to int to do computations, it might be more efficient to directly use a List<Integer> even if it really wastes memory.

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.

How to test if an array contains a pair of numbers whose product is odd?

How can I write a function that takes an array of integers and returns true if their exists a pair of numbers whose product is odd?
What are the properties of odd integers? And of course, how do you write this function in Java? Also, maybe a short explanation of how you went about formulating an algorithm for the actual implementation.
Yes, this is a function out of a textbook. No, this is not homework—I'm just trying to learn, so please no "do your own homework comments."
An odd number is not evenly divisible by two. All you need to know is are there two odd numbers in the set. Just check to see if each number mod 2 is non-zero. If so it is odd. If you find two odd numbers then you can multiply those and get another odd number.
Note: an odd number multiplied by an even number is always even.
The product of two integers will be odd only if both integers are odd. So, to solve this problem, just scan the array once and see if there are two (or more) odd integers.
EDIT: As others have mentioned, you check to see if a number is odd by using the modulus (%) operator. If N % 2 == 0, then the number is even.
Properties worth thinking about:
Odd numbers are not divisible by 2
Any number multiplied by an even number is even
So you can re-state the question as:
Does the array contain at least two integers that are not divisible by 2?
Which should make things easier.
You can test for evenness (or oddness) by using the modulus.
i % 2 = 0 if i is even; test for that and you can find out if a number is even/odd
A brute force algorithm:
public static boolean hasAtLeastTwoOdds(int[] args) {
int[] target = args; // make defensive copy
int oddsFound;
int numberOddsSought = 2;
for (int i = 0; i < target.length; i++) {
if (target[i] % 2 != 0) {
if (oddsFound== numberOddsSought) {
return true;
}
oddsFound++;
}
}
return false;
}
Thank you for your answers and comments.
I now understand well how to test whether an integer is odd. For example, this method is a neat way of doing this test without using multiplication, modulus, or division operators:
protected boolean isOdd(int i) {
return ( (i&1) == 1);
}
With your help, I now realize that the problem is much simpler than I had expected. Here is the rest of my implementation in Java. Comments and criticism are welcome.
protected boolean isOddProduct(int[] arr) {
int oddCount = 0;
if (arr.length < 2)
throw new IllegalArgumentException();
for (int i = 0; i <= arr.length-1; i++) {
if (isOdd(arr[i]))
oddCount++;
}
return oddCount > 1;
}
I wonder if there exists any other ways to perform this test without using *, % or / operators? Maybe I'll ask this question in a new thread.

Categories