Recursive method to remove all odd digits from an int - java

I'm having trouble writing a recursive method that is meant to remove any odd digits from an int - for example: evenDigits(123456) should return 246. My first thought was to turn the int into a string and cycle through that way but the question explicitly states you cannot use Strings to solve it.
Any help is appreciated
EDIT: This is what I have so far, I'm not sure if its along the right lines, but I cannot figure out what to do if the last digit was to be even
public static int evenDigits(int n)
if(n==2)
{
return 2;
}
if(n==1)
{
return 0;
}
if((n%10)%2==1) //if the last digit is odd
{
return evenDigits(n/10); //run it again without the last digit
}

Since its obviously the homework, I can't provide a full solution, however here are some hints:
When you define recursion you should think when you stop (a stop condition).
If you follow the hints provided by #marksplace - then you will probably stop when the recursion will reach the point where no digits have left.
Another thing you should think of is where to store the result "accumulated so far". You'll pass it through the recursion. Its even called "accumulator" in the literature.
So when you reach the stop condition you'll return the accumulator. In addition think about how exactly you are going to update the accumulator.
Here is an example of how it can work without diving into the code:
123456
a. Last digit is 6, its even, preserve it, update an accumulator (=6)
b. recursive call for 12345
12345 - last digit is odd - remove it,
b. recursivce call for 1234
1234 - last digit is 4 - its even, preserve it, update the accumulator 6 -> 46 (here you should think about the math formula of such an update)
....
At last - stop when you reach the point, where there are no digits, accumulator will contain the answer
Good luck!

Related

Find if a permutation (using + and -) on a string of integers matches a number

Basically what I am doing it taking a string of integers (e.g. "1234"), and I am able to insert a + or - anywhere in this string, as much or little as I want. For example, I can do "1 + 2 + 3 + 4", "12 + 34", "123 - 4", etc. It is required to use all integers of the string, I cannot exclude any.
What I am trying to do is take another array of integers, and find if it was possible to get that number using the permutations mentioned in the first paragraph. I am somewhat lost on where to start looking for this. I could possibly create a recursive loop function to create every possible combination of the string and see if each result matches but this seems like it will be terribly slow. Another thought was to index them into an array - that way I could simply look up the answers after calculating them once.
Anyone have any suggestions?
I could possibly create a recursive loop function to create every possible combination of the string and see if each result matches but this seems like it will be terribly slow.
Doing an exhaustive search is your only option here. Fortunately, the timing isn't going to be too bad even for moderately long strings of up to 7..10 characters, because you do not need to "redo" additions and subtractions of a prior string when you process the "tail".
An outline of a possible implementation could be as follows:
Put all desired results from your array of integers in a hash set
Make a recursive method that takes the result so far, the string, and the position of the next "cut"
When the next "cut" is at the end of the string, check the result so far against the hash set from step 1
Otherwise, try these three possibilities in a loop on k
Use a k-digit number from the "cut" as a positive number, and make a recursive invocation with the "cut" moved by k digits. This is equivalent to inserting a + at the cut
Use a k-digit number from the "cut" as a negative number, and make a recursive invocation with the "cut" moved by k digits. This is equivalent to inserting a - at the cut
I'll give start help, with the approach for such a solution.
formal problem statement;
data model;
algorithm;
heuristics, cleverness.
For N digits there are some 3^N possibilities.
The solution must model the running data as:
the digits, as int[]
the sum
index from which to advance, prior digits were done.
number partalready tried, plus sign. Sign must come separate (as -1, +1) as the coming digit may be 0;
(What I leave out is the collecting of the entire result.)
The brute force solution then could be:
boolean solve(int[] digits, int sum) {
return solve(digits, sum, 1, 0, 0);
}
boolean solve(int[] digits, int sum, int signum, int part, int index) {
if (index >= digits.length) {
return signum * part == sum;
}
// Before the digit at index do either nothing, +, or -
return solve(digits, sum, signum, part * 10 + digits[index], index + 1)
|| solve(digits, sum - signum * part, 1, 0, index + 1)
|| solve(digits, sum - signum * part, -1, 0, index + 1);
}
Mind you could also split the digits in half and try to insert (nothing, +, -) there.
There are pruning opportunities, to diminish the number of tries. First the above can be done in a loop, the alternatives need not all to be tried. The order of evaluation might favor more likely candidates:
if digit 0 ...
if part > sum first - then +
...
Unfortunately +/- make a number theoretical approach AFAIK for me illusory.
#dasblinkenlight mentions even better data models, allowing to not
repeat evaluation in the alternatives. That would be even more
interesting. But might fail miserably due to time constraints. And I
wanted to come with something concrete. Without providing an entirely
ready made solution.
It is reasonable to take a brute force approach if you can rely on the input string not to be too long. If it contains n digits then you can construct 3n-1 formulae from it (between each pair of digits you can insert '+', '-', or nothing, for n-1 internal positions). For a 12-digit input string that's roughly 270000 formulae, which should be computable quite quickly. Of course, you would build and compute each one once, and compare the result to all the alternatives. Don't redo the computation for each array element.
It may be that there's a dynamic programming approach to this, but I'm not immediately seeing it, at least not one that would be substantially better than brute force.

