I need to implement a function which decomposes a value into powers of two using java.
e.g: 14= 8 + 4 + 2
I need to find the powers of two which the value gets decomposed. For the above example I need 2,3,1 as outputs. How could I implement that?
Take advantage of the binary representation that Java uses. I don't know what form you want the powers of 2 to take, but you can loop through the bits one at a time by shifting and bit-wise & with 1 to test each bit. Each 1 bit represents a power of 2 in the sum.
For instance:
List<Integer> powers = new ArrayList<Integer>();
n = . . .; // something > 0
int power = 0;
while (n != 0) {
if ((n & 1) != 0) {
powers.add(1 << power);
// or, if you just need the exponents:
// powers.add(power);
}
++power;
n >>>= 1;
}
As integers are already represented as powers of two and Java has a collections for a set of bits I would use these two.
public static void main(String[] args) {
System.out.println(bitsSet(14));
}
public static BitSet bitsSet(long num) {
BitSet bitSet = new BitSet();
for (int i = 0; i < 64; i++)
if (((num >>> i) & 1) != 0)
bitSet.set(i);
return bitSet;
}
prints
{1, 2, 3}
For this, you usually use bit-wise operations, namely the shift (<<,>>,>>>) and the bit-wise and (&) operator, because the internal representation of integers in computers already is binary, which is what you need.
In binary representation each integer value is a composition of powers of 2: 1, 2, 4, 8, 16, 32, ...
So, 14 in decimal is in binary 1110: 8 + 4 + 2 + 0.
If you're after some nice, generic algorithm, you may want to start decomposing decimal numbers into their powers of 10 and from there on extend your solution to other bases, like 2.
You could simply subtract 2 from the value and keep subtracting subsequent higher powers.
int x = 0;
int value = args[0];
for (i=0, (value - Math.pow(2, i)) >= 0, i++) {
value = value - Math.pow(2, i);
x++;
}
for (i=0, i<x, i++) {
System.out.println("addent: " + Math.pow(2, i);
}
Related
Can somebody help me with this problem?
Statement: - What is the maximum possible n digit number starting from 0 we can make in K steps
using only 2 operations:-
multiplying by 3 or incrementing by 2.
EXAMPLE :
N =2 K = 5;
-> (0->2->6->8->24->72) 72 IS THE ANSWER
N = 2 , K = 51 -> (0->2->6->8->10->30->32->96->98). 98 is the maximum we can get so need to check for rest of the moves.
My 2 state-recursive solution:-
public static void largestNDigitNumber(long[] highest, long maxValue, long k, long currentValue) {
if (highest[0] == (maxValue - 2)) return; //no need to do anything as we get 98 as highest.
if (k < 0) return; //checking for steps
if (highest[0] < currentValue && currentValue <= (maxValue - 2)) {
highest[0] = currentValue;
}
largestNDigitNumber(highest, maxValue, (k - 1), (currentValue * 3));
largestNDigitNumber(highest, maxValue, (k - 1), (currentValue + 2));
}
public static void main(String[] args) {
int n = 2;
long k = 51;
long maxValue = (long) Math.pow(10, n);
long[] highest = new long[1];
largestNDigitNumber(highest, maxValue, (k - 1), 2);
if (highest[0] < (long) Math.pow(10, (n - 1))) {
System.out.println("-1"); // if it is not possible to make n digit in given steps
} else System.out.println(highest[0]);
}
when "k" is small it is giving the correct answer but for bigger values of "k", it does not show any input. for n=2 and k = 51, it does not show anything.
please help me to improve this code
The question is equivalent to asking what is the largest base 3 number that is less than 10^n/2, and has digit sum plus length less than or equal to k+1. (The answer is then double the base 3 number).
For example, N=2 K=5. What's the largest base 3 number that's less than 50, with length plus digit sum less than or equal to 6. Answer: 1100 (36 decimal), so the answer to the original question is 36*2=72.
For N=2, K=51, the largest base-3 number that's less than 50 is 2001 (49 decimal) and has length sum plus digit sum = 7, which is way less than K+1.
Given this representation, it's easy to solve the problem in O(n) time (in fact, you can solve it using pencil and paper). The length d of the base-3 number is as large as possible such that 3^d < 10^n/2 and d<=K. Then fill in the digits of the number greedily from the most-significant first until you have digit sum K+1-d (or you run out of digits).
Equivalence
First note that without loss of generality you can assume you never have three +2 operations in a row, since that can be done more efficiently by inserting a single +2 operation to before the most recent *3 (or simply replacing it by +2 * 3 if there's no *3 operation). Suppose you have represented the current number as a doubled base-3 number. A +2 operation corresponds to adding 1 to the bottom digit (this never overflows into the next column thanks to the observation above). A *3 operation moves all the digits up one column, introducing a 0 as the bottom digit. Note that because the number is doubled, the +2 operation adds just 1 to the base-3 number!
From this, you can see that you can count the number of operations from observation of the doubled base-3 number. Because *3 introduces a new digit, and +2 increases the digit sum by 1, so the number of operations is equal to the number of digits plus 1, plus the digit sum.
As an example. Suppose you have the doubled base-3 number 2 * 2101, then this is equivalent to 2 * (1+3*3*(1+3*(1+1)))) = (2 + 3*3*(2+3*(2+2))).
I tried something like this. it seems to work fine.
getMaxNumber(2, 5) ==> 72
getMaxNumber(2, 51) ==> 98
private int getMaxNumber(int n, int k){
int N = 0;
for (int i = 0; i < n; i++) {
N = N * 10 + 9;
}
int[] result = new int[1];
helper(N, k, 0, 0, result);
return result[0];
}
private void helper(int N, int K, int n, int k, int[] result){
if(n > N) return;
if(k <= K){
result[0] = Math.max(result[0], n);
}
if(n > 0)
helper(N, K, n * 3, k + 1, result);
helper(N, K, n + 2, k + 1, result);
}
Keeping with the style of your original recursive method. I modified it a bit to produce a working solution:
public static long largestNDigitNumber(int n, long currentK, long maxK, long currentValue) {
if (currentK > maxK || n < 1 || maxK < 1) return 0;
if (currentValue >= Math.pow(10, n))
return 0;
long c1 = largestNDigitNumber(n, currentK + 1, maxK, currentValue * 3);
long c2 = largestNDigitNumber(n, currentK + 1, maxK, currentValue + 2);
if (c1 == 0 && c2 == 0)
return currentValue;
return c1 > c2 ? c1 : c2;
}
public static void main(String[] args) {
int n = 2;
long k = 51;
long largest = largestNDigitNumber(n, 0, k, 0);
System.out.println(largest); //98
}
This recursive method returns values here instead of using an array. Hence the check if one returned value is bigger than the other or they are both 0 before returning.
Both the +2 and *3 operations preserve odd/even parity, so starting from 0 we can only reach even numbers. We could start our search at the highest even number: 8, 98, 998, 9998 etc. and see what the shortest distance to 0 is.
If we are looking for the shortest distance, then there are less choices to make. If the current number is a multiple of 3 then there are two choices, either we divide by 3 or subtract 2. Otherwise the only choice is to subtract 2. I suspect that in the majority of cases, dividing by 3 is the better option, so that might be the first to try to keep the tree smaller.
If the minimum number of steps is less than K then as many divide by 3 operations as needed can be used to make the correct K
If the minimum number of steps is equal to K then the problem is solved.
If the minimum number of steps is more than K then you need to pick a lower starting number. Some even numbers will already have been covered as part of the initial calculation. You get those 'for free', provide you include a small amount of record keeping. You only need to examine large even numbers that were missed earlier due to a 'divide by 3' step.
I have two values. One is static and equals 24
int A = 24;
and I have entries list :
[0, 21, 45, 76, 98]
All of occurences comes in loop and I want to get closest value which divides on A :
0 - 24
21 - 24
45 - 48
76 - 72
98 - 96
How to calculate this?
Using java8 you can stream the array or list and map that
public static void main(String[] args) {
int a = 24;
List<Integer> mL = Arrays.asList(0, 21, 45, 76, 98);
Map<Integer, Integer> m = mL.stream().collect(Collectors.toMap(Integer::intValue, x -> {
int r = a * (int) Math.round(x / (double) a);
return r == 0 ? a : r;
}));
System.out.println(m);
}
the output will be a map where the key is the values to analyse and the values are the closest delta to it
{0=24, 98=96, 21=24, 76=72, 45=48}
You could divide each value by a using floating point division, round it to the closest int and then multiply it back again by a:
int a = 24;
int[] values = new int[]{0, 21, 45, 76, 98};
int[] result =
Arrays.stream(values).map(v -> a * (int) Math.round(v / (double) a)).toArray();
To find the largest multiple x of a number n which is less than a given number a, you can use some arithmetic:
int x = n - n % a;
Now if you want to get the nearest multiple, whether larger or smaller than a, you can use an if statement:
if (a - x > (x + n) - a)
x = x + a
For a list of numbers, just loop over them or use the Stream API.
Assuming that the arrays are also integers, the correct approach for rounding an integer a to the nearest multiple of integer n is as follows:1
(a + n/2) / n * n
How this works
Hopefully the a / n * n approach should be familiar as an approach to get floor-like behaviour, due to the way integer maths works. The n/2 is a bias to give you round-like behaviour instead.2
Things to be aware of
Exact ties are rounded upward.
Inputs within n / 2 of the maximum representable value will cause this to fail.
Comparison with other answers
The floating-point approaches aren't guaranteed to give the right answer for all input values, due to the limitations of floating-point arithmetic.
Using double may work if the inputs are ints (although I'm not sure what the proof is). But it certainly won't be sufficient for longs.
This integer approach may be equivalent to #CodeApprentice's answer, I'm not sure. But this approach avoids the conditional.
1. The boilerplate stream/loop code to get this to work for multiple input values is left as an exercise for the reader.
2. And for completeness, if you use a bias of n-1, you get ceil-like behaviour!
One approach is to take the remainder and see if you need to add or substract from the given number to get closest number that divides. If remainder is less then half of A then substract remainder from the number otherwise add to it the difference between remainder and A. Also as a quick exit check if number is less then A the closest one is A itself.
public static int[] closest(int a, int[] b){
int[] result = new int[ b.length ];
int halfOfA = a/2;
for (int i = 0; i < b.length; i++){
if ( b[i] <= a ){
result[i] = a;
}else{
int rem = b[i] % a;
if (rem < halfOfA) result[i] = b[i] - rem;
else result[i] = b[i] + (a - rem);
}
}
return result;
}
You can do like this :
iterate until your are as near as possible of the value (when distance is less than A/2
private static int closestTo(int a, int i) {
int res = a;
while (Math.abs(res - i) > (a / 2.0) && res< i + a) {
res += a;
}
return res;
}
And use like
public static void main(String[] args) {
int A = 24;
int[] tab = new int[]{0, 21, 45, 76, 98};
for (int i : tab) {
System.out.println(i + " - " + closestTo(A, i));
}
}
I have a question where I have to add numbers from 1 to N which have their set bits as 2. Like for N = 5 we should get value 8, as number 3 and 5 have 2 bits set to one. I am implementing the same in java. I am getting the o/p correct for int value but when it comes to the long values, either it's taking a lot of time or freezing, and when I submit the same on code judge sites, it's giving run time exceeded message. Please guide me how may I optimise my code to run it faster, thanks :)
public static void main(String[] args)
{
long n = 1000000L;
long sum = 0;
long start = System.currentTimeMillis();
for(long i = 1L ; i <= n ; i++)
{
if(Long.bitCount(i) == 2)
{
sum += i;
}
}
long end = System.currentTimeMillis();
System.out.println(sum);
System.out.println("time="+(end-start));
}
As #hbejgel notes, there is no point in looping over all numbers and checking their bit count. You can simply construct numbers with 2 bits and add them up.
You can construct a number with 2 bits by picking two different bit positions in the long, the "higher" bit and the "lower" bit":
long i = (1 << higher) + (1 << lower);
So, you can simply loop over all such numbers, until the value you have constructed exceeds your limit:
long sum = 0;
outer: for (int higher = 1; higher < 63; ++higher) {
for (int lower = 0; lower < higher; ++lower) {
long i = (1 << higher) + (1 << lower);
if (i <= n) {
sum += i;
}
if (i >= n) break outer;
}
}
Let's say we know the closest number, x, equal to or lower than N with 2 set bits, then we can use the formula for power series to quickly sum all positions of the two set bits, for example, if x = b11000, we sum
4*2^0 + S(4)
+ 3*2^1 + S(4) - S(1)
+ 2*2^2 + S(4) - S(2)
+ x
where S(n) = 2 * (1 - 2^n) / (1 - 2)
= 2 + 2^2 + 2^3 ... + 2^n
With numbers encoded 2 out of 5, exactly two bits are set in every one-digit number. The sum is 45, with the exception of N×(N-1)/2 for 0≤N<9.
I think the question is supposed to discover the pattern.
Fast forward. Given a number N, you can tell the largest number
should count by bitmask from the first two bits are set. So you have
a smaller number M
Skip to next counted number Given any number with two bit set, next
largest number is the shift the second bit by one, until underflow.
Skip to next order When underflow happens on set two, shift the
highest bit by one and also the bit on it's right.
You don't really need a loop on N, but the bits it have.
Next question: can you answer a large number? which N >100,000,000
Next Next question: can you answer the same question for X bits when X>2
private void displayBinary() {
int value = 123;
for (int i = 128; i > 0; i = i / 2) {
if ((value & i) != 0) System.out.print("1 ");
else
System.out.print("0 ");
}
}
The method above successfully writes out 123 in its binary form, where the program outputs
0111101.
However, if I change the !=0 to ==1 in the if statement, it outputs 0000001. Since binary is only 0s and 1s, why doesn't the latter work?
You're not working with a base-2 number; you're still working with a base-10 int.
From this, all numbers for your iteration, except for the last, will fail your if condition, since they are not equal to 1.
Because when you use a bitwise AND, the place of the bit (the digit) matters. 1000 does not equal 1 in either decimal or binary.
(value & i) when it is not 0 wil vay between 1, 2, 4, 8, 16, 32, 64, and 128 depending on the bit you are testing.
I need a function in Java to give me number of bytes needed to represent a given integer. When I pass 2 it should return 1, 400 -> 2, 822222 -> 3, etc.
#Edit: For now I'm stuck with this:
numOfBytes = Integer.highestOneBit(integer) / 8
Don't know exactly what highestOneBit() does, but have also tried this:
numOfBytes = (int) (Math.floor(Math.log(integer)) + 1);
Which I found on some website.
static int byteSize(long x) {
if (x < 0) throw new IllegalArgumentException();
int s = 1;
while (s < 8 && x >= (1L << (s * 8))) s++;
return s;
}
Integer.highestOneBit(arg) returns only the highest set bit, in the original place. For example, Integer.highestOneBit(12) is 8, not 3. So you probably want to use Integer.numberOfTrailingZeros(Integer.highestOneBit(12)), which does return 3. Here is the Integer API
Some sample code:
numOfBytes = (Integer.numberOfTrailingZeroes(Integer.highestOneBit(integer)) + 8) / 8;
The + 8 is for proper rounding.
The lazy/inefficient way to do this is with Integer#toBinaryString. It will remove all leading zeros from positive numbers for you, all you have to do is call String#length and divide by 8.
Think about how to solve the same problem using normal decimal numbers. Then apply the same principle to binary / byte representation i.e. use 256 where you would use 10 for decimal numbers.
static int byteSize(long number, int bitsPerByte) {
int maxNumberSaveByBitsPerByte = // get max number can be saved by bits in value bitsPerByte
int returnValue = getFloor(number/maxNumberSaveByBitsPerByte); // use Math lib
if(number % maxNumberSaveByBitsPerByte != 0)
returnValue++;
return returnValue;
}
For positive values: 0 and 1 need 1 digit, with 2 digits you get the doubled max value, and for every digit it is 2 times that value. So a recursive solution is to divide:
public static int binaryLength (long l) {
if (l < 2) return 1;
else 1 + binaryLength (l /2L);
}
but shifting works too:
public static int binaryLength (long l) {
if (l < 2) return 1;
else 1 + binaryLength (l >> 1);
}
Negative values have a leading 1, so it doesn't make much sense for the question. If we assume binary1 is decimal1, binary1 can't be -1. But what shall it be? b11? That is 3.
Why you wouldn't do something simple like this:
private static int byteSize(int val) {
int size = 0;
while (val > 0) {
val = val >> 8;
size++;
}
return size;
}
int numOfBytes = (Integer.SIZE >> 3) - (Integer.numberOfLeadingZeros(n) >> 3);
This implementation is compact enough while performance-friendly, since it doesn't involve any floating point operation nor any loop.
It is derived from the form:
int numOfBytes = Math.ceil((Integer.SIZE - Integer.numberOfLeadingZeros(n)) / Byte.SIZE);
The magic number 3 in the optimized form comes from the assumption: Byte.SIZE equals 8