Codility: Condition in comfort - java

While conducting the examination this was one of the task (which I could not solve):
They say a number A "comfort" to another number B if, when you convert both numbers to binary, all positions in B where there is a number 1 must be another 1 in the same position in A.
example:
B = 101
A = 111
In this case, the number A "comfort" to B, however
B = 101
A = 011
The Comfort condition is not met.
They gave me 3 unsigned numbers with 30 bits A, B and C, between 0 and 2 ^ 30. I must determine the amount of numbers in that range that meet the condition of "comfort" for at least one of those numbers.
expected worst-case time complexity is O (log (A) + log (B) + log (C));
I use the following code and it takes too long, most of all because it checks the binary number as an array and compare every cell. I assume there must be some way to make it faster (some math operation or idk :-( ).
public class Main {
public static void main(String[] args)
{
sol(905,5000,11111111); //I used any numbers
}
public static void sol(int A, int B, int C)
{
int min=Math.min(A, Math.min(B, C));
int max=(int) Math.pow(2, 30);
String binA=Integer.toBinaryString(A); binA=fillBin(binA);
String binB=Integer.toBinaryString(B); binB=fillBin(binB);
String binC=Integer.toBinaryString(C); binC=fillBin(binC);
String binMax=Integer.toBinaryString(max);
int conta=0;
for(int i=min;i<=max;i++)
{
String binT = Integer.toBinaryString(i);binT=fillBin(binT);
boolean failA=false;
boolean failB=false;
boolean failC=false;
for(int j=0;j<binT.length();j++)
{
if((binA.length()<j)&&(binB.length()<j)&&(binC.length()<j))
{
break;
}
if((!failA)||(!failB)||(!failC))
{
if((binA.length()<j)&&(binA.charAt(j)=='1') && (binT.charAt(j)!='1'))
{
failA=true;
}
if((binB.length()<j)&&(binB.charAt(j)=='1') && (binT.charAt(j)!='1'))
{
failB=true;
}
if((binC.length()<j)&&(binC.charAt(j)=='1') && (binT.charAt(j)!='1'))
{
failC=true;
}
}
else
{
break;
}
}
if((!failA)||(!failB)||(!failC))
{
conta++;
}
}
}
private static String fillBin(String binA)
{
String S=binA;
for(int i=0;i<(31-binA.length());i++)
{
S="0"+S;
}
return S;
}
}
If any of you already done this task before and see that there are some missing data , let me know , excuse my English (not my native language).
thank you very much
EDIT: This is the code with #Eran 's help:
public class BinaryTask
{
public void test(int A, int B, int C)
{
long timeStart, timeEnd;
timeStart = System.currentTimeMillis();
//Bunch of variables
String binaryA = Integer.toBinaryString(A); int zerosA=0;
String binaryB = Integer.toBinaryString(B); int zerosB=0;
String binaryC = Integer.toBinaryString(C); int zerosC=0;
String binaryAB =""; int zerosAB=0;
String binaryBC =""; int zerosBC=0;
String binaryAC =""; int zerosAC=0;
String binaryABC=""; int zerosABC=0;
//The long for the for
int Max = Math.max(binaryA.length(), Math.max(binaryB.length(), binaryC.length()));
//Creating: A|B, B|C, A|B and A|B|C that meet the confort condition
for(int i=0;i<Max;i++)
{
//Creating A|B
if((binaryA.length()>i)&&(binaryB.length()>i))
{
if((binaryA.charAt(i)=='1')||(binaryB.charAt(i)=='1'))
{
binaryAB="1"+binaryAB;
}
else //I also count this zero so i dont have the do another for later
{
binaryAB="0"+binaryAB; zerosAB++;
}
}
//Creating B|C
if((binaryB.length()>i)&&(binaryC.length()>i))
{
if((binaryB.charAt(i)=='1')||(binaryC.charAt(i)=='1'))
{
binaryBC="1"+binaryBC;
}else{binaryBC="0"+binaryBC; zerosBC++;}
}
//Creating A|C
if((binaryA.length()>i)&&(binaryC.length()>i))
{
if((binaryA.charAt(i)=='1')||(binaryC.charAt(i)=='1'))
{
binaryAC="1"+binaryAC;
}else{binaryAC="0"+binaryAC;zerosAC++;}
}
//Creating A|B|C
if((binaryA.length()>i)&&(binaryB.length()>i)&&(binaryC.length()>i))
{
if((binaryA.charAt(i)=='1')||(binaryB.charAt(i)=='1')||(binaryC.charAt(i)=='1'))
{
binaryABC="1"+binaryABC;
}else{binaryABC="0"+binaryABC; zerosABC++;}
}
}
//Counting the other amount of zeros
zerosA = countZeros(binaryA);
zerosB = countZeros(binaryB);
zerosC = countZeros(binaryC);
long confortA = (long) Math.pow(2, zerosA);
long confortB = (long) Math.pow(2, zerosB);
long confortC = (long) Math.pow(2, zerosC);
long confortAB = (long) Math.pow(2, zerosAB);
long confortBC = (long) Math.pow(2, zerosBC);
long confortAC = (long) Math.pow(2, zerosAC);
long confortABC = (long) Math.pow(2, zerosABC);
long totalConfort = confortA + confortB + confortC - confortAB - confortBC - confortAC + confortABC;
timeEnd = System.currentTimeMillis();
System.out.println("Total of confort for A "+A+" B "+B+" C "+C+" is " +totalConfort);
System.out.println("the task has taken "+ ( timeEnd - timeStart ) +" milliseconds");
}
private int countZeros(String binary)
{
int count=0;
for(int i=0;i<binary.length();i++)
{
if(binary.charAt(i)=='0')
{count++;}
}
return count;
}
}
To make a test, i did this:
public static void main(String[] args)
{
BinaryTask T = new BinaryTask();
int A = (int) Math.pow(2, 10);
int B = (int) Math.pow(2, 15);
int C = (int) Math.pow(2, 30);
T.test(A, B, C);
}
And this was the output:
Total of confort for A 1024 B 32768 C 1073741824 is 1073739776
the task has taken 1 milliseconds

Building on #alain's answer, comf(A) = 2^(number of zero bits in A) is the number of comforting numbers for A.
You need the number of comforting numbers for either A, B or C.
That's comf(A)+comf(B)+comf(C)-comf(A and B)-comf(B and C)-comf(A and C)+comf(A and B and C).
where comf(A and B) denotes the number of comforting numbers for both A and B.
and comf(A and B and C) denotes the number of comforting numbers for all A, B and C.
We know how to calculate comf(A), comf(B) and comf(C).
comf(A and B) = 2^(number of zero bits in A|B), since a number X comforts both A and B if and only if it has ones in all the bits for which either A or B has ones.
Similarly, comf(A and B and C) = 2^(number of zero bits in A|B|C).
Since all the calculations are bit operations on A,B and C, the running time is the lengths in bits of A, B and C, which is O (log (A) + log (B) + log (C)).

The condition for 'A comfort to B' is
B & A == B
You could just count the number n of 0 bits in B, and then you have 2^n or Math.pow(2, n) possibilities to build a 'comforting' number A.
Unfortunately, this doesn't work for 'comforting to at least one of three numbers', but it could be a starting point.

Are you sure the output Total of confort for A 1024 B 32768 C 1073741824 is 1073739776 is correct ?
I do agree with bitwise operation, with that I am getting different retult btw.
public static int solution(int A,int B,int C){
int total = 0;
int totalA=0,totalB=0,totalC=0;
//int max = Math.max(Math.max(A, B), C);
double limit = Math.pow(2,30);
for(int i=0;i<=limit;i++){
int no = A & i;
if(no == A){
total++;
totalA++;
//continue;
}
no = B & i;
if(no == B){
total++;
totalB++;
//continue;
}
no = C & i;
if(no == C){
total++;
totalC++;
//continue;
}
}
System.out.println("totalA: " + totalA + " totalB: " + totalB + " totalC: " + totalC);
total = totalA + totalB + totalC;
return total;
}
It gives me totalA: 536870912 totalB: 536870912 totalC: 1
1073741825

Related

Fibonacci sequence - How to calculate the sum of the first 100 even-values Fibonacci numbers?

Fibonacci sequence is defined as a sequence of integers starting with 1 and 1, where each subsequent value is the sum of the preceding two I.e.
f(0) = 1
f(1) = 1
f(n) = f(n-1) + f(n-2) where n>=2
My goal is to calculate the sum of the first 100 even-values Fibonacci numbers.
So far I've found this code which works perfectly to calculate the sum of even numbers to 4million , however I'm unable to find edit the code so that it stops at the sum of the 100th value, rather than reaching 4million.
public class Improvement {
public static int Fibonacci(int j) {
/**
*
* Recursive took a long time so continued with iterative
*
* Complexity is n squared.. try to improve to just n
*
*/
int tmp;
int a = 2;
int b = 1;
int total = 0;
do {
if(isEven(a)) total +=a;
tmp = a + b;
b = a;
a = tmp;
} while (a < j);
return total;
}
private static boolean isEven(int a) {
return (a & 1) == 0;
}
public static void main(String[] args) {
// Notice there is no more loop here
System.out.println(Fibonacci(4_000_000));
}
}
Just to show the console from #mr1554 code answer, the first 100 even values are shown and then the sum of all is 4850741640 as can be seen below:
Any help is appreciated, thanks!
You need to use BigInteger because long easily overflows as Fibonacci's scales quite easily. BigInteger is also tricky to check whether is an odd or even number, but you can use BigInteger::testBit returning boolean as explained in this answer.
Here is some complete code:
BigInteger fibonacciSum(int count, boolean isOdd) {
int i = 0;
BigInteger sum = BigInteger.ZERO;
BigInteger current = BigInteger.ONE;
BigInteger next = BigInteger.ONE;
BigInteger temp;
while (i < count) {
temp = current;
current = current.add(next);
next = temp;
if ((current.testBit(0) && isOdd) || ((!current.testBit(0) && !isOdd))) {
sum = sum.add(current);
i++;
}
}
return sum;
}
Or you can have some fun with Stream API:
BigInteger fibonacciSum(int count, boolean isOdd) {
final BigInteger[] firstSecond = new BigInteger[] {BigInteger.ONE, BigInteger.ONE};
return Stream.iterate(
firstSecond,
num -> new BigInteger[] { num[1], num[0].add(num[1]) })
.filter(pair ->
(pair[1].testBit(0) && isOdd) ||
(!pair[1].testBit(0) && !isOdd))
.limit(count)
.map(pair -> pair[1])
.reduce(BigInteger.ZERO, BigInteger::add);
}
In any way, don't forget to test it out:
#Test
void test() {
assertThat(
fibonacciSum(100, false),
is(new BigInteger("290905784918002003245752779317049533129517076702883498623284700")));
}
You said.
My goal is to calculate the sum of the first 100 even-values Fibonacci numbers.
That number gets very large very quickly. You need to:
use BigInteger
use the mod function to determine if even
For this I could have started from (1,1) but it's only one term so ...
BigInteger m = BigInteger.ZERO;
BigInteger n = BigInteger.ONE;
BigInteger sumOfEven= BigInteger.ZERO;
int count = 0;
BigInteger t;
while( count < 100) {
t = n.add(m);
// check if even
if (t.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {
sumOfEven = sumOfEven.add(t);
count++;
}
n = m;
m = t;
}
System.out.println(sumOfEven);
Prints
290905784918002003245752779317049533129517076702883498623284700
If, on the other hand, from your comment.
My aim is to calculate the sum of the first 100 even numbers
Then you can do that like so
sumFirstNeven = (((2N + 2)N)/2 = (N+1)N
so (101)100 = 10100 and the complexity is O(1)
as I figured, you want a program to sum 100 first even values of the Fibonacci series.
here is a sample code, when you run the program it will ask you to determine the number of the even values, you want 100 value e.g, type 100 in consul:
public static void main(String[] args) {
int firstNumber = 0;
int secondNumber = 2;
System.out.print("Enter the number of odd elements of the Fibonacci Series to sum : ");
Scanner scan = new Scanner(System.in);
int elementCount = scan.nextInt(); // number of even values you want
System.out.print(firstNumber + ", ");
System.out.print(secondNumber + ", ");
long sum = 2;
for (int i = 2; i < elementCount; i++) {
int nextNumber = firstNumber + secondNumber;
System.out.print(nextNumber + ", ");
sum += (nextNumber);
firstNumber = secondNumber;
secondNumber = nextNumber;
}
System.out.print("...");
System.out.println("\n" + "the sum of " + elementCount + " values of fibonacci series is: " + sum);
}

count no. of set bits of each number in a range and then sum it up

Count no. of set bits in each number in a range and then display the total sum.
Input-
2
1 1
10 15
Output-
1
17
I am getting time limit exceeded problem also I am not getting any output for the problem. Could anyone tell me the error in my code.Thank you
import java.util.*;
public class counBitsInRange {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int Q = sc.nextInt();
int[] res = new int[Q];
for(int i=0;i<Q;i++)
{
int a = sc.nextInt();
int b = sc.nextInt();
res[i] = countbits(a,b);
}
for(int j=0;j<res.length;j++)
{
System.out.println(res[j]);
}
}
private static int countbits(int a,int b)
{
int count=0;
for(int i=a;i<=b;i++)
{
while(i>0)
{
count+=(i&1);
i=i>>1;
}
}
return count;
}
}
Integer class has the method bitCount returning the number of one-bits, rewrite your method countbits using the java library class method like below:
private static int countbits(int a,int b)
{
int count=0;
for(int i=a;i<=b;i++)
{
count += Integer.bitCount(i);
}
return count;
}
Here is the bug: Both the for loop and the body inside while loop changes the i value, which sometimes makes the loop go forever. Keep them separate.
private static int countbits(int a,int b)
{
int count=0;
for(int j=a;j<=b;j++)
{
int i = j;
while(i>0)
{
count+=(i&1);
i=i>>1;
}
}
return count;
}
This is a problem:
for(int i=a;i<=b;i++)
No matter what you put inside that loop, it will not scale well to large ranges, and the ranges could be two billion long.
An alternative algorithm is:
Use a clever trick to count the total number of set bits in the range [0, b + 1] (exclusive of the endpoint)
Use the trick again to count the total number of set bits in the range [0, a]
The difference between them is the total number of set bits in the range [a, b + 1]
For example, in code:
static long countSetBitsInRange(int a, int b)
{
return countSetBitsUpTo(b + 1) - countSetBitsUpTo(a);
}
static long countSetBitsUpTo(int n)
{
int power = 1;
long cnt = n >> 1;
while ((1 << power) <= n)
{
long totalPairs = n >> power;
cnt += (totalPairs >> 1) << power;
if ((totalPairs & 1) != 0)
cnt += n & ((1 << power) - 1);
power++;
}
return cnt;
}
Based on a trick from Count total set bits in all numbers from 1 to n.

How to find the third largest number out of 4 inputs without using arrays and only using three comparators or comparisons

The code that I have written is as follows :
/*
Program to find the 3rd largest no from 4 nos without using arrays and
only using 3 comparators or comparisons
*/
package d;
public class thirdlargest {
public static void main(String args[]) {
int a=1,b=2,c=3,d=4,soln;
soln= Math.min(Math.max(a,b),Math.max(c,d));
System.out.println("Third largest=" +soln);
}
}
/*
Output:
Third largest=2
*/
But this only works for the used pattern of input if I change the pattern the output will be wrong. How can I fix this code with only using 3 comparators or comparisons strictly and we can use any programming language
IMO it is not possible to find third largest number out of 4 numbers using only three comparisons:
public static void main(String[] args) throws IOException {
int a=1,b=2,c=3,d=4,soln;
int maximum1 = Math.max(a,b);
int maximum2 = Math.max(c,d);
if(maximum1 < maximum2) {
// either c or d and we need more comparisons
}
else {
// either a or b and we need more comparisons
}
}
Edit: Actually we can find the largest number or smallest number using 3 comparisons but probably not the third largest etc.
Also check this answer for finding kth largest number in O(n) time.
This answer on the Math StackExchange site discusses the problem of finding the 2nd largest of N values. It states (with proof) that the lower (tight) bound is N + ceiling(log2N) - 2
For N == 4, that evaluates to 4.
(This applies here because the 3rd largest of 4 is also the 2nd smallest of 4.)
I don't think the proof excludes (hypothetical) solutions with less than 4 comparisons that rely on the N numbers being unique. But that was not part of the problem statement.
Thanks to #invisal for link to algorithm to find the maximum of two numbers without using comparison operator.
I flipped it to return minimum instead, then used as follows to find second lowest value, aka third highest:
private static int thirdHighest(int a, int b, int c, int d) {
int lowest = min(min(a,b),min(c,d));
if (a == lowest)
return min(min(b,c),d);
if (b == lowest)
return min(min(a,c),d);
if (c == lowest)
return min(min(a,b),d);
return min(min(a,b),c);
}
private static int min(int a, int b) {
return b - (((a - b) >> 31) & 0x1) * (b - a);
}
Exactly 3 == comparisons.
Works for input numbers in any order and also works if duplicate numbers are given.
Note: If inputs are constrained to be distinct, then the answer by #ajb can truly do it without any comparisons, by using the min/max bit manipulation of the link provided by #invisal.
I'm not sure what the exact definition of "comparator" is, the way they're using it. But assuming that Math.min and Math.max don't count as comparators, here's a way to compute it using no comparisons or comparators:
public static int thirdLargest(int a, int b, int c, int d) {
int min = Math.min(a, Math.min(b, Math.min(c,d)));
int offset = min + 1 - Integer.MIN_VALUE;
a -= offset;
b -= offset;
c -= offset;
d -= offset;
min = Math.min(a, Math.min(b, Math.min(c,d)));
return min + offset;
}
Computing the third largest number is the same as computing the second smallest number. The trick in this code is that it computes the smallest number, then subtracts from each number the exact offset needed to make the smallest number wrap around and become Integer.MAX_VALUE, while not wrapping around for the other values. The smallest of the remaining numbers is now the second smallest of the original numbers, minus the offset, which we'll add back.
However, I'll concede that this only works if all four numbers are distinct--or, at least, if the lowest two numbers are distinct. It fails if you give it a=1, b=1, c=2, d=3--it outputs 2 instead of 1. At least this should get you points for your problem-solving skill, which is what I assume the question is intended to find out. It had better not be to find out how you would actually solve this in a production situation, because putting restrictions like this on production code (no arrays) would be lunacy.
EDIT:
Here's another solution. There's one comparison in the code, but it's in a method that's executed three times, so that should count as three comparisons.
public static int thirdLargest(int a, int b, int c, int d) {
if (isThirdLargest(a, b, c, d)) {
return a;
}
if (isThirdLargest(b, a, c, d)) {
return b;
}
if (isThirdLargest(c, a, b, d)) {
return c;
}
return d;
}
public static boolean isThirdLargest(int a, int b, int c, int d) {
int z = 3 + ((b - a) >> 31) + ((c - a) >> 31) + ((d - a) >> 31);
// z = number of other parameters that are >= a. Note that all of the
// shift operations will return either 0 or -1.
int y = 3 + ((a - b) >> 31) + ((a - c) >> 31) + ((a - d) >> 31);
// y = number of other parameters that are <= a
int x = -y >>> 31;
// x = 1 if there are any other parameters <= a, 0 if not. Note that
// x can be 0 only if z == 3.
int w = z & (x << 1);
// This will be 2 if a is the third largest. If z == 2, then x == 1
// and w will be 2. If z == 3, and x == 1, that means that a is the
// smallest but is equal to at least one of the other parameters;
// therefore a is also the third largest. But if x == 0, a is
// strictly smaller than all other parameters and is therefore not the
// third largest.
return w == 2;
}
Note: This may suffer from overflow problems, if there are two numbers that differ by 231 or greater. Converting all the parameters to long should avoid the problem (also all the 31's would be changed to 63), but I haven't tested it.
The solution posted by #Andreas is very clean and readable. There is another solution that is less clean and less efficient. The solution relies on catching errors when dividing by zero. We keep on adding 1 to each number and then use the following expression to see if an error occurred:
1 / (currentNumber - Integer.MAX_VALUE)
The second number that threw an error will be the third largest number out of the four. Even though the code has 4 comparison operators =. It will only run two of these statements: One for the first error, and one for the second error. For a total of two comparison statements. This method works for any set of input integers, both positive and negative.
public class thirdlargest
{
public static void main(String args[])
{
System.out.println("Third highest number: " + thirdHighest(1, 2, 3, 4));
System.out.println("Third highest number: " + thirdHighest(4, 3, 2, 1));
System.out.println("Third highest number: " + thirdHighest(-5, -4, -3, -2));
System.out.println("Third highest number: " + thirdHighest(0, 0, 0, 0));
}
private static int thirdHighest(int a, int b, int c, int d)
{
int testa = a, testb = b, testc = c, testd = d;
int divisionResult;
int numberFound = 0;
while(true)
{
try
{
divisionResult = 1 / (testa++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{
return a;
}
}
try
{
divisionResult = 1 / (testb++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{ return b;
}
}
try
{
divisionResult = 1 / (testc++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{
return c;
}
}
try
{
divisionResult = 1 / (testd++ - Integer.MAX_VALUE);
}
catch(Exception ex)
{
numberFound++;
if(numberFound == 2)
{
return d;
}
}
}
}
}
import java.util.Scanner;
public class TmaxFourNo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter no.'s:");
int w = sc.nextInt();
int x = sc.nextInt();
int y = sc.nextInt();
int z = sc.nextInt();
int m1 = Math.min(Math.max(w, x), Math.max(y, z));
int m2 = Math.max(Math.min(w, x), Math.min(y, z));
if (m1 < m2) {
System.out.println("Tmax=" + m1);
} else {
System.out.println("Tmax=" + m2);
}
sc.close();
}
}

Java: simplest integer hash

I need a quick hash function for integers:
int hash(int n) { return ...; }
Is there something that exists already in Java?
The minimal properties that I need are:
hash(n) & 1 does not appear periodic when used with a bunch of consecutive values of n.
hash(n) & 1 is approximately equally likely to be 0 or 1.
HashMap, as well as Guava's hash-based utilities, use the following method on hashCode() results to improve bit distributions and defend against weaker hash functions:
/*
* This method was written by Doug Lea with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/licenses/publicdomain
*
* As of 2010/06/11, this method is identical to the (package private) hash
* method in OpenJDK 7's java.util.HashMap class.
*/
static int smear(int hashCode) {
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}
So, I read this question, thought hmm this is a pretty math-y question, it's probably out of my league. Then, I ended up spending so much time thinking about it that I actually believe I've got the answer: No function can satisfy the criteria that f(n) & 1 is non-periodic for consecutive values of n.
Hopefully someone will tell me how ridiculous my reasoning is, but until then I believe it's correct.
Here goes: Any binary integer n can be represented as either 1...0 or 1...1, and only the least significant bit of that bitmap will affect the result of n & 1. Further, the next consecutive integer n + 1 will always contain the opposite least significant bit. So, clearly any series of consecutive integers will exhibit a period of 2 when passed to the function n & 1. So then, is there any function f(n) that will sufficiently distribute the series of consecutive integers such that periodicity is eliminated?
Any function f(n) = n + c fails, as c must end in either 0 or 1, so the LSB will either flip or stay the same depending on the constant chosen.
The above also eliminates subtraction for all trivial cases, but I have not taken the time to analyze the carry behavior yet, so there may be a crack here.
Any function f(n) = c*n fails, as the LSB will always be 0 if c ends in 0 and always be equal to the LSB of n if c ends in 1.
Any function f(n) = n^c fails, by similar reasoning. A power function would always have the same LSB as n.
Any function f(n) = c^n fails, for the same reason.
Division and modulus were a bit less intuitive to me, but basically, the LSB of either option ends up being determined by a subtraction (already ruled out). The modulus will also obviously have a period equal to the divisor.
Unfortunately, I don't have the rigor necessary to prove this, but I believe any combination of the above operations will ultimately fail as well. This leads me to believe that we can rule out any transcendental function, because these are implemented with polynomials (Taylor series? not a terminology guy).
Finally, I held out hope on the train ride home that counting the bits would work; however, this is actually a periodic function as well. The way I thought about it was, imagine taking the sum of the digits of any decimal number. That sum obviously would run from 0 through 9, then drop to 1, run from 1 to 10, then drop to 2... It has a period, the range just keeps shifting higher the higher we count. We can actually do the same thing for the sum of the binary digits, in which case we get something like: 0,1,1,2,2,....5,5,6,6,7,7,8,8....
Did I leave anything out?
TL;DR I don't think your question has an answer.
[SO decided to convert my "trivial answer" to comment. Trying to add little text to it to see if it can be fooled]
Unless you need the ranger of hashing function to be wider..
The NumberOfSetBits function seems to vary quite a lot more then the hashCode, and as such seems more appropriate for your needs. Turns out there is already a fairly efficient algorithm on SO.
See Best algorithm to count the number of set bits in a 32-bit integer.
I did some experimentation (see test program below); computation of 2^n in Galois fields, and floor(A*sin(n)) both did very well to produce a sequence of "random" bits. I tried multiplicative congruential random number generators and some algebra and CRC (which is analogous of k*n in Galois fields), none of which did well.
The floor(A*sin(n)) approach is the simplest and quickest; the 2^n calculation in GF32 takes approx 64 multiplies and 1024 XORs worstcase, but the periodicity of output bits is extremely well-understood in the context of linear-feedback shift registers.
package com.example.math;
public class QuickHash {
interface Hasher
{
public int hash(int n);
}
static class MultiplicativeHasher1 implements Hasher
{
/* multiplicative random number generator
* from L'Ecuyer is x[n+1] = 1223106847 x[n] mod (2^32-5)
* http://dimsboiv.uqac.ca/Cours/C2012/8INF802_Hiv12/ref/paper/RNG/TableLecuyer.pdf
*/
final static long a = 1223106847L;
final static long m = (1L << 32)-5;
/*
* iterative step towards computing mod m
* (j*(2^32)+k) mod (2^32-5)
* = (j*(2^32-5)+j*5+k) mod (2^32-5)
* = (j*5+k) mod (2^32-5)
* repeat twice to get a number between 0 and 2^31+24
*/
private long quickmod(long x)
{
long j = x >>> 32;
long k = x & 0xffffffffL;
return j*5+k;
}
// treat n as unsigned before computation
#Override public int hash(int n) {
long h = a*(n&0xffffffffL);
long h2 = quickmod(quickmod(h));
return (int) (h2 >= m ? (h2-m) : h2);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
/**
* computes (2^n) mod P where P is the polynomial in GF2
* with coefficients 2^(k+1) represented by the bits k=31:0 in "poly";
* coefficient 2^0 is always 1
*/
static class GF32Hasher implements Hasher
{
static final public GF32Hasher CRC32 = new GF32Hasher(0x82608EDB, 32);
final private int poly;
final private int ofs;
public GF32Hasher(int poly, int ofs) {
this.ofs = ofs;
this.poly = poly;
}
static private long uint(int x) { return x&0xffffffffL; }
// modulo GF2 via repeated subtraction
int mod(long n) {
long rem = n;
long q = uint(this.poly);
q = (q << 32) | (1L << 31);
long bitmask = 1L << 63;
for (int i = 0; i < 32; ++i, bitmask >>>= 1, q >>>= 1)
{
if ((rem & bitmask) != 0)
rem ^= q;
}
return (int) rem;
}
int mul(int x, int y)
{
return mod(uint(x)*uint(y));
}
int pow2(int n) {
// compute 2^n mod P using repeated squaring
int y = 1;
int x = 2;
while (n > 0)
{
if ((n&1) != 0)
y = mul(y,x);
x = mul(x,x);
n = n >>> 1;
}
return y;
}
#Override public int hash(int n) {
return pow2(n+this.ofs);
}
#Override public String toString() {
return String.format("GF32[%08x, ofs=%d]", this.poly, this.ofs);
}
}
static class QuickHasher implements Hasher
{
#Override public int hash(int n) {
return (int) ((131111L*n)^n^(1973*n)%7919);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
// adapted from http://www.w3.org/TR/PNG-CRCAppendix.html
static class CRC32TableHasher implements Hasher
{
final private int table[];
static final private int polyval = 0xedb88320;
public CRC32TableHasher()
{
this.table = make_table();
}
/* Make the table for a fast CRC. */
static public int[] make_table()
{
int[] table = new int[256];
int c;
int n, k;
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if ((c & 1) != 0)
c = polyval ^ (c >>> 1);
else
c = c >>> 1;
}
table[n] = (int) c;
}
return table;
}
public int iterate(int state, int i)
{
return this.table[(state ^ i) & 0xff] ^ (state >>> 8);
}
#Override public int hash(int n) {
int h = -1;
h = iterate(h, n >>> 24);
h = iterate(h, n >>> 16);
h = iterate(h, n >>> 8);
h = iterate(h, n);
return h ^ -1;
}
#Override public String toString() { return getClass().getSimpleName(); }
}
static class TrigHasher implements Hasher
{
#Override public String toString() { return getClass().getSimpleName(); }
#Override public int hash(int n) {
double s = Math.sin(n);
return (int) Math.floor((1<<31)*s);
}
}
private static void test(Hasher hasher) {
System.out.println(hasher+":");
for (int i = 0; i < 64; ++i)
{
int h = hasher.hash(i);
System.out.println(String.format("%08x -> %08x %%2 = %d",
i,h,(h&1)));
}
for (int i = 0; i < 256; ++i)
{
System.out.print(hasher.hash(i) & 1);
}
System.out.println();
analyzeBits(hasher);
}
private static void analyzeBits(Hasher hasher) {
final int N = 65536;
final int maxrunlength=32;
int[][] runs = {new int[maxrunlength], new int[maxrunlength]};
int[] count = new int[2];
int prev = -1;
System.out.println("Run length test of "+N+" bits");
for (int i = 0; i < maxrunlength; ++i)
{
runs[0][i] = 0;
runs[1][i] = 0;
}
int runlength_minus1 = 0;
for (int i = 0; i < N; ++i)
{
int b = hasher.hash(i) & 0x1;
count[b]++;
if (b == prev)
++runlength_minus1;
else if (i > 0)
{
++runs[prev][runlength_minus1];
runlength_minus1 = 0;
}
prev = b;
}
++runs[prev][runlength_minus1];
System.out.println(String.format("%d zeros, %d ones", count[0], count[1]));
for (int i = 0; i < maxrunlength; ++i)
{
System.out.println(String.format("%d runs of %d zeros, %d runs of %d ones", runs[0][i], i+1, runs[1][i], i+1));
}
}
public static void main(String[] args) {
Hasher[] hashers = {
new MultiplicativeHasher1(),
GF32Hasher.CRC32,
new QuickHasher(),
new CRC32TableHasher(),
new TrigHasher()
};
for (Hasher hasher : hashers)
{
test(hasher);
}
}
}
The simplest hash for int value is the int value.
See Java Integer class
public int hashCode()
public static int hashCode(int value)
Returns:
a hash code value for this object, equal to the primitive int value represented by this Integer object.