Java exam prep - Recursion task [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
This is my task:
Use recursion to find 13th member of an array where every member is multiplication of last two members minus the second member. First two members are 3 and 3.
This is what I came up with:
public class Zadatak2 {
int array[] = {3,3,0,0,0,0,0,0,0,0,0,0,0};
public Zadatak2(){
find13(2);
}
public int find13(int index){
if (index == 13){
System.out.println("Member 13: " + array[index-1]);
return 0;
}
else{
array[index] = array[index-1] * array[index-2] - array[1];
System.out.println(index + " : " + array[index]);
return find13(index + 1);
}
}
}
Console output where I see index in array : value :
2 : 6
3 : 15
4 : 87
5 : 1302
6 : 113271
7 : 147478839
8 : 1947758222
9 : 465247871
10 : 818773103
11 : -459621106
12 : 383828239
Member 13: 383828239
But I am pretty sure I made a mistake or there is a better solution. Any help is appreciated.
As Kevin W. said in a comment, in the future, "if you want someone to review your code... use the codereview stackexchange". However, here are a few suggestions.
Firstly, as something to keep in mind, the problem you have is a lot like calculating the fibonacci sequence, and there are probably plenty of examples of using recursion to calculate members of that sequence.
Secondly, the way you built your recursive function makes it limited to being used only to find the 13th number in the sequence. You begin at the start of the sequence and work your way up to the 13th number, and what you are doing is basically an iterative solution to the problem with minor tweaks to make it work via recursion.
A better approach would be to generalize your function so that you can pass the sequence member number as a parameter, and the function will calculate it via recursion. The way to do this is to start at your target member number and through recursion, get the members required to make that member. This allows the function to be used to calculate any number in the sequence, not just the 13th number. It also has the added benefit that your code can be both shrunk and do more.
This is the code:
// index is the member number; it is 1 based e.g. index of 1 gives the first number in the sequence
int find(int index)
{
if (index == 1 || index == 2)
return 3;
return (find(index - 1) * find(index - 2)) - find(2);
}
When solving problems with recursion, the method generally used is to start with the problem you want to solve and break it down (as shown in my code above), rather than start with subproblems to find the larger problem (as your code shows).
When applying recursion to a sequence, write out the mathematical definition of the sequence first, and that is what must be returned from the recursive function. For example, in your problem, the definition is
a[n] = (a[n-1] * a[n-2]) - a[2]
Now take a look at the solution I wrote. What I am returning is precisely this sequence definition, just in terms of the recursive function. The base case at the beginning of the function is simply the initial member(s) required to calculate the rest of the sequence. I encourage you to work the algorithm through on paper and play with it to see exactly what is happening.
As a final note, this algorithm is horrendous in terms of run time. There are three recursive calls per call to find(), which means that finding the 13th member is on the order of 3^13, which is exponential. Exponential algorithms are terrible algorithms, and should always be avoided.
If the recursion is examined closely you can see that in order to calculate a[n], the code calculates a[n-1] and a[n-2]. But in order to calculate a[n-1], a[n-2] and a[n-3] are both calculated, meaning that a[n-2] is calculated TWICE. This observation is very important because we only went down one level of recursion. There are a total of about 3^13 member calculations occurring when all there should be are 13 (for the 13 members). All of that time performing the same calculations millions of times is a horrendous waste and is what makes exponential algorithms so awful.
So what if we stored each of the members that the function calculates? This technique is called dynamic programming, and is where answers to subproblems are stored on the way to solving a larger problem so calculations are not performed multiple times. The solution implementing dynamic programming is:
// a variable that persists across function calls such as an instance field
int[] array = new int[20]; // just giving some extra memory in case you want to calculate other members
array[0] = -1; //invalid member of the sequence since it is 1-based
array[1] = 3;
array[2] = 3;
//set the rest of the numbers to values letting you know they have not been set/found/calculated yet
for (int i = 3; i < 20; i++)
{
array[i] = -1;
}
// index is the member number; it is 1 based e.g. index of 1 gives the first number in the sequence
int find(int index)
{
if (array[index] != -1) //if already calculated that member, just return it
return array[index];
//store the answer
array[index] = (find(index - 1) * find(index - 2)) - find(2);
return array[index];
}
With this code, you can call find() for any number and it will calculate it for you, instead of just the 13th number.
Lastly, and most importantly, as Kevin W. pointed out in a comment, the presence of a negative number as a member means that you are getting numbers too big for ints. Luka Milosevic says that the 13th member is actually a number x10^90, which is too big for a long even. Doubles can work as long as you don't need more than 20 or so digits of precision, but because of at least 90 digits in the answer, doubles are not accurate enough. Fortunately Java has a class called BigInteger, which can store as large of numbers as you want, regardless of size. In order to obtain your answer, you probably have to use them, unless you want to do the math manually. The documentation for BigInteger is here.
As this is a task you were assigned to do I would like to give you a hint only. In our case a recursive function would call itself with a lower argument and finally end with some defined values.
In our case the lower values f(1) and f(2) are already defined as 3.
So f(n) = f(n-1) * f(n-2) - f(2) where f(1) = 3 and f(2) = 3.
(If I understood the task right)
Now your job is to do the coding and find f(13).
Does it help?

Finding the expansion of PI

In an interview, I was asked to find a first 9 digit palindrome in an expansion of PI. And I had no idea as to how I should go for it. The question remained in my system throughout the interview and I couldn't properly answer the questions to follow.
Whats the optimal way?
EDIT:
Finding palindrome is not difficult but how can I get the expansion of PI as much as I need. I have tried Math.PI, i have tried 22/7 but nothing gives me what I need.
the "optimal" way here strongly depends on the choice of the algorithm for calculating Pi, assuming you don't have access to an arbitrary number of digits off the shelf.
There are lots of infinite sums that converge against pi, each of which capable of eventually producing the right digits, however you'd have to use some library that allows infinitely precise floating point numbers, or infinitely large integers.
After that, finding the palindromes is relatively easy, as you'd only have to compare the first to the ninth number, the second to the eighth and so forth.
The devil in this case is clearly which converging sum to use for the approximation of Pi.
A couple of these are listed on the wikipedia page for Pi: http://en.wikipedia.org/wiki/Pi#Polygon_approximation_era
Firstly, I would make a subset of the numbers in pi and convert to a string.
I would take a nine character subset string from it, then compare the first character with the last one. If they match, compare character 2 with 8 and so on. If any of the comparisons fails then move the 9 character string to the next set - by one character.
I would probably point the assign the first index value to first variable and ninth index value to second variable and then see if they are equal . In case they are equal I will assign second index value to first variable and eight index value to second variable till they meet at mid postion . In case they differ with one another at some place assign first variable the value of the latest left side index which differs with right side index and second variable value of the left side index + 8 and repeat process till you reach last index - 8 position .

How to calculate Lucas Numbers in Java

I am a starting programmer and need to program an application in java which ask for a number and then prints the first n number of Lucas Numbers. for example when 7 is put in, it outputs: 2, 1, 3, 4, 7, 11, 18.
Just to be clear, lucas numbers are defined as:
2 if n = 0
1 if n = 1
L(n-1) + L(n-2) if n>1
I am really not sure howver how to programm this in java. Because I cannot translate this into java code. I've been thinking for a while now but still can't figure it out. Also when i would have the code for calculating the Nth lucas number, i would now how to output all the first Lucan Numbers up until the Nth number. Can some of you guys help me gte on the right way or give me tips? Thanks a lot!
The definition you have for the Lucas number is recursive, i.e., to calculate the Nth lucas number, you already need to know the N-1th and the N-2nd.
A naive way to do this would be
public int lucas(int N) {
if( N == 0 ) return 2;
if( N == 1 ) return 1;
return lucas(N-1) + lucas(N-2);
}
However, you only have to print the numbers, don't you? Then it's quite easy, actually.
int L2 = 2;
int L1 = 1;
for( int i = 2; i <= N; i++ ) {
int L = L1 + L2;
print(L); //or whatever output function you have
L2 = L1;
L1 = L;
}
The idea is to keep the last two numbers, which you need to compute the next two numbers, always at hand.
PS: These Lucas numbers are just like the Fibonacci numbers with different starting values, so any algorithm for the Fibonacci numbers will do. If you're really good at math, you can even try to find a closed formula for the Lucas numbers, but it's definitely beyond high school math (search tag would be "linear difference equation with constant coefficients").
If you're not sure how to do the whole thing, break the problem down into smaller pieces until you can start.
Try taking each case, one at a time. Implement the '2 if n=0' case, test that it works. The calculation is trivial, but you will have to write the code that calls your implementation, too. The trivial case helps you check that the code around it works properly.
Then implement the next one, check it still works, implement the final one. It'll become clearer as you go.
Just in case someone is looking for a formula and happens on this page then maybe this will help. In Windows take the following line and replace each N with the desired integer, copy the modified line and paste it into Windows' calculator:
(5#/2+0.5)yN+(-(5#/2+0.5))y(-N)=
For example if you want to find the Lucus number for 7 you would paste this line into Windows' calculator:
(5#/2+0.5)y7+(-(5#/2+0.5))y(-7)=
And the result will be 29.

How to multiply two big big numbers

You are given a list of n numbers L=<a_1, a_2,...a_n>. Each of them is
either 0 or of the form +/- 2k, 0 <= k <= 30. Describe and implement an
algorithm that returns the largest product of a CONTINUOUS SUBLIST
p=a_i*a_i+1*...*a_j, 1 <= i <= j <= n.
For example, for the input <8 0 -4 -2 0 1> it should return 8 (either 8
or (-4)*(-2)).
You can use any standard programming language and can assume that
the list is given in any standard data structure, e.g. int[],
vector<int>, List<Integer>, etc.
What is the computational complexity of your algorithm?
In my first answer I addressed the OP's problem in "multiplying two big big numbers". As it turns out, this wish is only a small part of a much bigger problem which I'm going to address now:
"I still haven't arrived at the final skeleton of my algorithm I wonder if you could help me with this."
(See the question for the problem description)
All I'm going to do is explain the approach Amnon proposed in little more detail, so all the credit should go to him.
You have to find the largest product of a continuous sublist from a list of integers which are powers of 2. The idea is to:
Compute the product of every continuous sublist.
Return the biggest of all these products.
You can represent a sublist by its start and end index. For start=0 there are n-1 possible values for end, namely 0..n-1. This generates all sublists that start at index 0. In the next iteration, You increment start by 1 and repeat the process (this time, there are n-2 possible values for end). This way You generate all possible sublists.
Now, for each of these sublists, You have to compute the product of its elements - that is come up with a method computeProduct(List wholeList, int startIndex, int endIndex). You can either use the built in BigInteger class (which should be able to handle the input provided by Your assignment) to save You from further trouble or try to implement a more efficient way of multiplication as described by others. (I would start with the simpler approach since it's easier to see if Your algorithm works correctly and first then try to optimize it.)
Now that You're able to iterate over all sublists and compute the product of their elements, determining the sublist with the maximum product should be the easiest part.
If it's still to hard for You to make the connections between two steps, let us know - but please also provide us with a draft of Your code as You work on the problem so that we don't end up incrementally constructing the solution and You copy&pasting it.
edit: Algorithm skeleton
public BigInteger listingSublist(BigInteger[] biArray)
{
int start = 0;
int end = biArray.length-1;
BigInteger maximum;
for (int i = start; i <= end; i++)
{
for (int j = i; j <= end; j++)
{
//insert logic to determine the maximum product.
computeProduct(biArray, i, j);
}
}
return maximum;
}
public BigInteger computeProduct(BigInteger[] wholeList, int startIndex,
int endIndex)
{
//insert logic here to return
//wholeList[startIndex].multiply(wholeList[startIndex+1]).mul...(
// wholeList[endIndex]);
}
Since k <= 30, any integer i = 2k will fit into a Java int. However the product of such two integers might not necessarily fit into a Java int since 2k * 2k = 22*k <= 260 which fill into a Java long. This should answer Your question regarding the "(multiplication of) two numbers...".
In case that You might want to multiply more than two numbers, which is implied by Your assignment saying "...largest product of a CONTINUOUS SUBLIST..." (a sublist's length could be > 2), have a look at Java's BigInteger class.
Actually, the most efficient way of multiplication is doing addition instead. In this special case all you have is numbers that are powers of two, and you can get the product of a sublist by simply adding the expontents together (and counting the negative numbers in your product, and making it a negative number in case of odd negatives).
Of course, to store the result you may need the BigInteger, if you run out of bits. Or depending on how the output should look like, just say (+/-)2^N, where N is the sum of the exponents.
Parsing the input could be a matter of switch-case, since you only have 30 numbers to take care of. Plus the negatives.
That's the boring part. The interesting part is how you get the sublist that produces the largest number. You can take the dumb approach, by checking every single variation, but that would be an O(N^2) algorithm in the worst case (IIRC). Which is really not very good for longer inputs.
What can you do? I'd probably start from the largest non-negative number in the list as a sublist, and grow the sublist to get as many non-negative numbers in each direction as I can. Then, having all the positives in reach, proceed with pairs of negatives on both sides, eg. only grow if you can grow on both sides of the list. If you cannot grow in both directions, try one direction with two (four, six, etc. so even) consecutive negative numbers. If you cannot grow even in this way, stop.
Well, I don't know if this alogrithm even works, but if it (or something similar) does, its an O(N) algorithm, which means great performance. Lets try it out! :-)
Hmmm.. since they're all powers of 2, you can just add the exponent instead of multiplying the numbers (equivalent to taking the logarithm of the product). For example, 2^3 * 2^7 is 2^(7+3)=2^10.
I'll leave handling the sign as an exercise to the reader.
Regarding the sublist problem, there are less than n^2 pairs of (begin,end) indices. You can check them all, or try a dynamic programming solution.
EDIT: I adjusted the algorithm outline to match the actual pseudo code and put the complexity analysis directly into the answer:
Outline of algorithm
Go seqentially over the sequence and store value and first/last index of the product (positive) since the last 0. Do the same for another product (negative) which only consists of the numbers since the first sign change of the sequence. If you hit a negative sequence element swap the two products (positive and negative) along with the associagted starting indices. Whenever the positive product hits a new maximum store it and the associated start and end indices. After going over the whole sequence the result is stored in the maximum variables.
To avoid overflow calculate in binary logarithms and an additional sign.
Pseudo code
maxProduct = 0
maxProductStartIndex = -1
maxProductEndIndex = -1
sequence.push_front( 0 ) // reuses variable intitialization of the case n == 0
for every index of sequence
n = sequence[index]
if n == 0
posProduct = 0
negProduct = 0
posProductStartIndex = index+1
negProductStartIndex = -1
else
if n < 0
swap( posProduct, negProduct )
swap( posProductStartIndex, negProductStartIndex )
if -1 == posProductStartIndex // start second sequence on sign change
posProductStartIndex = index
end if
n = -n;
end if
logN = log2(n) // as indicated all arithmetic is done on the logarithms
posProduct += logN
if -1 < negProductStartIndex // start the second product as soon as the sign changes first
negProduct += logN
end if
if maxProduct < posProduct // update current best solution
maxProduct = posProduct
maxProductStartIndex = posProductStartIndex
maxProductEndIndex = index
end if
end if
end for
// output solution
print "The maximum product is " 2^maxProduct "."
print "It is reached by multiplying the numbers from sequence index "
print maxProductStartIndex " to sequence index " maxProductEndIndex
Complexity
The algorithm uses a single loop over the sequence so its O(n) times the complexity of the loop body. The most complicated operation of the body is log2. Ergo its O(n) times the complexity of log2. The log2 of a number of bounded size is O(1) so the resulting complexity is O(n) aka linear.
I'd like to combine Amnon's observation about multiplying powers of 2 with one of mine concerning sublists.
Lists are terminated hard by 0's. We can break the problem down into finding the biggest product in each sub-list, and then the maximum of that. (Others have mentioned this).
This is my 3rd revision of this writeup. But 3's the charm...
Approach
Given a list of non-0 numbers, (this is what took a lot of thinking) there are 3 sub-cases:
The list contains an even number of negative numbers (possibly 0). This is the trivial case, the optimum result is the product of all numbers, guaranteed to be positive.
The list contains an odd number of negative numbers, so the product of all numbers would be negative. To change the sign, it becomes necessary to sacrifice a subsequence containing a negative number. Two sub-cases:
a. sacrifice numbers from the left up to and including the leftmost negative; or
b. sacrifice numbers from the right up to and including the rightmost negative.
In either case, return the product of the remaining numbers. Having sacrificed exactly one negative number, the result is certain to be positive. Pick the winner of (a) and (b).
Implementation
The input needs to be split into subsequences delimited by 0. The list can be processed in place if a driver method is built to loop through it and pick out the beginnings and ends of non-0 sequences.
Doing the math in longs would only double the possible range. Converting to log2 makes arithmetic with large products easier. It prevents program failure on large sequences of large numbers. It would alternatively be possible to do all math in Bignums, but that would probably perform poorly.
Finally, the end result, still a log2 number, needs to be converted into printable form. Bignum comes in handy there. There's new BigInteger("2").pow(log); which will raise 2 to the power of log.
Complexity
This algorithm works sequentially through the sub-lists, only processing each one once. Within each sub-list, there's the annoying work of converting the input to log2 and the result back, but the effort is linear in the size of the list. In the worst case, the sum of much of the list is computed twice, but that's also linear complexity.
See this code. Here I implement exact factorial of a huge large number. I am just using integer array to make big numbers. Download the code from Planet Source Code.

Categories

Resources