While reading this book I came across converting binary to integer.
The code that is given by the book is:
// convert a String of 0's and 1's into an integer
public static int fromBinaryString(String s) {
int result = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '0') result = 2 * result;
else if (c == '1') result = 2 * result + 1;
}
return result;
}
and the way I solved the problem is:
public static int fromBinary(String s) {
int result = 0;
int powerOfTwo = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if ('1' == s.charAt(i)) {
result += Math.pow(2, powerOfTwo);
}
powerOfTwo++;
}
return result;
}
I know my code has an extra counter and it is probably a bit slowly but the way I implement the solution is by following the polynomial definition
x = xn b^n + xn-1 b^n-1 + ... + x1 b^1 + x0 b^0.
What I don't understand is how their's solution works ?
I've already debugged but still can't find what is key. Can someone explain ?
They basically shift the result with 2 * result and add 1 if the bit is set.
Example: 01101
1. iteration: result = 0 -> result * 2 = 0 (same as binary 00000)
2. iteration: result = 0 -> result * 2 + 1 = 1 (same as binary 00001)
3. iteration: result = 1 -> result * 2 + 1 = 3 (same as binary 00011)
4. iteration: result = 3 -> result * 2 = 6 (same as binary 00110)
5. iteration: result = 6 -> result * 2 + 1 = 13 (same as binary 01101)
In terms of bits: 8 + 4 + 1 = 13
Alternatively you could replace result = result * 2 with result <<= 1 but adding 1 in a single statement would not work then. You could write result = (result << 1) + 1 but that's longer and harder to read than the multiplication.
Copying your polynomial definition x = xn b^n + xn-1 b^n-1 + ... + x1 b^1 + x0 b^0 you can rewrite this to
x = ((((...(((( xn * b + xn-1 ) * b + ... )* b + x1 ) * b + x0
where you have b=2 for binary representation and you have n-1 parenthesis opening on the left most side.
For n=4 this reads like
x = ((((x3*2)+x2)*2+x1)*2+x0 = x3 * 2^3 + x2 * 2^2 + x1 * 2^1 + x0 * 2^0
If you are parsing the string begining with the MSB (x_n) towards LSB (x_0), when reading x_i you will have to execute
result = result * 2 + x_i
Before executing this result would have stored the value
((...(((( xn * b + xn-1 ) * b + ... )* b + x_(i+1) )
After executing this result would have stored the value
((...(((( xn * b + xn-1 ) * b + ... )* b + x_i )
Reasoning by induction you can prove you compute the correct answer in the end.
Related
I am writing a program where I have strings of 9 bits of "0" and "1" to convert to exponent (taking each index and doing 2 ^ n from right to left).
example: ["1","0","1"] = 2^2 + 0^1 + 2^0
I know this is wrong because of the errors I am getting but am confused what to do which will calculate it in an efficient manner.
expoBefore = (strNum.charAt(9)) * 1 + (strNum.charAt(8)) * 2 + (strNum.charAt(7)) * 4 + (strNum.charAt(6)) * 8 + (strNum.charAt(5)) * 16 + (strNum.charAt(4)) * 32 + (strNum.charAt(3)) * 64 + (strNum.charAt(8)) * 128;
for example for one of the strings I am passing through [11111111] I want it to add 1 * 2^0 + 1 * 2 ^1 + 1 * 2^2.....etc
Clarification edit:
What is a more efficient way of converting a string of 0's and 1's to an integer?
You're trying to multiply a character's ascii value with an integer.
You must take the integer value of this character and then multiply it with another integer. Hope this helps.
String str = "111";
int x = Character.getNumericValue(str.charAt(0));
int y = Character.getNumericValue(str.charAt(1));
int z = Character.getNumericValue(str.charAt(2));
System.out.println(x + y + z);
Output:
3
You need to use a loop.
Iterate over the binary string. For each character, add 2^x to an accumulator if the bit is set (where x is the position of the bit), otherwise, add 0.
String binary = "11111111";
int number = 0;
for(int i = binary.length() - 1; i >= 0; i--) {
char c = binary.charAt(i);
number += Integer.parseInt(c + "") * Math.pow(2, binary.length() - i - 1);
}
System.out.println(number); // prints 255
How to convert binary to decimal
Just use a for loop and increment down to miniplate each number
It is very inefficient to use Math.pow(2, i) in a loop.
Faster to keep the previous value and multiply by 2 each time through (code untested):
int ip = 1;
int sum = 0;
for ( int i = binary.length -1; i >= 0) {
if ( binary.charAt(i) == '1' ) {
sum += ip;
}
ip *= 2;
}
You may want to use long ints if the number gets large.
Also, be sure to check that binary contains only zeroes and ones.
Question
Given N and M, write an equation using left shift operators whose
result will be equal to the product N * M.
Input : First line has 0 < T ≤ 50000 denoting number of test cases.
Next T lines have two integers 0 < N, M ≤ 10¹⁶.
Output : For each test case print an equation for N * M resembling
(N << p1) + (N << p2)+ ...+(N << pk) where p1 ≥ p2 ≥ ... ≥ pk
and k is minimum.
SAMPLE INPUT SAMPLE OUTPUT
2
2 1 (2<<0)
2 3 (2<<1) + (2<<0)
Time Limit: 1.0 sec
My Solution 1st approach
int dig = (int)(Math.floor(Math.log10(m)/Math.log10(2))+1);
boolean flag = false;
for(long i = dig; i>=0; --i) {
if(((m>>(i-1l)) & 1l) == 1l) {
if(flag)
System.out.print(" + ("+n+ "<<"+(i-1)+")");
else {
System.out.print("("+n+"<<"+(i-1)+")");
flag = true;
}
}
}
Second Approach
boolean[] arr = new boolean[dig];
int i = dig-1;
while(m > 0) {
if((m&1) == 1 ) {
arr[i] = true;
}
i--;
m = m>>1l;
}
int j = dig-1;
for( i = 0; i < dig; ++i) {
if(arr[i]) {
if(flag)
System.out.print(" + ("+n+"<<"+j+")");
else {
System.out.print("("+n+"<<"+j+")");
flag = true;
}
}
j--;
}
In both cases I am getting 5 correct out of 8 and rest 3 are TLE why?
I don't actually see anything in both of your approaches preventing some ten-thousands of products of numbers up to 57 bit to be represented as Strings in one second:
TLE may be due to System.out.print() taking an inordinate amount of time.
That said, use a utility like
/** builds <code>n * m</code> in the form
* <code>(n<<p1) + (n<<p2) + ... + (n<<pk)</code>
* using left shift.
* #param n (0 < multiplicand <= 10**16)
* #param m 0 < multiplier <= 10**16
* #return a verbose <code>String</code> for <code>n * m</code>
*/
static String verboseBinaryProduct(Object n, long m) {
int shift = Long.SIZE - Long.numberOfLeadingZeros(m) - 1;
final long highest = 1 << shift;
final StringBuilder binary = new StringBuilder(42);
final String chatter = ") + (" + n + "<<";
final long rest = highest - 1;
while (true) {
if (0 != (highest & m))
binary.append(chatter).append(shift);
if (0 == (rest & m)) {
binary.append(')');
return binary.substring(4);
}
m <<= 1;
shift -= 1;
}
}
and System.out.println(verboseBinaryProduct(n, m));.
I can do this using combinations.
Queens won't be stable (under attack) if they are in the same :
Vertical
Horizontal
Diagonal.
So
Its possible by : n * P(n,2) ways
Its possible by : n * P(n,2) ways
Its possible by : 2 * ( P(n,2) + P(n-1,2) + ... + P(2,2)) + 2 * (P(n-1,2) + ... + P(2,2))
What would be an appropriate algo for the above ?
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
int n = 8;
int arr[][] = new int[n][n];
long x = 0;
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
x += Math.min(n-1-i, n-1-j) + Math.min(i, j) + Math.min(n-1-i,j) + Math.min(i,n-1-j);
x+= 2*n -2;
}
}
System.out.println(x);
}
}
How about the above logic?
Well, for n * n board there are
All: n * n * (n * n - 1) / 2
Stable: n * (n - 1) * (n - 2) * (3 * n - 1) / 6
Unstable: n * (5 * n - 1) * (n - 1) / 3
positions. (See https://oeis.org/A036464 for details). Some examples for small ns:
n all unstable stable
-----------------------------
1 0 = 0 + 0
2 6 = 6 + 0
3 36 = 28 + 8
4 120 = 76 + 44
5 300 = 160 + 140
6 630 = 290 + 340
7 1176 = 476 + 700
8 2016 = 728 + 1288
9 3240 = 1056 + 2184
10 4950 = 1470 + 3480
The implementation (Java) is evident
private static long unstableCount(long n) {
return n * (5 * n - 1) * (n - 1) / 3;
}
It may be interesting to note, that
All = O(n**4)
Stable = O(n**4)
Unstable = O(n**3) // just cube
so for a large board almost all postions are stable.
If queens are distinguishable (e.g. you have white and red queens) all you have to do is to multiply the numbers and formulas above by 2 (swapping queens brings a new position now).
private static long unstableDistinguishableCount(long n) {
return n * (5 * n - 1) * (n - 1) / 3 * 2;
}
Edit: Naive sampling implementation (we loop over all possible queens' positions) could be
private static long unstableCountNaive(int n) {
long result = 0;
for (int file1 = 0; file1 < n; ++file1)
for (int rank1 = 0; rank1 < n; ++rank1)
for (int file2 = file1; file2 < n; ++file2)
for (int rank2 = file1 == file2 ? rank1 + 1 : 0; rank2 < n; ++rank2)
if ((file1 == file2) || // Same file
(rank1 == rank2) || // Same rank
(file1 + rank1 == file2 + rank2) || // Same top-left bottom-right diagonal
(file1 - rank1 == file2 - rank2)) // Same bottom-left top-right diagonal
result += 1;
return result;
}
Edit 2: if I got your idea right, you can just count diagonal attacks and then use symmetry:
private static long unstableCountBetter(int n) {
long result = 0;
// Attacked by top-left bottom-right diagonal
for (int rank = 0; rank < n; ++rank)
for (int file = 0; file < n; ++file)
result +=
(rank + file >= n ? 2 * n - 2 - (rank + file) : rank + file);
result =
// symmetry: we have TWO diagonals
result * 2 +
// At each postion (n * n of them) we have n - 1 checks on the same rank
n * n * (n - 1) +
// At each postion (n * n of them) we have n - 1 checks on the same file
n * n * (n - 1);
// /2 if queens are indistiguished (728 for 8x8 board)
return result / 2;
}
The question is a bit incomplete but looking at the comments, I think I have got all the information to answer the question.
Since you wrote that there is 56 ways for 2 queens to intersect on a 3*3 board, you treat both queens as different, ie. ordered. eg. These 2 boards are different:
..q ..Q
.Q. .q.
... ...
So, the answer to your question is simple formula for n*n board:
(n*n) * (n*n - 1) - n*(n-1)*(n-2)*(3*n-1)/3
I am trying to calculate partitions of a natural number using the formula below. The formula generates two positive numbers, then two negative and so on. You stop when P(n) < 0 An example is
p(3) = p(2) + p(1) = 3
p(4) = p(3) + p(2) = 3 + 2 = 5
p(5) = p(4) + p(3) - p(0) = 5 + 3 - 1 = 7
p(6) = p(5) + p(4) - p(1) = 7 + 5 - 1 = 11
*P(0) = 1 by convention
In other words in order to calculate say P(5) you would have to calculate P(4) which equals P(3) + P(2) and and P(3) which equals P(2) + P(1) and finally - P(0) which equals 1. You would have to traverse down for each to find what they equal and then sum them. So to find a partition of a number you would have to find the partitions of all other numbers each. I have tried something as you can see the code below but it does not work. k = counter in my code.
Code:
public static long SerialFib( long n )
{
long exponent = 0;
double ex;
long counter = 1;
ex = Math.pow(-1, counter - 1);
exponent = (long) ex;
if (n < 0)
{
return 0;
}
else
{
return SerialFib((exponent * (n - ( (counter * ( (3 * counter) - 1)) /
2)))) + SerialFib((exponent * (n - ( (counter * ( (3 * counter) +1))/2))));
}
}
Counter is going to always be 1 because you aren't passing it back into SerialFib. Also, you need a base case for when n is equal to 0 it will return 1.
first base case:
if(n==0)
return 1;
SerialFib should have another parameter for counter:
SerialFib(long n, int counter)
When you call SerialFib it should look like:
SerialFib( [your formula], ++counter);
I am trying to write a function using which I can obtain any natural number in minimum steps. Where I am allowed to add or subtract natural numbers starting from 1.
There the conditions are :
Use a number only once
You are allowed to perform only addition and subtraction.
You are not allowed to escape any digit
Find the value of the integer which has a maximum value to obtain that number.
eg : If I my desired number is 4 then it is obtained as -1+2+3 here answer is 3. In a similar manner if I want 6 then 1+2+3 here answer is 3. For 10= 1+2+3+4 ans is 4.
what I have so far :
What I have so far:
public void step() {
int n = (int)Math.sqrt(position * 2);
k = (position - (((n + 1) * n) / 2));
l = ((((n + 1) * (n + 2)) / 2) - position);
System.out.println(k + " " + l);
System.out.println(n);
p = (l > k ? k : l);
r = (l > k ? n : n + 1);
System.out.println(p + " " + r);
if (k == 0) {
result = n;
} else {
result = r + (2 * p);
} System.out.println("__________" + result + "__________");
}
Ok, lets do it in this way. Consider following binary tree. now you can find sum from each path and take every path with sum=your number(let's say 4). now you can get the maximum value from those. Try to come up with implementation of this. I can help you further, If you try some thing.
0
/ \
-1 1
/ \ / \
-2 2 -2 2
The solution is :
for n=1: = 1
for n=2: = 1+2 => 1+2+3 => 1-2+3
for n=3: = 1+2
for n=4: = 1+2+3 => -1+2+3
for n=5: = 1+2+3 => 1+2+3+4-5
for n=6: = 1+2+3
for n=7: = 1+2+3+4=>1+2+3+4+5=>1+2+3-4+5
for any n, first calculate the S(k)=1+2+3+...+k
where S(k)>n and x=S(k)-n is an even number. Then go flip the + of x/2 to -.
S(k) = (1+k)*k/2 > n
=> k*k + k -2n > 0
=> k > (-1 + sqrt(1+8n))/2
eg, n=7, k > 3.2, then k=4, S(4) = 10, 10-7=3, it's odd, so k=5, S(5)=15, x=15-7=8, 8/2=4, flip the sign of 4, we got 1+2+3-4+5 = 7
in some cases, Sk-n is odd, but S(k+1)-n is also odd, in this case, we need to use S(k+2).
The code is as follow :
public void step() {
k = (int)Math.ceil(((-1 + Math.sqrt(1 + 8 * n)) / 2));
int Sk = (1 + k) * k / 2;
if ((Sk - n) % 2 != 0) {
k++;
Sk = (1 + k) * k / 2;
if ((Sk - n) % 2 != 0) {
k++;
Sk = (1 + k) * k / 2;
}
}
int i = (Sk - n) / 2;
System.out.println("maximum number is : " + k + "the number with -ve sign is : " + i);
}