simplifying fractions in Java

My task is to develop a rational class. If 500 and 1000 are my inputs, then (½) must be my output.
I have written a program on my own to find it.
Is there another best way to find the solution, or my program is already the best one?
public class Rational {
public static void main(String[] args){
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
int temp1 = n1;
int temp2 = n2;
while (n1 != n2){
if(n1 > n2)
n1 = n1 - n2;
else
n2 = n2 - n1;
}
int n3 = temp1 / n1 ;
int n4 = temp2 / n1 ;
System.out.print("\n Output :\n");
System.out.print(n3 + "/" + n4 + "\n\n" );
System.exit(0);
}
}
Interesting question. Here's some executable code that does it with minimal code:
/** #return the greatest common denominator */
public static long gcd(long a, long b) {
return b == 0 ? a : gcd(b, a % b);
}
public static String asFraction(long a, long b) {
long gcd = gcd(a, b);
return (a / gcd) + "/" + (b / gcd);
}
// Some tests
public static void main(String[] args) {
System.out.println(asFraction(500, 1000)); // "1/2"
System.out.println(asFraction(17, 3)); // "17/3"
System.out.println(asFraction(462, 1071)); // "22/51"
}
Bonus methods:
/** #return the lowest common multiple */
public static long lcm(long a, long b) {
return a * b / gcd(a, b);
}
/** #return the greatest common denominator */
public static long gcd(List<? extends Number> numbers) {
return numbers.stream().map(Number::longValue).reduce((a, b) -> gcd(a, b)).orElseThrow(NoSuchElementException::new);
}
/** #return the lowest common multiple */
public static long lcm(List<? extends Number> numbers) {
return numbers.stream().map(Number::longValue).reduce((a, b) -> lcm(a, b)).orElseThrow(NoSuchElementException::new);
}
You need the GCD. Either use BigInteger like Nathan mentioned or if you can't, use your own.
public int GCD(int a, int b){
if (b==0) return a;
return GCD(b,a%b);
}
Then you can divide each number by the GCD, like you have done above.
This will give you an improper fraction. If you need a mixed fraction then you can get the new numbers. Example if you had 1500 and 500 for inputs you would end up with 3/2 as your answer. Maybe you want 1 1/2. So you just divide 3/2 and get 1 and then get the remainder of 3/2 which is also 1. The denominator will stay the same.
whole = x/y;
numerator x%y;
denominator = y;
In case you don't believe me that this works, you can check out
http://en.wikipedia.org/wiki/Euclidean_algorithm
I just happen to like the recursive function because it's clean and simple.
Your algorithm is close, but not exactly correct. Also, you should probably create a new function if you want to find the gcd. Just makes it a little cleaner and easier to read. You can also test that function as well.
For reference, what you implemented is the original subtractive Euclidean Algorithm to calculate the greatest common divisor of two numbers.
A lot faster version is using the remainder from integer division, e.g. % instead of - in your loop:
while (n1 != 0 && n2 != 0){
if(n1 > n2)
n1 = n1 % n2;
else
n2 = n2 % n1;
}
... and then make sure you will use the one which is not zero.
A more streamlined version would be this:
while(n1 != 0) {
int old_n1 = n1;
n1 = n2 % n1;
n2 = old_n1;
}
and then use n1. Matt's answer shows a recursive version of the same algorithm.
You should make this class something other than a container for static methods. Here is a skeleton
import java.math.BigInteger;
public class BigRational
{
private BigInteger num;
private BigInteger denom;
public BigRational(BigInteger _num, BigInteger _denom)
{
//put the negative on top
// reduce BigRational using the BigInteger gcd method
}
public BigRational()
{
this(BigInteger.ZERO, BigInteger.ONE);
}
public BigRational add(BigRational that)
{
// return this + that;
}
.
.
.
//etc
}
}
I have a similar BigRational class I use. The GcdFunction is makes use of BigInteger's gcd function:
public class GcdFunction implements BinaryFunction {
#Override
public BigRational apply(final BigRational left, final BigRational right) {
if (!(left.isInteger() && right.isInteger())) {
throw new EvaluationException("GCD can only be applied to integers");
}
return new BigRational(left.getNumerator().gcd((right.getNumerator())));
}
}
BigRational contains a BigInteger numerator and denominator. isInteger() returns true if the simplified ratio's denominator is equal to 1.
Noticed that all answers here do not mention the iterative implementation of the Euclidean algorithm.
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return a;
}
I implemented the validation test like #Bohemian and both recursive and iterative implementations work the same, however the iterative approach is faster. The benchmarks show small improvement, but it's improvement and overall it feels better to not use the stack so much and depend fully on the Java VM to optimize its implementation depend. Even if the benchmarks would be the same I would still feel better with the iterative as that would be more portable while the recursive was only optimized by my host Java, but might not be so well optimized on other's VMs.
Benchmark results (code is on the bottom of the answer):
(100 000 000 iterations)
gcd recursive: 3113ms
gcd iterative: 3079ms
gcd BigInteger: 13672ms
Signs:
One difference I noticed (besides the performance) is that the signs are handled differently, hand implemented Euclidean algorithm gcdLong and my gcdLongIterative behave the same, but both are different from BigInteger which tends to 'keep' the signs as they are. It seems that in essence the gcd and gcdLongIterative can return a negative number, while BigInteger will return positive only.
gcdLong and gcdLongIterative implementations:
-4/-2 => 2/1
-10/200 => 1/-20
10/-200 => 1/-20
BigInteger implementation tends to 'keep' the signs:
-4/-2 => -2/-1
-10/200 => -1/20
10/-200 => 1/-20
All results when used for fractions are valid, but it's worth considering post-process normalization if you expect the numbers in a specific 'style'.
For example, if the BigInteger behavior is preferred, then just returning absolute value should be enough, like here:
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return Math.abs(a);
}
Performance:
Inspired by #Xabster benchmark (from Java: Get Greatest Common Divisor, which method is better?) I extended it to test all 3 implementations, in some cases both recursive and iterative were performing the same, however the iterative is slightly faster in most of the cases.
The benchmark code:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class Test {
private static final int BENCHMARK_ITERATIONS = 100000000;
public static long gcdLong(long a, long b) {
return b == 0 ? a : gcdLong(b, a % b);
}
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return a;
}
public static long gcdLongBigInteger(long a, long b) {
return BigInteger.valueOf(a).gcd(BigInteger.valueOf((b))).longValue();
}
public static String asFractionGcdLong(long a, long b) {
long gcd = gcdLong(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static String asFractionGcdLongIterative(long a, long b) {
long gcd = gcdLongIterative(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static String asFractionGcdLongBI(long a, long b) {
long gcd = gcdLongBigInteger(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static void test(String actual, String expected) {
boolean match = expected.equals(actual);
if (match) {
System.out.println("Actual and expected match=" + expected);
} else {
System.out.println("NO match expected=" + expected + " actual=" + actual);
}
}
public static class Values {
public long a;
public long b;
public String expected;
public Values(long a, long b, String expected) {
this.a = a;
this.b = b;
this.expected = expected;
}
}
public static void validityTest() {
List<Values> vals = new LinkedList<Values>(Arrays.asList(
new Values(500, 1000, "1/2"),
new Values(17, 3, "17/3"),
new Values(462, 1071, "22/51"),
new Values(-4, -2, "2/1"),
new Values(-10, 200, "1/-20"),
new Values(10, -200, "1/-20")
));
System.out.println("------ Recursive implementation -------");
vals.forEach(v -> test(asFractionGcdLong(v.a, v.b), v.expected));
System.out.println();
System.out.println("------ Iterative implementation -------");
vals.forEach(v -> test(asFractionGcdLongIterative(v.a, v.b), v.expected));
System.out.println();
System.out.println("------ BigInteger implementation -------");
vals.forEach(v -> test(asFractionGcdLongBI(v.a, v.b), v.expected));
System.out.println();
}
public static void benchMark() {
Random r = new Random();
long[] nums = new long[BENCHMARK_ITERATIONS];
for (int i = 0 ; i < nums.length ; i++) nums[i] = r.nextLong();
System.out.println("Waming up for benchmark...");
for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);
System.out.println("Started benchmark...");
long s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
System.out.println("recursive: " + (System.currentTimeMillis() - s) + "ms");
s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
System.out.println("iterative: " + (System.currentTimeMillis() - s) + "ms");
s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);
System.out.println("BigInteger: " + (System.currentTimeMillis() - s) + "ms");
}
public static void main(String[] args) {
validityTest();
benchMark();
}
}

Categories

Resources