I am trying to create a bit vector backed by an int[].
So I have the following code:
public class BitVector {
int[] vector = new int[1 << 16];
public void setBit(int nextInt) {
nextInt = nextInt & 0xFFFF;
int pos = nextInt / 32;
int offset = nextInt % 32;
vector[pos] |= (1 << offset);
}
public int findClearedBit() {
for(int i = 0; i < vector.length; i++){
for(int j = 0; j < 8; j++){
if((vector[i] & (1 << j)) == 0)
return i * 32 + j;
}
}
return -1;
}
}
I know that perhaps I should have used byte[] instead etc but I was wondering why this way it does not work.
The idea is that I pass in int from a stream and keep the lower 16 bits and mark the corresponding bit as set. So when I iterate over the vector I will find the number (indicate by the lower 16 bits) missing.
But I get wrong result. So I believe my handing is wrong.
Any ideas?
Update:
I have a stream of 32-bit integers. As I read them in I try to mark a number missing by using the lower 16-bits and setting the bitvector (code posted).
I also try to find the upper 16 bits missing reading the stream a second time.
So while the missing number is: 231719592 = (1101110011111100001010101000) = (3535-49832)
When I read the stream I don't get 49832 as the missing lower bits but 65536
Update2:
public int findMissingInt(File f)throws Exception{
Scanner sc = new Scanner(f);
int SIZE = 1 << 16;
int[] occurences = new int[SIZE];
while(sc.hasNext()){
occurences[getIdx(sc.nextInt())]++;
}
int missingUpper = -1;
for(int i = 0; i < occurences.length; i++){
if(occurences[i] < SIZE){
System.out.println("Found upper bits:"+i);
missingUpper = i;
break;
}
}
if(missingUpper == -1){
return -1;
}
//Arrays.fill(occurences, 0); //I reused this. Bellow changed after answer of Peter de Rivaz
BitVector v = new BitVector(new int[1 << (16-5)]);
sc = new Scanner(f);
while(sc.hasNext()){
v.setBit(sc.nextInt());
}
int missingLower = v.findClearedBit();
System.out.println("Lower bits:"+missingLower);
return createNumber(missingUpper, missingLower);
}
private int createNumber(int missingUpper, int missingLower) {
int result = missingUpper;
result = result << 16;
return result | missingLower;
}
public int getIdx(int nextInt) {
return (nextInt >>> 16);
}
I get:
Missing number=231719592
Found upper bits:3535 //CORRECT
Lower bits:-1 //WRONG
Actual missing number=-1 //WRONG
I think there are two problems:
Your array has 65536 entries, but you store 32 bits in each entry, so you only need 65536/32 entries in it.
You store 32 bits in each int, but only check j from 0 to 7 when finding gaps
The first bug means that your program reports 65536 as a missing 16bit number.
The second bug means that your program does not spot the missing number.
i.e. change
int[] vector = new int[1 << 16];
to
int[] vector = new int[1 << (16-5)];
and change
for(int j = 0; j < 8; j++)
to
for(int j = 0; j < 32; j++)
EDIT
Judging from the comments, the question is actually how to find a missing number with limited RAM. The answer to this question can be found here on stackoverflow.
There is an additional bug in the higher level code.
During the second pass that populates the bitset, you should only include numbers that have the matching upper bits.
i.e. change
v.setBit(sc.nextInt());
to something like
int nx = sc.nextInt();
if (getIdx(nx)==missingUpper)
v.setBit(nx);
Related
Given a binary String which represents the target state. Minimum number of flips needed to convert a same size Binary String (with all 0’s) to target state. A flip also causes all the right bits to be flipped.
e.g.
Input : 00101 (Represents Target)
Output : 3
Explanation :
00000 -> 00111 -> 00100 -> 00101
Two observations:
Flips are commutative. You'll get the same result regardless of what order you do them in.
At some point you have to flip the most significant bit that doesn't match
This gives us a handy greedy argument. We will always get the optimal solution by flipping the leftmost bit that needs to be flipped. At some point we have to flip that bit, and the order doesn't matter so we might as well do it first.
Implementing this to be O(N) can be tricky - if we flip everything naively we end up with an O(N) flip which gives an O(N^2) solution. We can note that in determining the true value of the current bit, we only care about the number of flips that have already occurred. If this number is odd then the value of that bit is flipped. Otherwise it is unchanged.
We can then make a final observation to make life a lot easier:
Flips cancel each other out. Instead of asking how many flips it takes to get from 0 to the target, let's ask how many flips it takes to get from the target to 0. Whenever the true value of a bit is not equal to zero, we simply add a flip.
Pseudocode:
result = 0
// most to least significant
for bit in bits:
if result%2 == 0:
if bit != 0: result += 1
else:
if not bit != 0: result += 1
print(result)
And to be more succinct:
bits = [0, 0, 1, 0, 1]
result = 0
for bit in bits: result += (result%2)^bit
print(result)
Output:
3
Input : 00101 (Represents Target)
Output : 3
Explanation :
00000 -> 00111 -> 00100 -> 00101
static int minFlip(String arr) {
String s = "00000";
int i;
char[] original = s.toCharArray();
char[] bits = arr.toCharArray();
int result = 0;
for (i = 0; i < bits.length;) {
if (bits[i] != original[i]) {
for (int j = i; j < original.length; j++) {
if (original[j] == '0') {
original[j] = '1';
} else {
original[j] = '0';
}
}
result++;
}
i++;
}
return result;
}
Thanks, #Primusa for the answer. Below is the code in Java for #Primusa 's answer:
public static int getFlipsCount(String s) {
int result = 0;
int[] arr = new int[s.length()];
for (int i = 0; i < s.length(); i++) {
arr[i] = Integer.valueOf(s.charAt(i) + "");
}
for (int i = 0; i < arr.length; i++) {
result += (result % 2) ^ arr[i];
}
return result;
}
In case someone wonder how to do it in cpp here's the minimal solution:
#include <iostream>
using namespace std;
int theFinalProblem(string target)
{
int result=0;
for(int i=0;i<target.size();i++)
if(result%2==0 && target[i] || target[i] =='0')
++result;
return result;
}
int main() {
cout<<theFinalProblem("1010");
return 0;
}
to the point.
I don't know what make my function error but here when i want to convert an int Array to ASCII character, i got some errors which says
java.lang.OutOfMemoryError: Failed to allocate a 51529974 byte allocation with 4194304 free bytes and 30MB
I think my function doesn't right enough to convert it.
Here is my function :
public static String[] DectoASCII(int[] resultXORDec,int jumKat) {
int length = jumKat;
String ASCIIfromDec[] = new String[jumKat];
for(int i=0;i<jumKat;i++) {
StringBuilder builder = new StringBuilder(length);
for (int j = length - 1; j >= 0; i--) {
builder.append((char) ((resultXORDec[j] >> (8 * i)) & 0xFF));
}
ASCIIfromDec[i]=builder.toString();
Log.d("ascifrom",ASCIIfromDec[i]);
}
return ASCIIfromDec;
}
}
Please master, help me. Is there any other way to convert int (Decimal) to ASCII code?
Thanks..
Well, I guess the j index does not change in this loop:
for (int j = length - 1; j >= 0; i--) {
builder.append((char) ((resultXORDec[j] >> (8 * i)) & 0xFF));
}
thus you have an infinite loop, so builder gets bigger and bigger.
I want to find all possible binary permutations with a given number of ones in Java:
x is the desired number of ones in each sequence
n is the desired length of each sequence
For an example:
x=2, n=4
Output: 1100, 0011, 1010, 1001, 0101, 0110
I'm searching for an elegant and fast way to do this. Can you help me?
I've tested eboix solution in Print list of binary permutations but it is unfortunately too slow because the algorithm in this example is searching for all 2^n binary permutations.
I want to find sequences with a length of 50 or 100.
First of all, you're missing 0110 as an output case.
It's fairly intuitive that there are n choose x possibilities. You're finding all valid arrangements of x identical items among n total slots. So you can find the total number of sequences in O(1).
As a hint, try simply finding all permutations of the bitstring consisting of x ones followed n - x zeros.
To specifically address the problem, try creating a recursive algorithm that decides at every ith iteration to either include 1 or 0. If 1 is included, you need to decrement the count of 1's available for the rest of the string.
Actually, there may be an elegant way, but no fast way to do this. The number of string permutations is given by the binomial coefficient (see https://en.wikipedia.org/wiki/Binomial_coefficient). For example, x=10, n= 50 gives over 10 million different strings.
Here is just a basic version that will generate your desired output. Please work on it to make it more accurate/efficient -
This will not generate all the combinations, but you will get the idea of how to do it. Off course, for all the possible combinations generated by this, you will have to generate all the other possible combinations.
public class Test {
static int iter = 0;
public static void main(String args[]){
int n = 50;
int x = 5;
byte[] perms = new byte[n];
for(int i=0; i<x; i++){
perms[i] = 1;
}
print(perms);
for(int j=x-1; j>=0; j--){
for(int i=1; i<(n/2-j); i++){
iter++;
swap(perms, j, i);
}
}
}
public static void swap(byte[] perms, int pos, int by){
byte val = perms[pos+by];
perms[pos+by] = perms[pos];
perms[pos] = val;
print(perms);
val = perms[pos+by];
perms[pos+by] = perms[pos];
perms[pos] = val;
}
public static void print(byte[] perms){
System.out.println("iter = "+iter);
for(int i=0; i<perms.length; i++){
System.out.print(perms[i]);
}
System.out.println();
for(int i=perms.length-1; i>=0; i--){
System.out.print(perms[i]);
}
System.out.println();
}
}
Another inspiration for you. A dirty version which works. It allocates extra array space (you should adjust size) and uses String Set at the end to remove duplicates.
public static void main(String[] args) {
int x = 2;
int n = 4;
Set<BigInteger> result = new LinkedHashSet<>();
for (int j = x; j > 0; j--) {
Set<BigInteger> a = new LinkedHashSet<>();
for (int i = 0; i < n - j + 1; i++) {
if (j == x) {
a.add(BigInteger.ZERO.flipBit(i));
} else {
for (BigInteger num : result) {
if (num != null && !num.testBit(i) && (i >= (n - j) || num.getLowestSetBit() >= i-1))
a.add(num.setBit(i));
}
}
}
result = a;
}
String zeros = new String(new char[n]).replace("\0", "0");
for (BigInteger i : result) {
String binary = i.toString(2);
System.out.println(zeros.substring(0, n - binary.length()) + binary);
}
}
EDIT: changed the primitives version to use BigInteger instead to support larger n,x values.
I'm working on a program that will fix data corruption given the data and the hash of the correct data. It starts to get slow after about 4 or 5 bits are corrupted even when only dealing with only a few bytes of data, so I thought I would make it iterative instead of recursive. After doing some research, I found that I could use a stack to do so. I'm currently having trouble with finding the correct place to pop the variables off of the stack. Here's the original method.
private static void fixFile(byte[] data, byte[] hash, byte[] correctHash, MessageDigest hasher, long depth)
{
int len = data.length;
outer: for(int i = 0; i < len; i++)
{
byte origVal = data[i];
for(int j = 0; j < 8; j++)
{
data[i] = (byte) (data[i] ^ (1 << j));
if(depth > 1)
fixFile(data, hash, correctHash, hasher, depth - 1);
hash = hasher.digest(data);
if(!Arrays.equals(correctHash, hash))
data[i] = origVal;
else
break outer;
}
}
}
Here's the modified method where I tried to make it iterative.
private static void fixFile(byte[] data, byte[] hash, byte[] correctHash, MessageDigest hasher, long depth)
{
Stack stack = new Stack<Integer>();
int len = data.length;
outer: for(int i = 0; i < len; i++)
{
byte origVal = data[i];
for(int j = 0; j < 8; j++)
{
data[i] = (byte) (data[i] ^ (1 << j));
if(depth > 1)
{
stack.push(depth);
stack.push(i);
stack.push(j);
depth--;
i = -1;
j = 0;
continue outer;
}
else
{
// where do I put this to make it work.
j = stack.pop();
i = stack.pop();
depth = stack.pop();
}
hash = hasher.digest(data);
if(!Arrays.equals(correctHash, hash))
data[i] = origVal;
else
break outer;
}
}
}
I think your recursive approach is ideal for this problem and all the time will be being spent in the digest function.
However, when you are fixing depth bits you can get a factorial(depth) improvement in the speed of the program. (So for 6 bits this will make the program go 6*5*4*3*2*1 = 720 times faster.)
The issue is that your current code currently toggles depth bits in your data, but in any order. i.e. when it toggles three bits it will try toggling bits 1,2,3 and 2,1,3 and 3,1,2 and 3,2,1 and 1,3,2 and 2,3,1 (amongst many other choices). Note that in each of these cases exactly the same 3 bits are toggled so there is no point testing them all.
You can fix this by passing additional parameters to your code saying where the last bit was toggled (i.e. pass in i and j as i_base and j_base), and then only allow your code to toggle new bits if they are at a later position in the data (i.e. if i>i_base || (i==i_base && j>j_base)).
public byte[] d
In this byte array, each byte represents a digits, where d[0] is the least significant digit, and a[d.length-1] is the most significant digit. For example, 543210 is stored as {0,1,2,3,4,5}. The most significant digit can't be a zero;
In the real implementation, this array should be private.
Constructor Detail: AdditionOnlyInt
public AdditionOnlyInt(java.lang.String a)
This is a constructor that construct an AdditionOnlyInt with value presented by the input string. For example, if input a = "00012340", this constructor will set the byte array to have value {0,4,3,2,1}. Note that the leading zeros in the input string should not be stored.
Parameters:a - is a string such as "00012340"
I do not know how to do this constructor does anyone?
I know its very wrong but I tried this
public AdditionOnlyInt(String number) {
int counter = number.length();
number.replace("0","");
data = new byte[number.length()];
int i = 0;
while(i<number.length()) {
data[i] = (byte)number.charAt(counter);
i++;
counter--;
}
}
and I do know converting to byte gives you different values.
You're in luck: only a handful of modifications need to be made to your program. You weren't entirely wrong. :)
First, these three statements are giving you fits:
int counter = number.length();
number.replace("0","");
data = new byte[number.length()];
You get a counter, which is the unbiased String (that is, with zeroes), which will undoubtedly be smaller than the String, without zeroes. You'd also be creating the array with the size of the unbiased list.
Well...it would be if your second statement did something. String is immutable, so anything that's done to modify it would only generate a new String, leaving the old one unmodified. That's fixable by this:
number = number.replace("0", "");
...but in reality, given your input set, it should be fixed by this:
number = String.valueOf(Integer.parseInt(number));
This way, you keep internal zeroes.
Now assuming that your byte[] is actually called data and not d, there's one little issue we have to fix: numbers in terms of a byte are quite large (that is, the character for '7' is 0x37, which is 55).
So we need to bias it. Whatever our byte number is, we need to subtract '0' from it; that is, we need to subtract 48 from it, to give us our correct value. I'll show you what that looks like in a moment.
Now, for your loop:
int i = 0;
while(i<number.length()) {
data[i] = (byte)number.charAt(counter);
i++;
counter--;
}
I'm not sold on the necessity of counter, so let's get rid of it. Now we'll use i from now on. Essentially, what this means is that we have to move charAt from the end of the String to the front of the String, placing the values into the array as such. What that (mostly) looks like is this:
data[i] = (byte) (number.charAt(number.length() - 1 - i);
Pay close attention here - we have to subtract 1 from the length right off the bat, since we don't have a place on the String that's exactly equal to its maximum length. We then subtract i from that, so we get the effect of moving backwards on the String.
That is, for a string of length 10 without zeroes, if we start at i = 0, we get the character at 10 - 1 - 0 = 9, or the last character.
Remember what I said about biasing the result of that, though? After you've got the data, be sure to subtract '0' from it.
data[i] = (byte) (number.charAt(number.length() - 1 - i) - '0';
And really, that's all there is to it. You mostly got it, except the iteration and sanitization was a bit wonky.
public AdditionOnlyInt(String input)
{
//remove trailing 0s
int relevStart = 0;
while(input.charAt(relevStart) == '0')
{
relevStart++;
}
String relevantTerms = input.substring(relevStart);
//flip the remaining chars
int length = relevantTerms.length();
data = new byte[length];
for(int iter = 0; iter < length; iter++)
{
data[iter] = (byte) (relevantTerms.charAt(length - iter - 1) - '0');
}
}
Hope this helps.
Step 1: Check whether its a number by using Integer value = Integer.valueOf(args);
Step 2: convert the Integer into a byte array by calling byte array[] = value.toString().getBytes();
Step 3: the byte array contains the value in forward fashion, So swapping all the values in the array will make the digit reverse as user requested.
for (int i = 0, j = array.length - 1; i < array.length / 2; i++, j--) {
byte temp = array[i];
array[i] = array[j];
array[j] = temp;
}
find the complete program below:
public class AdditionOnlyInt {
public static void main(String[] args) {
// TODO Auto-generated method stub
new AdditionOnlyInt("01010120");
}
public AdditionOnlyInt(String args) {
try {
Integer value = Integer.valueOf(args);
byte array[] = value.toString().getBytes();
for (int i = 0, j = array.length - 1; i < array.length / 2; i++, j--) {
byte temp = array[i];
array[i] = array[j];
array[j] = temp;
}
for (int i = 0; i < array.length; i++) {
System.out.print((char) array[i]);
}
} catch (Exception e) {
}
}
}