Find a Number of ways to Generate a Number - java

I have given Fibonacci digits only , i have to find out the numbers of ways to generate a number using K Fibonacci numbers only.
Constraints:
1<=K<=10
1<=N<=10^9
For Example:
N=14 and K=3
There are two ways:
(8,5,1) and (8,3,3)
Here is my recursive solution:
public static void num_gen(int i ,long val ,int used){
if(used==0){
if(val==n) ans++;
return ;
}
if(i==Fib.length) return ;
for(int j=0;j<=used;j++){
long x = j*Fib[i];
if(x+val<=n){
num_gen(i+1,x+val, used-j);
}
}
}
This solution will timeout for large value of N and K=10. Can you provide me algorithm with better complexity.

This can be expressed as multiplying polynomials where exponents are Fibonacci numbers.
Number of factors is K.
The result is a coefficient of the member of the result polynomial whose exponent equals N.
Example:
What is the number of ways to compose number 7 from 3 numbers where each of these 3 numbers can be 1,2 or 3.
(x + x² + x³)³ = x⁹ + 3x⁸ +6x⁷ + 7x⁶ + 6x⁵ + 3x⁴ + x³
Result is 6 since it is the coefficient of the x⁷ member of the result polynomial.

I'd like to give you a solution that works in another language, and I hope that helps you learn in the process of translating it to Java. Because I'm unclear on how to otherwise help you fix the recursive solution you're working on, as I believe that no recursion is required. Also no preset array of Fibonacci numbers is needed.
This is in Perl, it worked for:
$ perl fibber.pl 3 14
8,5,1
8,3,3
2 matches
But I can't guarantee it's perfectly right.
#!/usr/bin/perl
use bigint;
use List::Util qw(sum);
my ($digits, $goal) = #ARGV;
if (!($digits > 0) || !($goal > 0)) {
die "Missing 2 arguments: the number count to sum, the value they sum to.";
}
sub fib {
my ($a, $b) = #_;
return sub {
if (0 == scalar #_) {
(my $r, $a, $b) = ($a, $b, $a+$b);
return $r;
} else {
($a, $b) = #_;
(my $r, $a, $b) = ($b, $a+$b, $a+$b+$b);
return $r;
}
}
}
my #f = (0) x $digits;
#f = map {fib(1,2)} #f;
my #d = map {$_->()} #f;
my $count = 0;
while ($d[0] < $goal) {
if ($goal == sum #d) {
$count++;
print(join(",", #d)."\n");
}
my ($i, $a, $b) = (0, $d[$i], $f[$i]->());
$d[$i] = $b;
while ($goal <= $d[$i]) {
$i++;
if ($i == $digits) {
print "$count matches\n";
exit 0;
}
($a, $b) = ($d[$i], $f[$i]->());
$d[$i] = $b;
}
while ($i > 0) {
$i--;
$d[$i] = $f[$i]->($a, $b);
}
}

Related

How do I count numbers that contain one digit, but not another?

I recently came across an interview question which although had an immediately obvious solution, I struggled to find a more efficient one.
The actual question involved counting numbers from a to b (up to 2^64) which satisfied having either the digit 6 or 8, but not both. They called it a 'lucky number'. So for example:
126 - lucky
88 - lucky
856 - not lucky
The obvious thought was to brute force it by testing each number between a and b as a string, to check for the relevant characters. However, this was prohibitively slow as expected.
A much better solution that I tried, involved first computing all the 'lucky numbers' which had the number of digits between the number of digits that a and b have (by counting possible combinations):
long n = 0;
for (int occurrences = 1; occurrences <= maxDigits; occurrences++) {
n += (long) Math.pow(8, digits - occurrences) * choose(digits, occurrences);
}
return 2 * n;
and then using the brute force method to compute the number of extra lucky numbers that I had counted. So for example, if a = 3 and b = 21, I could count the number of 1 and 2 digit lucky numbers, then subtract the count of those in [1, 3) and (21, 99].
However, although this was a massive improvement, the brute force element still slowed it down way too much for most cases.
I feel like there must be something I am missing, as the rest of the interview questions were relatively simple. Does anyone have any idea of a better solution?
Although I have tagged this question in Java, help in any other languages or pseudocode would be equally appreciated.
I would say you are at the right track. The gut feeling is that dealing with the a and b separately is easier. Making a function count_lucky_numbers_below(n) allows
return count_lucky_numbers_below(b) - count_lucky_numbers_below(a);
The combinatorial approach is definitely a way to go (just keep in mind that the sum is actually equal to 9**n - 8**n, and there is no need to compute the binomial coefficients).
The final trick is to recurse down by a numbeer of digits.
Lets say n is an N-digit number, and the most significant digit is 5. Each set of N-digit numbers starting with a smaller digit contributes S = 9**(N-1) - 8**(N-1) to the total; you immediately have 5*S of lucky numbers. To deal with the remainder, you need to compute the lucky numbers for the N-1-digit tail.
Of course, care must be taken if the most significant digit is above 5. You need to special case it being 6 or 8, but it doesn't seem to be too complicated.
In the end the answer from #user58697 pushed me in the right direction towards finding a solution. With my (albeit extremely primitive) benchmark, it handles 1 to 2^63 - 1 in less than 2 nanoseconds, so it is definitely fast enough. However it is still more verbose than I would have liked, especially given that I was originally expected to write it in half an hour, so I feel like there is still an easier solution that gives comparable performance.
long countLuckyNumbersBetween(long a, long b) {
return countLuckyNumbersBelow(b) - countLuckyNumbersBelow(a - 1);
}
long countLuckyNumbersBelow(long n) {
return countNumbers(n, 6, 8) + countNumbers(n, 8, 6);
}
/**
* Counts the natural numbers in [0, {to}] that have {including} as a digit, but not {excluding}.
* {excluding} should be in (0, 9] or -1 to exclude no digit.
*/
long countNumbers(long to, int including, int excluding) {
if (including == -1) return 0;
if (to < 10) {
if (to >= including) {
return 1;
} else {
return 0;
}
}
int nSignificand = significand(to);
int nDigits = countDigits(to);
long nTail = to % (long) Math.pow(10, nDigits - 1);
// The count of numbers in [0, 10^(nDigits-1)) that include and exclude the relevant digits
long bodyCount;
if (excluding == -1) {
bodyCount = (long) (Math.pow(10, nDigits - 1) - Math.pow(9, nDigits - 1));
} else {
bodyCount = (long) (Math.pow(9, nDigits - 1) - Math.pow(8, nDigits - 1));
}
long count = 0;
for (int i = 0; i < nSignificand; i++) {
if (i == including) {
if (excluding == -1) {
count += Math.pow(10, nDigits - 1);
} else {
count += Math.pow(9, nDigits - 1);
}
} else if (i != excluding) {
count += bodyCount;
}
}
if (nSignificand == including) {
count += 1 + nTail - countNumbers(nTail, excluding, -1);
} else if (nSignificand != excluding) {
count += countNumbers(nTail, including, excluding);
}
return count;
}
int significand(long n) {
while (n > 9) n /= 10;
return (int) n;
}
int countDigits(long n) {
if (n <= 1) {
return 1;
} else {
return (int) (Math.log10(n) + 1);
}
}
Here is another approach:
264 = 18446744073709551616
We can represent the number as a sum of components (one component per every digit position):
18446744073709551616 associated range of numbers
———————————————————— ———————————————————————————————————————————
0xxxxxxxxxxxxxxxxxxx => [00000000000000000000;09999999999999999999]
17xxxxxxxxxxxxxxxxxx => [10000000000000000000;17999999999999999999]
183xxxxxxxxxxxxxxxxx => [18000000000000000000;18399999999999999999]
1843xxxxxxxxxxxxxxxx => [18400000000000000000;18439999999999999999]
18445xxxxxxxxxxxxxxx => [18440000000000000000;18445999999999999999]
...
1844674407370955160x => [18446744073709551600;18446744073709551609]
18446744073709551616 => [18446744073709551610;18446744073709551616]
If we could compute the amount of lucky numbers for every component, then the sum of the amounts for every component will be the total amount for 264.
Note that every component consists of a prefix followed by xs.
Imagine that we know how many lucky numbers there are in an n-digit xx..x (i.e. numbers [0..0 - 9..9]), let's call it N(n).
Now let's look at a component 18445x..x. where 18445 is a prefix and an n-digit xx..x.
In this component we look at all numbers from 18440xx..x to 18445xx..x.
For every item 1844dxx..x we look at the prefix 1844d:
if prefix contains no 6 or 8, then it's the same as x..x without prefix => N(n) special numbers
if prefix contains 6 and no 8, then x..x cannot contain 8 => 9ⁿ special numbers
if prefix contains 8 and no 6, then x..x cannot contain 6 => 9ⁿ special numbers
if prefix contains 6 and 8 => 0 special numbers
Now let's compute N(n) — the amount of lucky numbers in an n-digit xx..x (i.e. in [0..0 - 9..9]).
We can do it iteratively:
n=1: there are only 2 possible numbers: 8 and 6 => N(1)=2.
n=2: there are 2 groups:
8 present: 8x and x8 where x is any digit except 6
6 present: 6x and x6 where x is any digit except 8
=> N(2)=4*9=34.
n=3: let's fix the 1st digit:
0xx — 5xx, 7xx, 9xx => 8 * N(2)
6xx: xx are any 2 digits except 8 => 9²
8xx: xx are any 2 digits except 6 => 9²
=> N(3) = 8*N(2) + 2*9².
n=k+1 => N(k+1) = 7*N(k) + 2*9ᵏ
Here is an implementation (not 100% tested):
public final class Numbers {
public long countLuckyNumbersBelow(BigInteger num) {
if (num.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("num < 0: " + num);
}
var numberText = num.toString();
var result = 0L;
for (var digitPosition = 0; digitPosition < numberText.length(); digitPosition++) {
result += countLuckyNumbersForComponent(numberText, digitPosition);
}
return result;
}
private long countLuckyNumbersForComponent(String numberText, int digitPosition) {
var prefixEndIdx = numberText.length() - 1 - digitPosition;
var prefixHas6s = containsChar(numberText, '6', prefixEndIdx);
var prefixHas8s = containsChar(numberText, '8', prefixEndIdx);
if (prefixHas6s && prefixHas8s) {
return 0;
}
var result = 0L;
for (var c = numberText.charAt(prefixEndIdx) - 1; c >= '0'; c--) {
var compNo6s = (!prefixHas6s) && (c != '6');
var compNo8s = (!prefixHas8s) && (c != '8');
if (compNo6s && compNo8s) {
result += countLuckyNumbers(digitPosition);
} else if (compNo6s || compNo8s) {
result += power9(digitPosition);
}
}
return result;
}
private static boolean containsChar(String text, char c, int endIdx) {
var idx = text.indexOf(c);
return (idx > 0) && (idx < endIdx);
}
private long[] countLuckyNumbersCache = {0L, 0L};
/**
* Computes how many lucky numbers are in an n-digit `xx..x`
*/
private long countLuckyNumbers(int numDigits) {
if (countLuckyNumbersCache[0] == numDigits) {
return countLuckyNumbersCache[1];
}
long N;
if (numDigits <= 1) {
N = (numDigits == 1) ? 2 : 0;
} else {
var prevN = countLuckyNumbers(numDigits - 1);
N = (8 * prevN) + (2 * power9(numDigits-1));
}
countLuckyNumbersCache[0] = numDigits;
countLuckyNumbersCache[1] = N;
return N;
}
private long[] power9Cache = {0L, 1L};
/**
* Computes 9<sup>power</sup>
*/
private long power9(int power) {
if (power9Cache[0] == power) {
return power9Cache[1];
}
long res = 1;
var p = power;
if (power > power9Cache[0]) {
p -= power9Cache[0];
res = power9Cache[1];
}
for (; p > 0; p--) {
res *= 9;
}
power9Cache[0] = power;
power9Cache[1] = res;
return res;
}
}
BTW it took me half a day, and I have no idea how is that possible to complete it in 30 minutes.
I guess your interviewers expected from you to demonstrate them your thought process.
Here is the result of my attempt.
First, let me explain a little bit what logic I used.
I used formula S = 9N — 8N (mentioned in the user58697's answer) to compute how many of N-digit numbers are lucky.
How to get this formula:
for N-digit numbers there are 10N numbers in total: N digits, each can take one of 10 values: [0-9].
if we only count numbers without 6, then each digit can only take one of 9 values [0-5,7-9] — it's 9N numbers in total
now we also want only numbers with 8.
We can easily compute how many numbers don't have both 6 and 8: digits in these numbers can only take one of 8 values [0-5,7,9] — it's 8N numbers in total.
As a result, there are S = 9N — 8N numbers which have 8 and no 6.
For numbers with 6 and without 8 the formula is the same.
Also numbers without 6 do not intersect with numbers without 8 — so we can just sum them.
And finally, since we know how to count lucky numbers for intervals [0;10N], we need to split the interval [0; our arbitrary number] into suitable sub-intervals.
For instance, we can split number 9845637 this way:
Sub-interval
Prefix
Digit
N-digit interval
0000000 - 8999999
0 - 8
000000 - 999999
9000000 - 9799999
9
0 - 7
00000 - 99999
9800000 - 9839999
98
0 - 3
0000 - 9999
9840000 - 9844999
984
0 - 4
000 - 999
9845000 - 9845599
9845
0 - 5
00 - 99
9845600 - 9845629
98456
0 - 2
0 - 9
9845630 - 9845637
Now we can compute the number for every sub-interval (just keep attention to digits in prefix — they might contains 8 or 6) and then just sum those numbers to get the final result.
Here is the code:
// Special value for 'requiredDigit': no required digit
private static char NIL = Character.MAX_VALUE;
public static long countLuckyNumbersUpTo(BigInteger number) {
if (number.compareTo(BigInteger.ZERO) < 0) {
throw new IllegalArgumentException("number < 0: " + number);
}
var numberAsDigits = number.toString();
return countNumbersUpTo(numberAsDigits, '6', '8') + countNumbersUpTo(numberAsDigits, '8', '6');
}
// count all numbers in [0;'numberAsDigits'] which have 'requiredDigit' and no 'excludeDigit'
private static long countNumbersUpTo(String numberAsDigits, char requiredDigit, char excludeDigit) {
var highDigit = numberAsDigits.charAt(0);
if (numberAsDigits.length() == 1) {
return (requiredDigit != NIL)
? ((highDigit >= requiredDigit) ? 1 : 0)
: numDigitsInInterval('0', highDigit, excludeDigit);
}
var tailDigits = numberAsDigits.substring(1);
var result = 0L;
// numbers where the highest digit is in [0;`highDigit`)
var numGoodDigits = numDigitsInInterval('0', (char) (highDigit - 1), excludeDigit);
var containsRequiredDigit = (requiredDigit != NIL) && (highDigit > requiredDigit);
if (containsRequiredDigit) {
result += totalNumbers(tailDigits.length(), NIL);
numGoodDigits--;
}
if (numGoodDigits > 0) {
result += numGoodDigits * totalNumbers(tailDigits.length(), requiredDigit);
}
// remaining numbers where the highest digit is `highDigit`
if (highDigit != excludeDigit) {
var newRequiredDigit = (highDigit == requiredDigit) ? NIL : requiredDigit;
result += countNumbersUpTo(tailDigits, newRequiredDigit, excludeDigit);
}
return result;
}
private static int numDigitsInInterval(char firstDigit, char lastDigit, char excludeDigit) {
var totalDigits = lastDigit - firstDigit + 1;
return (excludeDigit <= lastDigit) ? (totalDigits - 1) : totalDigits;
}
// total numbers with given requiredDigit in [0;10^numDigits)
private static long totalNumbers(int numDigits, char requiredDigit) {
return (requiredDigit == NIL) ? pow(9, numDigits) : (pow(9, numDigits) - pow(8, numDigits));
}
private static long pow(int base, int exponent) {
return BigInteger.valueOf(base).pow(exponent).longValueExact();
}

Find maximum product using recursion

There's a question I saw and I'm wondering if it's possible to solve it using recursion. It goes as follow:
Write an algorithm that, when given an array of input, finds the maximum product from those inputs. For example:
Input: [1, 2, 3]
Output: 6 (1*2*3)
Input: [-1, 1, 2, 3]
Output: 6 (1*2*3)
Input: [-2, -1, 1, 2, 3]
Output: 12 (-2*-1*1*2*3)
I'm trying to find a way of using recursion to solve it, but the algorithm I tried doesn't work. My algorithm, written in Java is as follow
Integer[] array;
public int maximumProduct(int[] nums) {
array=new Integer[nums.length];
return multiply(nums, 0);
}
public int multiply(int[] nums, int i){
if (array[i]!=null){
return array[i];
}
if (i==(nums.length-1)){
return nums[i];
}
int returnval=Math.max(nums[i]*multiply(nums, i+1), multiply(nums, i+1));
array[i]=returnval;
return returnval;
}
The problem with this algorithm is that it doesn't work well if there's an even number of negative numbers. For example, if nums[0]=-2, nums[1]=-1 and nums[2]=1, then multiply(nums, 1) will always return 1 instead of -1, and thus it will always see 1 as bigger than 1*-2 at multiply(nums, 0). I'm not sure how to solve this problem, however. Is there any way of solving this using recursion or dynamic programming?
If there is only one non-zero element in the array, and it happens to be a negative number, then then answer is either 0, if there is a 0 present in the input, or if the array contains only that single negative element, the answer is that element itself.
In all other cases, the final answer is going to be positive.
We first make a linear scan to find the number of negative integers. If this number is even, then the answer is the product of all the non-zero elements. If there are an odd number of negative elements, we need to leave out one negative element from the answer, so that the answer is positive. As we want the maximum possible answer, the number we want to leave out should have as small an absolute value as possible. So among all the negative numbers, find the one with the minimum absolute value, and find the product of the remaining non-zero elements, which should be the answer.
All this requires only two linear scans of the array, and hence runs in O(n) time.
What is the maximum product of integers?
To obtain the maximum sum, you will want to multiply all the positive integers with the product of the largest negative integers, with the number of negative integers included in the product being even to obtain a positive final result.
In an algorithm for a single traversal
I am going to treat the positive integers and the negative integers in the input separately. You will want to keep a running product of positive integers, a running product of negative integers and the largest negative integer (ie. the negative integer with the smallest absolute value) found so far.
Let us ignore the edge cases where the final answer is <= 0. That can be handled easily.
//Initialization
int [] nums // Input
int posProduct = 1;
int negProduct = 1;
int smallestNeg = 1;
//Input Traversal
for (int i : nums) {
if ( i == 0 ) {
// ignore
} else if ( i < 0 ) {
if (smallestNeg == 1) {
smallestNeg = i;
} else if ( i > smallestNeg ) {
negProduct *= smallestNeg; //Integrate the old smallest into the running product
smallestNeg = i; // i is the new smallest
} else {
negProduct *= i;
}
} else {
// i is strictly positive
posProduct *= i;
}
}
//Result Computation
int result = posProduct;
if ( negProduct < 0 ) {
// The running product of negative number numbers is negative
// We use the smallestNeg to turn it back up to a positive product
result *= smallestNeg;
result *= negProduct;
} else {
result *= negProduct
}
edit: In a recursive traversal
I personally find that writing the array traversal in a recursive manner to be clumsy but it can be done.
For the beauty of the exercise and to actually answer the question of the OP, here is how I would do it.
public class RecursiveSolver {
public static int findMaxProduct (int [] nums) {
return recursiveArrayTraversal(1, 1, 1, nums, 0);
}
private static int recursiveArrayTraversal(int posProduct, int negProduct,
int smallestNeg, int [] nums, int index) {
if (index == nums.length) {
// End of the recursion, we traversed the whole array
posProduct *= negProduct;
if (posProduct < 0) {
posProduct *= smallestNeg;
}
return posProduct;
}
// Processing the "index" element of the array
int i = nums[index];
if ( i == 0 ) {
// ignore
} else if ( i < 0 ) {
if (smallestNeg == 1) {
smallestNeg = i;
} else if ( i > smallestNeg ) {
negProduct *= smallestNeg;
smallestNeg = i;
} else {
negProduct *= i;
}
} else {
// i is strictly positive
posProduct *= i;
}
//Recursive call here!
//Notice the index+1 for the index parameter which carries the progress
//in the array traversal
return recursiveArrayTraversal(posProduct, negProduct,
smallestNeg, nums, index+1);
}
}
First, break the array in subproblems always you find a 0 in the list:
1 -2 4 -1 8 0 4 1 0 -3 -4 0 1 3 -5
|_____________| |____| |____| |_______|
p1 p2 p3 p4
Then, for each problem pi, count how many negative numbers are there.
If pi has an even number of negatives (or no negatives at all), the answer of pi is the product of all its elements.
If pi has only 1 negative number (say n), the answer will be the maximum between the product of all the elements in n's right and the product of all elements in n's left.
If pi has an odd number (bigger than only 1) of negative numbers, call the index of the leftmost negative number l and the index of the rightmost negative number r. Supposing pi has n elements, the answer will be:
max(
pi[ 0 ] * pi[ 1 ] * ... * pi[r - 1],
pi[l + 1] * pi[l + 2] * ... * pi[ n ]
)
Knowing that, it's easy to write a recursion for each step of the solution of this problem: a recursion to divide problems at zeros, another to count negatives and another to find answers, in O(n).
Linear version
List<Integer> vals = new ArrayList<>(List.of(5,1,-2,1,2,3,-4,-1));
int prod = 0;
int min = 1;
for (int v : vals) {
if (v == 0) {
// ignore zero values
continue;
}
if (prod == 0) {
prod = 1;
}
prod *= v;
// compute min to be the largest negative value in the list.
if (v < 0 && min < Math.abs(v)) {
min = v;
}
}
if (prod < 0) {
prod /= min;
}
System.out.println("Maximum product = " + prod);
}
Recursive version
int prod = prod(vals, new int[] {0} , vals.size());
System.out.println("Maximum product = " + prod);
public static int prod(List<Integer> vals, int[]min, int size) {
int prod = 0;
if(vals.size() > 0) {
int t = vals.get(0);
if (t < 0 && min[0] < Math.abs(t)) {
min[0] = t;
}
prod = prod(vals.subList(1,vals.size()), min, vals.size());
}
if (vals.isEmpty() || vals.get(0) == 0) {
return prod;
}
if (prod == 0) {
prod = 1;
}
prod *= t;
if (vals.size() == size && prod < 0) {
prod/=min[0];
}
return prod;
}
This is my solution - leaving it open for optimization and to figure out the runtime. This is a general purpose solution that finds the products of all the combinations of integers in a list. Of course, there is a O(n) solution but I present this solution as well.
import java.util.ArrayList;
import java.util.List;
public class MaxProd {
int[] input = {1, 2, 3};
// int[] input = {-2, -1, 1, 2, 3};
public static void main(String[] args) {
MaxProd m = new MaxProd();
List<Integer> ll = m.max(0);
for (int i : ll) {
System.out.println(i);
}
ll.sort((x,y) -> Integer.compare(x, y));
System.out.println("The max: " + ll.get(ll.size() -1 ));
}
private List<Integer> max(int index) {
if (index < input.length){
List<Integer> l = new ArrayList<>();
List<Integer> retList = max(index + 1);
for (int j : retList){
l.add(input[index] * j);
}
l.add(input[index]);
l.addAll(retList);
return l;
}
else return new ArrayList<>();
}
}
it prints:
6
2
3
1
6
2
3
The max: 6
If the requirements are constrained (as in this case) then one can get by without the need for generating all combinations resulting in a linear solution. Also, I'm sorting at the end. Note: you could easily get the result with a single pass on the returned list to find the maximum product as specified in other answers.

Find max rating(number) in an array where we cannot skip over 1 or more consecutive number in array

we have an array of ratings, we have to find the max rating in such a away that we cannot skip 1 or more consecutive rating in an arrray
Example-1: {9,-1,-3,-4,-5} output = 9 + -1 + -4 = 4
Explanation: I took 9 the we have to took -1 or -3 we cannot jump to -4 directly as we cannot skip 1 or more consecutive number.
Example-2: {-1,-2,-3,-4,-5} output = -2 + -4 = -6
Example-3: {-3,2,-4,-1,-2,5} output = 2 + -1 + 5 = 6
Example-4: {9,-1,-3,4,5} output = 9 + -1 + 4 + 5 = 17
I tried below code but it is working in case of example: 2,3,4 but not for example 1 similarly failing for other scenario.
static int maximizeRatings(int[] ratings) {
int current = 0;
boolean result = false;
for(int j=0; j<ratings.length;j++){
if(ratings[j]<0){
result = true;
}else{
result = false;
}
}
if(result){
return allnegatine(ratings);
}
for(int i=0; i<ratings.length;i++){
if(i == ratings.length-1){
if(ratings[i] > 0)
current += ratings[i];
}else{
if(ratings[i] >0 && ratings[i+1]>0){
current = ratings[i]+ratings[i+1];
i++;
}
if(ratings[i] > ratings[i+1]){
current += ratings[i];
}else{
current += ratings[i+1];
i++;
}
}
}
return current;
}
private static int allnegatine(int[] ratings) {
int current =0;
for(int i=0; i<ratings.length;i++){
if(ratings.length%2==0){
if(i%2 == 0)
current += ratings[i];
}else{
if(i%2!=0)
current += ratings[i];
}
}
return current;
}
not getting excepted out for some scenarios like example 1 I am getting -6 instead of 4, I am trying to get proper code which will pass all scenarios. Thank you
This is a dynamic programming problem.
Let dp[i] be the max ratings which can be achieved considering only the part of the array that starts at zero, ends at i, and includes ratings[i].
dp[0]=ratings[0]
dp[1]=max(ratings[1],ratings[0]+ratings[1])
dp[i]=max(dp[i-1],dp[i-2])+ratings[i]
Answer: max(dp[n-1],dp[n-2]) where n is the size of the ratings array.
Also you can chose to do away with dp array and maintain 2 variables for dp[i-1] and dp[i-2].
this is typical recursion problem (as long as the input array is reasonably long). You should go thru items and try all possible combinations and then pick the best one.
Because it looks like typical school work I am not sure if I should paste my solution. You should figure it out yourself or at least understand what's going on to be able to implement it yourself next time.
public class RatingService {
public int calculate(List<Integer> input) {
return recursion(input, true, 0);
}
private int recursion(List<Integer> sublist, boolean canSkip, int sum) {
if (sublist.isEmpty()) {
return sum;
}
int skippedSum = Integer.MIN_VALUE;
int notSkippedSum;
Integer integer = sublist.get(0);
if (canSkip) {
skippedSum = recursion(sublist.subList(1, sublist.size()), false, sum);
}
notSkippedSum = recursion(sublist.subList(1, sublist.size()), true, integer + sum);
return skippedSum > notSkippedSum ? skippedSum : notSkippedSum;
}
}
I think you are doing the mistake while checking for all negative numbers in for loop. If the last element in the array is negative then the 'result' variable will be true means that all array is negative but actually its not.
You have to replace the for loop by :
for(int j=0;j<ratings.length;j++){
if(ratings[j]<0){
result=true;
}
else{
result = false;
break;
}
}
It will break the for loop at the index where it founds any positive number i-e: all elements of array are not negative.

All combinations of 1 + 2 that adds to n

I am trying to solve this question as the preparation for a programming interview:
A frog only moves forward, but it can move in steps 1 inch long or in jumps 2 inches long. A frog can cover the same distance using different combinations of steps and jumps.
Write a function that calculates the number of different combinations a frog can use to cover a given distance.
For example, a distance of 3 inches can be covered in three ways: step-step-step, step-jump, and jump-step.
I think there is a quite simple solution to this, but I just can't seem to find it. I would like to use recursion, but I can't see how. Here is what I have so far:
public class Frog {
static int combinations = 0;
static int step = 1;
static int jump = 2;
static int[] arr = {step, jump};
public static int numberOfWays(int n) {
for (int i = 0; i < arr.length; i++) {
int sum = 0;
sum += arr[i];
System.out.println("SUM outer loop: " + sum + " : " + arr[i]);
while (sum != 3) {
for (int j = 0; j < arr.length; j++) {
if (sum + arr[j] <= 3) {
sum += arr[j];
System.out.println("SUM inner loop: " + sum + " : " + arr[j]);
if (sum == 3) {
combinations++;
System.out.println("Combinations " + combinations);
}
}
}
}
}
return combinations;
}
public static void main(String[] args) {
System.out.println(numberOfWays(3));
}
}
It doesn't find all combinations, and I think the code is quite bad. Anyone have a good solution to this question?
Think you have an oracle that knows how to solve the problem for "smaller problems", you just need to feed it with smaller problems. This is the recursive method.
In your case, you solve foo(n), by splitting the possible moves the frog can do in the last step, and summing them):
foo(n) = foo(n-1) + foo(n-2)
^ ^
1 step 2 steps
In addition, you need a stop clause of foo(0) = 1, foo(1)=1 (one way to move 0 or 1 inches).
Is this recursive formula looks familiar? Can you solve it better than the naive recursive solution?
Spoiler:
Fibonacci Sequence
Here's a simple pseudo-code implementation that should work:
var results = []
function plan(previous, n){
if (n==0) {
results.push(previous)
} else if (n > 0){
plan(previous + ' step', n-1)
plan(previous + ' hop', n-2)
}
}
plan('', 5)
If you want to improve the efficiency of an algorithm like this you could look into using memoization
Here's a combinatoric way: think of n as 1 + 1 + 1 ... = n. Now bunch the 1's in pairs, gradually increasing the number of bunched 1's, summing the possibilities to arrange them.
For example, consider 5 as 1 1 1 1 1:
one bunch => (1) (1) (1) (11) => 4 choose 1 possibilities to arrange one 2 with three 1's
two bunches => (1) (11) (11) => 3 choose 2 possibilities to arrange two 2's with one 1
etc.
This seems directly related to Wikipedia's description of Fibonacci numbers' "Use in Mathematics," for example, in counting "the number of compositions of 1s and 2s that sum to a given total n" (http://en.wikipedia.org/wiki/Fibonacci_number).
This logic is working fine. (Recursion)
public static int numberOfWays(int n) {
if (n== 1) {
return 1; // step
} else if (n== 2) {
return 2; // (step + step) or jump
} else {
return numberOfWays(n- 1)
+ numberOfWays(n- 2);
}
}
The accepted answer fails performance test for larger sets. Here is a version with for loop that satisfies performance tests at testdome.
using System;
public class Frog
{
public static int NumberOfWays (int n)
{
int first = 0, second = 1;
for ( int i = 0; i<n; i++ )
{
int at = first;
first = second;
second = at + second;
}
return second;
}
public static void Main (String[] args)
{
Console.WriteLine (NumberOfWays (3));
}
}
C++ code works fine.
static int numberOfWays(int n)
{
if (n == 1) return 1;
else if (n == 2) return 2;
else
{
static std::unordered_map<int,int> m;
auto i = m.find(n);
if (i != m.end())
return i->second;
int x = numberOfWays(n - 1) + numberOfWays(n - 2);
m[n] = x;
return x;
}
}

Building a math game in Java

I am building a math game for java and I'm stuck at this part as per the details of my assignment. The rules are simple: you have to use each number only once and only the 4 numbers that were read from the user to find one equation to obtain 24.
For example, for the numbers 4,7,8,8, a possible solution is: (7-(8/8))*4=24.
Most sets of 4 digits can be used in multiple equations that result in 24. For example the input 2,2,4,7 can be used in multiple ways to obtain 24:
2+2*(4+7) = 24
2+2*(7+4) = 24
(2+2)*7-4 = 24
(2*2)*7-4 = 24
2*(2*7)-4 = 24
There are also combinations of 4 numbers that cannot result into any equation equal with 24. For example 1,1,1,1. In this case, your program should return that there is no possible equation equal with 24.
Note: Although we will enter 4 integers between 1 and 9, we will use doubles to compute all the operations. For example, the numbers 3,3,8,8 can be combined into the formula: 8/(3-8/3) = 24.
Workflow: Your program should read the 4 numbers from the user and output a formula that results in 24. The algorithm should enumerate all the possible orders of 4 numbers, all the possible combinations and all the possible formulas.
Which leads me to 24 permutations of Numbers a,b,c,d and 64 permutations of operators +-/*. How I came to this conclusion was 4^3 4 operators only 3 fill spots in the equation. Except today I am having trouble writing the evaluation method and also accounting for parentases in the equations.
Here is my code:
public static void evaluate(cbar [][] operations , double [][] operands)
{
/*
This is the part that gets me how am I supposed to account
for parentases and bring all these expressions togather to
actually form and equation.
*/
}
This problem presents several challenges. My solution below is about two hundred lines long. It's probably a little longer than the assignment requires because I generalized it to any number of terms. I encourage you to study the algorithm and write your own solution.
The main obstacles we must overcome are the following.
How do we generate permutations without repetition?
How do we build and evaluate arithmetic expressions?
How do we convert the expressions into unique strings?
There are many ways to generate permutations. I chose a recursive approach because it's easy to understand. The main complication is that terms can be repeated, which means that there may be fewer than 4! = 4*3*2*1 permutations. For example, if the terms are 1 1 1 2, there are only four permutations.
To avoid duplicating permutations, we start by sorting the terms. The recursive function finds places for all duplicate terms from left to right without backtracking. For example, once the first 1 has been placed in the array, all the remaining 1 terms are placed to the right of it. But when we get to a 2 term, we can go back to the beginning of the array.
To build arithmetic expressions, we use another recursive function. This function looks at each position between two terms of the permutation, splitting the array into a segment to the left of the position and a segment to the right. It makes a pair of recursive calls to build expressions for the left and right segments. Finally, it joins the resulting child expressions with each of the four arithmetic operators. The base case is when the array is of size one, so it can't be split. This results in a node with no operator and no children, only a value.
Evaluating the expressions by performing arithmetic on double values would be problematic due to the imprecision of floating-point division. For example, 1.0 / 3 = 0.33333..., but 3 * 0.33333... = 0.99999.... This makes it difficult to know for sure that 1 / 3 * 3 = 1 when you're using double values. To avoid these difficulties, I defined a Fraction class. It performs arithmetic operations on fractions and always simplifies the result by means of the greatest common divisor. Division by zero does not result in an error message. Instead, we store the fraction 0/0.
The final piece of the puzzle is converting expressions into strings. We want to make canonical or normalized strings so that we don't repeat ourselves needlessly. For example, we don't want to display 1 + (1 + (1 + 2)) and ((1 + 1) + 1) + 2, since these are essentially the same expression. Instead of showing all possible parenthesizations, we just want to display 1 + 1 + 1 + 2.
We can achieve this by adding parentheses only when necessary. To wit, parentheses are necessary if a node with a higher-priority operator (multiplication or division) is the parent of a node with a lower-priority operator (addition or subtraction). By priority I mean operator precedence, also known as the order of operations. The higher-priority operators bind more tightly than the lower ones. So if a parent node has higher priority than the operator of a child node, it is necessary to parenthesize the child. To ensure that we end up with unique strings, we check them against a hash set before adding them to the result list.
The following program, Equation.java, accepts user input on the command line. The parameters of the game are on the first line of the Equation class. You can modify these to build expressions with more terms, bigger terms, and different target values.
import java.lang.*;
import java.util.*;
import java.io.*;
class Fraction { // Avoids floating-point trouble.
int num, denom;
static int gcd(int a, int b) { // Greatest common divisor.
while (b != 0) {
int t = b;
b = a % b;
a = t;
}
return a;
}
Fraction(int num, int denom) { // Makes a simplified fraction.
if (denom == 0) { // Division by zero results in
this.num = this.denom = 0; // the fraction 0/0. We do not
} else { // throw an error.
int x = Fraction.gcd(num, denom);
this.num = num / x;
this.denom = denom / x;
}
}
Fraction plus(Fraction other) {
return new Fraction(this.num * other.denom + other.num * this.denom,
this.denom * other.denom);
}
Fraction minus(Fraction other) {
return this.plus(new Fraction(-other.num, other.denom));
}
Fraction times(Fraction other) {
return new Fraction(this.num * other.num, this.denom * other.denom);
}
Fraction divide(Fraction other) {
return new Fraction(this.num * other.denom, this.denom * other.num);
}
public String toString() { // Omits the denominator if possible.
if (denom == 1) {
return ""+num;
}
return num+"/"+denom;
}
}
class Expression { // A tree node containing a value and
Fraction value; // optionally an operator and its
String operator; // operands.
Expression left, right;
static int level(String operator) {
if (operator.compareTo("+") == 0 || operator.compareTo("-") == 0) {
return 0; // Returns the priority of evaluation,
} // also known as operator precedence
return 1; // or the order of operations.
}
Expression(int x) { // Simplest case: a whole number.
value = new Fraction(x, 1);
}
Expression(Expression left, String operator, Expression right) {
if (operator == "+") {
value = left.value.plus(right.value);
} else if (operator == "-") {
value = left.value.minus(right.value);
} else if (operator == "*") {
value = left.value.times(right.value);
} else if (operator == "/") {
value = left.value.divide(right.value);
}
this.operator = operator;
this.left = left;
this.right = right;
}
public String toString() { // Returns a normalized expression,
if (operator == null) { // inserting parentheses only where
return value.toString(); // necessary to avoid ambiguity.
}
int level = Expression.level(operator);
String a = left.toString(), aOp = left.operator,
b = right.toString(), bOp = right.operator;
if (aOp != null && Expression.level(aOp) < level) {
a = "("+a+")"; // Parenthesize the child only if its
} // priority is lower than the parent's.
if (bOp != null && Expression.level(bOp) < level) {
b = "("+b+")";
}
return a + " " + operator + " " + b;
}
}
public class Equation {
// These are the parameters of the game.
static int need = 4, min = 1, max = 9, target = 24;
int[] terms, permutation;
boolean[] used;
ArrayList<String> wins = new ArrayList<String>();
Set<String> winSet = new HashSet<String>();
String[] operators = {"+", "-", "*", "/"};
// Recursively break up the terms into left and right
// portions, joining them with one of the four operators.
ArrayList<Expression> make(int left, int right) {
ArrayList<Expression> result = new ArrayList<Expression>();
if (left+1 == right) {
result.add(new Expression(permutation[left]));
} else {
for (int i = left+1; i < right; ++i) {
ArrayList<Expression> leftSide = make(left, i);
ArrayList<Expression> rightSide = make(i, right);
for (int j = 0; j < leftSide.size(); ++j) {
for (int k = 0; k < rightSide.size(); ++k) {
for (int p = 0; p < operators.length; ++p) {
result.add(new Expression(leftSide.get(j),
operators[p],
rightSide.get(k)));
}
}
}
}
}
return result;
}
// Given a permutation of terms, form all possible arithmetic
// expressions. Inspect the results and save those that
// have the target value.
void formulate() {
ArrayList<Expression> expressions = make(0, terms.length);
for (int i = 0; i < expressions.size(); ++i) {
Expression expression = expressions.get(i);
Fraction value = expression.value;
if (value.num == target && value.denom == 1) {
String s = expressions.get(i).toString();
if (!winSet.contains(s)) {// Check to see if an expression
wins.add(s); // with the same normalized string
winSet.add(s); // representation was saved earlier.
}
}
}
}
// Permutes terms without duplication. Requires the terms to
// be sorted. Notice how we check the next term to see if
// it's the same. If it is, we don't return to the beginning
// of the array.
void permute(int termIx, int pos) {
if (pos == terms.length) {
return;
}
if (!used[pos]) {
permutation[pos] = terms[termIx];
if (termIx+1 == terms.length) {
formulate();
} else {
used[pos] = true;
if (terms[termIx+1] == terms[termIx]) {
permute(termIx+1, pos+1);
} else {
permute(termIx+1, 0);
}
used[pos] = false;
}
}
permute(termIx, pos+1);
}
// Start the permutation process, count the end results, display them.
void solve(int[] terms) {
this.terms = terms; // We must sort the terms in order for
Arrays.sort(terms); // the permute() function to work.
permutation = new int[terms.length];
used = new boolean[terms.length];
permute(0, 0);
if (wins.size() == 0) {
System.out.println("There are no feasible expressions.");
} else if (wins.size() == 1) {
System.out.println("There is one feasible expression:");
} else {
System.out.println("There are "+wins.size()+" feasible expressions:");
}
for (int i = 0; i < wins.size(); ++i) {
System.out.println(wins.get(i) + " = " + target);
}
}
// Get user input from the command line and check its validity.
public static void main(String[] args) {
if (args.length != need) {
System.out.println("must specify "+need+" digits");
return;
}
int digits[] = new int[need];
for (int i = 0; i < need; ++i) {
try {
digits[i] = Integer.parseInt(args[i]);
} catch (NumberFormatException e) {
System.out.println("\""+args[i]+"\" is not an integer");
return;
}
if (digits[i] < min || digits[i] > max) {
System.out.println(digits[i]+" is outside the range ["+
min+", "+max+"]");
return;
}
}
(new Equation()).solve(digits);
}
}
I would recommend you to use a tree structure to store the equation, i.e. a syntactic tree in which the root represents and operator having two children representing the operands and so on recursively. You would probably get a cleaner code doing it like that, because then you won't need to generate the combinations of operands "by hand", but you can make a code which picks every operand from a 1-dimensional char[] operands = new char[] {'+','-','*','/'} array.
If you don't want to use a syntactic tree or think it's not necessary for your use case you can always try to find a different way to make the code to pick operands from the 1-dimensional array and store them into a different data structure. But I would especially avoid writing all the combinations as you are doing. It does not look very easy to maintain.
I have fixed the similar puzzle with below code.
public static boolean game24Points(int[] operands) {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName("javascript");
char[] operations = new char[] { '+', '-', '*', '/' };
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
try {
String exp = "" + operands[0] + operations[i] + operands[1] + operations[j]
+ operands[2] + operations[k] + operands[3];
String res = engine.eval(exp).toString();
if (Double.valueOf(res).intValue() == 24) {
System.out.println(exp);
return true;
}
} catch (ScriptException e) {
return false;
}
}
}
}
return false;
}
Here are testcases
public void testCase01() {
int[] operands = { 7, 2, 1, 10 };
assertEquals(true, Demo.game24Points(operands));
}
public void testCase02() {
int[] operands = { 1, 2, 3, 4 };
assertEquals(true, Demo.game24Points(operands));
}
public void testCase03() {
int[] operands1 = { 5, 7, 12, 12 };
assertEquals(true, Demo.game24Points(operands1));
int[] operands = { 10, 3, 3, 23 };
assertEquals(true, Demo.game24Points(operands));
}

Categories