I do simple rownumber calculation in InputStream (calc number of NewLines #10)
for (int i = 0; i < readBytes ; i++) {
if ( b[ i + off ] == 10 ) { // New Line (10)
rowCount++;
}
}
Can I do it faster? Without iteration by one byte?
Probably I am looking for some class which able to use CPU specific instructions (simd/sse).
All code:
#Override
public int read(byte[] b, int off, int len) throws IOException {
int readBytes = in.read(b, off, len);
for (int i = 0; i < readBytes ; i++) {
hadBytes = true; // at least once we read something
lastByteIsNewLine = false;
if ( b[ i + off ] == 10 ) { // New Line (10)
rowCount++;
lastByteIsNewLine = (i == readBytes - 1); // last byte in buffer was the newline
}
}
if ( hadBytes && readBytes == -1 && ! lastByteIsNewLine ) { // file is not empty + EOF + last byte was not NewLine
rowCount++;
}
return readBytes;
}
On my system, just moving the lastByteIsNewLine and hasBytes parts out of the loop results in a ~10% improvement*:
public int read(byte[] b, int off, int len) throws IOException {
int readBytes = in.read(b, off, len);
for (int i = 0; i < readBytes ; i++) {
if ( b[ i + off ] == 10 ) {
rowCount++;
}
}
hadBytes |= readBytes > 0;
lastByteIsNewLine = (readBytes > 0 ? b[readBytes+off-1] == 10 : false);
if ( hadBytes && readBytes == -1 && ! lastByteIsNewLine ) {
rowCount++;
}
return readBytes;
}
* 6000ms vs 6700ms for 1,000 iterations on 10MB buffers read from a ByteArrayInputStream filled with arbitrary text.
I started with that other guy's improvements, and hoisted the array index calculation and the field access out of the for loop.
According to my JMH benchmark, this saved another 25%, with "that other guy's" implementation clocking 3.6 ms/op, and this version at 2.7 ms/op. (Here, one operation is reading a ~10 MB ByteArrayInputStream with around 5000 lines of random length).
public int read(byte[] buffer, int off, int len) throws IOException {
int n = in.read(buffer, off, len);
notEmpty |= n > 0;
int count = notEmpty && n < 0 && !trailingLineFeed ? 1 : 0;
trailingLineFeed = (n > 0) && buffer[n + off - 1] == '\n';
for (int max = off + n, idx = off; idx < max;) {
if (buffer[idx++] == '\n') ++count;
}
rowCount += count;
return n;
}
Things that really hurt performance: indexing backward over the array.
Things that don't matter: comparing values with the more readable '\n' instead of 10.
Surprisingly (to me anyway), using only one of these tricks by itself did not seem to improve performance. They only made a difference used together.
You can easily search in readBytes after converting it in String:
String stringBytes = new String(readBytes);
To get the amount of occurrences:
int rowCount = StringUtils.countMatches(stringBytes, "\n");
To only know if the \n is contained in readBytes:
boolean newLineFound = stringBytes.contains("\n");
Well, rather than trying to speed up that one specific portion (which I don't think you can), you can try using a different method. Here's a class which you can use to keep track of the number of rows while reading from an InputStream.
public class RowCounter {
private static final int LF = 10;
private int rowCount = 0;
private int lastByte = 0;
public int getRowCount() {
return rowCount;
}
public void addByte(int b) {
if (lastByte == LF) {
rowCount++;
}
lastByte = b;
}
public void addBytes(byte[] b, int offset, int length) {
if (length <= 0) return;
if (lastByte == LF) rowCount++;
int lastIndex = offset + length - 1;
for (int i = offset; i < lastIndex; i++) {
if (b[i] == LF) rowCount++;
}
lastByte = b[lastIndex];
}
}
Then when reading an InputStream, you can use it like this.
InputStream is = ...;
byte[] b = new byte[...];
int bytesRead;
RowCounter counter = new RowCounter();
while ((bytesRead = is.read(b)) != -1) {
counter.addBytes(b, 0, bytesRead);
}
int rowCount = counter.getRowCount();
or you can easily adapt it to whatever situation you need it for.
Related
You have been given a binary string containing only the characters '1' and '0'.
Calculate how many characters of the string need to be changed in order to make the binary string such that each of its substrings of at least a certain length contains at least one "1" character.
I came to think of the following idea but it fails for many testcases:
public static int minimumMoves(String s, int d) {
int n = s.length();
int i=0, answer = 0;
while(i<n)
{
boolean hasOne = false;
int j=i;
while(j<n && j<i+d)
{
if(s.charAt(j) == '1')
{
hasOne = true;
break;
}
j++;
}
if(!hasOne) {
answer++;
i += d;
}
else i++;
}
return answer;
}
Also my algorithm runs on O(|s|2) time. Can anyone suggest ideas on O(|s|) time?
Just throwing off an idea:
return s.split("(?<=\\G.{" + String.valueof(d) + "})").stream().filter(str -> str.contains("1")).count()
You just need to break ensure there is no run of d zeros.
public static int minimumMoves(String s, int d) {
int result = 0;
int runLength = 0;
for(char c: s.toCharArray()) {
if (c == '0') {
runLength += 1;
if (runLength == d) { // we need to break this run
result += 1;
runLength = 0;
}
} else {
runLength = 0;
}
}
return result;
}
I used the sliding window technique and Deque to solve this. This is my accepted solution:
public static int minimumMoves(String s, int d) {
int n = s.length();
Deque<Character> dq = new LinkedList<>();
int count = 0, answer = 0;
for(int i=0; i<d; i++)
{
if(s.charAt(i) == '1') count++;
dq.addLast(s.charAt(i));
}
if(count == 0) {
answer++;
count++;
dq.removeLast();
dq.addLast('1');
}
int i=d;
while(i<n)
{
if(dq.getFirst() == '1') count--;
dq.removeFirst();
if(s.charAt(i) == '1') count++;
dq.addLast(s.charAt(i));
if(count == 0)
{
answer++;
dq.removeLast();
dq.addLast('1');
count++;
}
i++;
}
return answer;
}
You just need to use a sliding window and a count of 1s so far at each index. Use a sliding window of d and if you don't see any ones so far, update the last index of that window with 1 and increment the result.
Code below:
public static int minimumMoves(String s, int d) {
int n = s.length();
int[] count = new int[n+1];
int res = 0;
for ( int i = 1; i <= d; i++ ) {
if ( s.charAt(i-1) == '1') count[i] = count[i-1]+1;
else count[i] = count[i-1];
}
if ( count[d] == 0 ) {
res++;
count[d] = 1;
}
for ( int i = d+1; i <= n; i++ ) {
if ( s.charAt(i-1) == '0' ) {
count[i] = count[i-1];
int ones = count[i] - count[i-d];
if ( ones == 0 ) {
count[i] = count[i-1] + 1;
res++;
}
} else {
count[i] = count[i-1] + 1;
}
}
return res;
}
Thought of another implementation you can do for this by working from the maximum possible changes (assumes at start that all values are '0' in String), reduce it when it finds a '1' value, and then jump to the next substring start. This allows it to run in O(n) and Ω(n/m) (n = String length, m = Substring length).
public static int minimumMoves(String s, int d)
{
char[] a = s.toCharArray();
//Total possible changes (not counting tail)
if(a.length < d)
return 0;
int t = (int) a.length / d;
//Total possible changes (counting tail)
//int t = (int) Math.ceil((double) a.length / (double) d);
for(int i = 0; i < a.length; i++)
{
if(a[i] == '1')
{
t--;
//Calculate index for start of next substring
i = (i / d + 1) * d - 1;
}
}
return t;
}
I've implemented the Reading wav files in Java in my project (android game) and it works fine.
Now I need to break down the wav file reading into pieces and I don't know what am I doing wrong.
The code runs, and it reads the first part (out of 5), but when trying to read the following parts, the FileInputStream returns -1 and I don't get the logic behind it.
Here's what I have so far:
private List<Float> extractBeats(FileHandle fileHandle) throws Wave.WavFileException, IOException {
List<Float> peaksAppended;
peaksAppended = new ArrayList<Float>();
final FileHandle fileHandleFinal = fileHandle;
for (int i = 0; i < GameSettings.numThreadsAnalyzing; i++) {
final int I = i;
AsyncTask partAnalyzing = new AsyncTask() {
#Override
public List<Float> call() throws Wave.WavFileException, IOException {
final File file = fileHandleFinal.file();
Wave.WavFile wavFile = Wave.WavFile.openWavFile(file);
// Get the number of audio channels in the wav file
final int NUM_CHANNELS = wavFile.getNumChannels();
final int NUM_FRAMES = 1000;
final long totalNumFrames = wavFile.getNumFrames();
final long auxOffset = totalNumFrames / GameSettings.numThreadsAnalyzing;
int offset = (int) auxOffset * I;
if (offset>0){
wavFile.skipFrames(offset);
}
List<Float> peaks;
double[] buffer = new double[NUM_FRAMES * NUM_CHANNELS];
int framesToRead = NUM_FRAMES;
double min = 10;
double max = -10;
// =========================================
// Read file and find out MIN and MAX values
// =========================================
do {
// Read frames into buffer
framesToRead = wavFile.readFrames(buffer, offset, (int) auxOffset, framesToRead);
// Loop through frames and look for minimum and maximum value
for (int s = 0; s < framesToRead * NUM_CHANNELS; s++) {
if (buffer[s] > max) max = buffer[s];
if (buffer[s] < min) min = buffer[s];
}
System.out.println("Buffer_read : " + max + " and min " + min);
}
while (framesToRead != 0);
// Close the wavFile
wavFile.close();
[. . .]//do some other beats extraction stuff
return peaks;
}
};
AsyncExecutor partAnalyzer = new AsyncExecutor(30);
AsyncResult result = partAnalyzer.submit(partAnalyzing);
[. . .]//do some more other beats extraction stuff
}
}
This works fine for the first piece of the song. It reads the first 633000 frames. Now I want it to read the next 633000 frames, but it get stuck into the readSample method.
Here's the sequence running from readFrames method.
public int readFrames(double[] sampleBuffer, int offset, int partSize, int numFramesToRead) throws IOException, WavFileException {
if (ioState != IOState.READING)
throw new IOException("Cannot read from WavFile instance");
for (int f = 0; f < numFramesToRead; f++) {
if (frameCounter == offset + partSize)
return f;
for (int c = 0; c < numChannels; c++) {
sampleBuffer[offset] = floatOffset + (double) readSample() / floatScale;
offset++;
}
frameCounter++;
}
return numFramesToRead;
}
private long readSample() throws IOException, WavFileException {
long val = 0;
for (int b = 0; b < bytesPerSample; b++) {
if (bufferPointer == bytesRead) {
int read = iStream.read(buffer, 0, BUFFER_SIZE);
if (read == -1) throw new WavFileException("Not enough data available");
bytesRead = read;
bufferPointer = 0;
}
int v = buffer[bufferPointer];
if (b < bytesPerSample - 1 || bytesPerSample == 1) v &= 0xFF;
val += v << (b * 8);
bufferPointer++;
}
return val;
}
I tried to use the offset and pass it to the FileInputStream (iStream) but didn't work either. Then, I created the method skipFrames with the following code but also didn't help.
public void skipFrames(int offset){
frameCounter = offset;
}
If solved, I can update the topic with a basic functionallity of the reading wav in pieces, great approach for sound analysis (which it's what I am doing).
Any help would be greatly appreciated.
This code supposed to output the longest run on which a character in a string has a consecutive runs of itself. Though the problem is that it outputs: 8 (which should be 5 instead). I just would like to ask what seems to be the problem regarding this code.
public class Sample {
public static void main(String[] args) {
String setofletters = "aaakkcccccczz"; /* 15 */
int output = runLongestIndex(setofletters);
System.out.println("Longest run that first appeared in index:" + output);
}
public static int runLongestIndex(String setofletters) {
int ctr = 0;
int ctrstor = 0;
int ii = 0;
int output = 0;
// loops until the last character in the string
for (int i = 0; i < setofletters.length() - 1; i++) {
// checks if the letter is the same to the next
if (setofletters.charAt(i) == setofletters.charAt(i++)) {
ctr++;
ii = i++;
// loops until the letter in the index is no longer equal
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
// storing purposes
ctrstor = ctr;
}
// resets the counter
ctr = 0;
}
return output;
}
}
UPDATE Sorry, I misunderstood your question a bit, you need to make the following changes in your code to make it work.(lines with comments)
public static int runLongestIndex(String setofletters){
int ctr = 1; // every character is repeated at least once, so you should initialize it to 1, not 0
int ctrstor = 0;
int ii = 0;
int output = 0;
for (int i = 0; i < setofletters.length() - 1; i++) {
if (i < setofletters.length() - 1 && setofletters.charAt(i) == setofletters.charAt(i+1)) { // i++ is not same as i+1
ctr++;
ii = i+1; // i++ is not same as i+1
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
ctrstor = ctr;
}
ctr = 1; // for the same reason I mentioned above
}
return output;
}
EDIT : the easiest way to write your code is :
public static int runLongestIndex(String setofletters){
int ctr = 1;
int output = 0;
int j=0;
for(int i=0; i<setofletters.length()-1;i++){
j=i;
while(i <setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
i++;
ctr++;
}
if(ctr>output){
output=j;
}
ctr = 1;
}
return output;
}
Why are you assigning i to output? You should assign ctr to output.
change
if(ctr>ctrstor){
output=i;
}
to
if(ctr>ctrstor){
output=ctr;
}
and also I think you should change
if(setofletters.charAt(i)==setofletters.charAt(i++))
to
if(i<setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
and you should intialize ctr to 1 but not 0 because every character is repeated at least once.
I'll give you a Scala implementation for that problem.
Here it is the automatic test (in BDD style with ScalaTest)
import org.scalatest._
class RichStringSpec extends FlatSpec with MustMatchers {
"A rich string" should "find the longest run of consecutive characters" in {
import Example._
"abceedd".longestRun mustBe Set("ee", "dd")
"aeebceeedd".longestRun mustBe Set("eee")
"aaaaaaa".longestRun mustBe Set("aaaaaaa")
"abcdefgh".longestRun mustBe empty
}
}
Following is the imperative style implementation, with nested loops and mutable variables as you would normally choose to do in Java or C++:
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
val chunks = mutable.Set.empty[String]
val ilen = string.length
var gmax = 0
for ((ch, curr) <- string.zipWithIndex) {
val chunk = mutable.ListBuffer(ch)
var next = curr + 1
while (next < ilen && string(next) == ch) {
chunk += string(next)
next = next + 1
}
gmax = chunk.length max gmax
if (gmax > 1) chunks += chunk.mkString
}
chunks.toSet.filter( _.length == gmax )
}
}
}
Following is a functional-style implementation, hence no variables, no loops but tail recursion with result accumulators and pattern matching to compare each character with the next one (Crazy! Isn't it?):
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
def recurse(chars: String, chunk: mutable.ListBuffer[Char], chunks: mutable.Set[String]): Set[String] = {
chars.toList match {
case List(x, y, _*) if (x == y) =>
recurse(
chars.tail,
if (chunk.isEmpty) chunk ++= List(x, y) else chunk += y,
chunks
)
case Nil =>
// terminate recursion
chunks.toSet
case _ => // x != y
recurse(
chars.tail,
chunk = mutable.ListBuffer(),
chunks += chunk.mkString
)
}
}
val chunks = recurse(string, mutable.ListBuffer(), mutable.Set.empty[String])
val max = chunks.map(_.length).max
if (max > 0) chunks.filter( _.length == max ) else Set()
}
}
}
For example, for the given "aeebceeedd" string, both implementations above will build the following set of chunks (repeating characters)
Set("ee", "eee", "dd")
and they will filter those chunks having the maximum length (resulting "eee").
This code should work for any length of string sequence.
public class LongestStringSequqnce {
static String myString = "aaaabbbbcccchhhhiiiiibbbbbbbbbccccccc";
static int largestSequence = 0;
static char longestChar = '\0';
public static void main(String args[]) {
int currentSequence = 1;
char current = '\0';
char next = '\0';
for (int i = 0; i < myString.length() - 1; i++) {
current = myString.charAt(i);
next = myString.charAt(i + 1);
// If character's are in sequence , increase the counter
if (current == next) {
currentSequence += 1;
} else {
if (currentSequence > largestSequence) { // When sequence is
// completed, check if
// it is longest
largestSequence = currentSequence;
longestChar = current;
}
currentSequence = 1; // re-initialize counter
}
}
if (currentSequence > largestSequence) { // Check if last string
// sequence is longest
largestSequence = currentSequence;
longestChar = current;
}
System.out.println("Longest character sequence is of character "
+ longestChar + " and is " + largestSequence + " long");
}
}
Source : http://www.5balloons.info/program-java-code-to-find-longest-character-sequence-in-a-random-string/
if(ctr>ctrstor){
output=i;
}
//storing purposes
ctrstor=ctr;
This looks like the problem. So if you find 8 consecutive characters, it will set output to 8, and proceed. The next time thru, it finds 3 consecutive characters, so doesn't set output, but sets ctrstor. Next time thru it finds 4 consecutive characters, and this will set output to 4
There are few traps in the code that your logic felt in:
Code incorrectly assumes that there is always next character to compare current one.
This fails for string like "a" or the last character in any string.
Code does not store the max count of characters but only the max index (i).
MaxCount is needed to compare the next chars sequence size.
Loop for and loop while repeat the same subset of characters.
Also variable name style makes it harder to understand the code.
After correcting above
public static int runLongestIndex(String setofletters) {
int maxCount = 0;
int maxIndex = 0;
// loops each character in the string
for (int i = 0; i < setofletters.length() - 1; ) {
// new char sequence starts here
char currChar = setofletters.charAt(i);
int count = 1;
int index = i;
while ( (index < setofletters.length() - 1) &&
(currChar == setofletters.charAt(++index)) ) {
count++;
}
if (count > maxCount) {
maxIndex = i;
maxCount = count;
}
i = index;
}
return maxIndex;
}
See Java DEMO
I think you don't need an internal loop:
public static int runLongestIndex(String setofletters) {
if (setofletters == null || setofletters.isEmpty()) {
return -1;
}
int cnt = 1;
char prevC = setofletters.charAt(0);
int maxCnt = 1;
//char maxC = prevC;
int maxRunIdx = 0;
int curRunIdx = 0;
for (int i = 1; i < setofletters.length(); i++){
final char c = setofletters.charAt(i);
if (prevC == c) {
cnt++;
} else {
if (cnt > maxCnt) {
maxCnt = cnt;
//maxC = prevC;
maxRunIdx = curRunIdx;
}
cnt = 1;
curRunIdx = i;
}
prevC = c;
}
if (setofletters.charAt(setofletters.length() - 1) == prevC) {
if (cnt > maxCnt) {
//maxC = prevC;
maxCnt = cnt;
maxRunIdx = curRunIdx;
}
}
return maxRunIdx;
}
and this code:
System.out.println(runLongestIndex("aaakkcccccczz"));
gives you
5
This is how a "colleague" of mine is understanding to write readable code in order to solve this problem, even if this is working :)
public static int count (String str) {
int i = 0;
while(i < str.length()-1 && str.charAt(i)==str.charAt(i+1))
i ++;
return ++i;
}
public static int getLongestIndex(String str){
int output = 0;
for(int i=0, cnt = 1, counter = 0 ; i<str.length() - 1;i += cnt, cnt = count(str.substring(i)), output = (counter = (cnt > counter ? cnt : counter)) == cnt ? i : output);
return output;
}
int indexOfLongestRun(String str) {
char[] ar = str.toCharArray();
int longestRun = 0;
int lastLongestRun = 0;
int index = 0;
for(int i = ar.length-1; i>0; i--){
if(ar[i] == ar[i-1]){
longestRun++;
}else{
if(longestRun > lastLongestRun){
lastLongestRun = longestRun;
longestRun = 0;
index = i;
}
}
}
return index;
Well, the solution a bit depends on the additional requirements. Here is the code which returns the FIRST longest sequence of a repeated character int the given string, meaning if you have a second sequence with the same length you never get it out :(. But still, this is a simple and clear solution here, so good news - it works! :)
string = 'abbbccddddddddeehhhfffzzzzzzzzdddvyy'
longest_sequence = ''
for i in range(len(string)):
is_sequence = True
ch_sequence = ''
while is_sequence:
ch_sequence += string[i]
if i+1 < len(string) and string[i]==string[i+1]:
i += 1
else:
is_sequence = False
if len(ch_sequence) > len(longest_sequence):
longest_sequence = ch_sequence
print (longest_sequence)
#Paolo Angioletti already provided an answer using Scala, but it's more complicated than it needs to be. The idea is not very different from Run-length encoding. Time complexity O(n).
def longestConsecutive(s: String): (Char, Int) = {
Iterator.iterate(('\u0000', 0, 0)) { case (ch, longestRun, i) =>
val run = (i until s.length)
.takeWhile(s(_) == s(i))
.size
if (run > longestRun) (s(i), run, i + run)
else (ch, longestRun, i + run)
}
.dropWhile(i => s.isDefinedAt(i._3))
.take(1)
.map(x => (x._1, x._2))
.next()
}
Tested with:
("s", "ch", "n")
----------------
("", '\u0000', 0),
("a", 'a', 1),
("aabcddbbbea", 'b', 3),
("abcddbbb", 'b', 3),
("cbccca", 'c', 3)
#include <iostream>
#include<algorithm>
using namespace std;
int main() {
string s="abbcccccbbffffffffff";
//cin>>s;
int count=1;
int maxcount=1;
int start=0;
int ps=0;
for (int i=0;i<s.size()-1;i++)
{
if(s.at(i)==s.at(i+1))
{
count +=1;
maxcount=max(maxcount,count);
}
else
{
ps=max(ps,start+count);
count =1;
start=i;
}
}
for(int i=1;i<=maxcount;i++)
{
cout<<s.at(i+ps);
}
// your code goes here
return 0;
}
This is the simplest I can think of and it will print the number of the longest sequenced identical characters in a one line string.
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
scanner.close();
int count = 0;
int curCount = 1;
for (int i = 0; i < s.length() -1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
curCount++;
if (curCount > count) {
count = curCount;
}
}else {
if (curCount > count) {
count = curCount;
}
curCount = 1;
}
}
System.out.println(count);
}
The function below takes two BitSets, makes a copy of the first (it must not be overridden), intersects the copy with the second (bitwise AND) and returns the cardinality of the result.
public int getIntersectionSize(BitSet bits1, BitSet bits2) {
BitSet copy = (BitSet) bits1.clone();
copy.and(bits2);
return copy.cardinality();
}
I'm interested if this code can be sped up? This function is called billion of times so even a microsecond speed up makes sense plus I'm curious about the fastest possible code.
If you're going to use each BitSet several times, it could be worthwhile to create a long array corresponding to each BitSet. For each BitSet:
long[] longs = bitset.toLongArray();
Then you can use the following method, which avoids the overhead of creating a cloned BitSet. (This assumes that both arrays are the same length).
int getIntersectionSize(long[] bits1, long[] bits2) {
int nBits = 0;
for (int i=0; i<bits1.length; i++)
nBits += Long.bitCount(bits1[i] & bits2[i]);
return nBits;
}
Here is an alternative version, but I'm not sure if it is really faster, depends on nextSetBit.
public int getIntersectionsSize(BitSet bits1, BitSet bits2) {
int count = 0;
int i = bits1.nextSetBit(0);
int j = bits2.nextSetBit(0);
while (i >= 0 && j >= 0) {
if (i < j) {
i = bits1.nextSetBit(i + 1);
} else if (i > j) {
j = bits2.nextSetBit(j + 1);
} else {
count++;
i = bits1.nextSetBit(i + 1);
j = bits2.nextSetBit(j + 1);
}
}
return count;
}
The above is the readable version, hopefully good enough for the compiler, but you could optimize it manually I guess:
public int getIntersectionsSize(BitSet bits1, BitSet bits2) {
int count = 0;
for (int i = bits1.nextSetBit(0), j = bits2.nextSetBit(0); i >= 0 && j >= 0; ) {
while (i < j) {
i = bits1.nextSetBit(i + 1);
if (i < 0)
return count;
}
if (i == j) {
count++;
i = bits1.nextSetBit(i + 1);
}
while (j < i) {
j = bits2.nextSetBit(j + 1);
if (j < 0)
return count;
}
if (i == j) {
count++;
j = bits2.nextSetBit(j + 1);
}
}
return count;
}
I've been looking for a solution to this recently and here's what I came up with:
int intersectionCardinality(final BitSet lhs, final BitSet rhs) {
int lhsNext;
int retVal = 0;
int rhsNext = 0;
while ((lhsNext = lhs.nextSetBit(rhsNext)) != -1 &&
(rhsNext = rhs.nextSetBit(lhsNext)) != -1) {
if (rhsNext == lhsNext) {
retVal++;
rhsNext++;
}
}
return retVal;
}
Perhaps someone would like to take the time to compare the different solutions here and post the results...
I am trying to copy the elements from src (Array 1) to tgt (Array 2) using recursion. Len is an integer value that determines how many of the elements should be transferred. For example, if len is 4, I take 4 elements out of Array 1 and transfer them to Array 2.
Start is the starting location of array src, and this value is transferred to location start2 of array tgt. Then I recursively copy the remaining len-1 elements. Returning out of bound exception.
public void arraycopy(double[] src, int start, double[] tgt, int start2, int len){
if(len < 1) return;
if(len > src.length) return;
tgt[start2] = src[start];
arraycopy(src, start + 1, tgt, start2 + 1, len);
}
First, you are not treating len as the number of characters to copy. You are treating it as an ending index with this condition:
if(start < len){
You can change it to
if (len > 0)
but at that point, len is already greater than 0 because the base case len < 1 is already past. You can remove that if condition entirely.
Second, pass len - 1 in the recursive call:
arraycopy(src, start+1, tgt, start2+1, len - 1);
Third, if len is greater than the source array's length:
if (len > src.length) return;
then all you do is return, leading to an uncopied array and a confused caller. I would remove this line entirely. You can let Java throw the ArrayIndexOutOfBoundsException, passing it to the caller. If you must perform the bounds check, then test it yourself properly, for both the source and destination arrays.
if (start < 0 || start + len > src.length || start2 < 0 || start2 + len > tgt.length) {
throw new IllegalArgumentException("Out of bounds");
}
You don't have to pass two position integer. One is enough.
Check out the code. And also pass the actual length not (len-1)
public static void arraycopy(double[] src, int start, double[] tgt, int len){
if (len != src.length) return;
if (start<len){
tgt[start] = src[start];
arraycopy(src, start+1, tgt, len);
}
}
I have to say that my first attempt had some definite confusion mixed in. Thanks to rgettman^ I was able to make my code more concise and have it pass all my tests!
public void arraycopy(double[] src, int start, double[] tgt, int start2, int len){
if (start < 0 || start + len > src.length || start2 < 0 || start2 + len > tgt.length) return;
if (len > 0){
tgt[start2] = src[start];
arraycopy(src, start+1, tgt, start2+1, len-1);
}
}
public class RecursiveArrayCopyAlgorithm {
public static void main(String[] args) {
String str = "ABCD";
char[] chars = str.toCharArray();
char[] charElements = new char[chars.length];
int charLen = chars.length-1;
int charInitialIndex = 0;
RecursiveArrayCopyAlgorithm testSearch = new RecursiveArrayCopyAlgorithm();
char[] charObjs = testSearch.callLinear(charLen, charInitialIndex, chars, charElements);
for (int i = 0; i < charObjs.length; i++) {
System.out.println(charObjs[i]);
}
}
private char[] callLinear(int charLen, int index,char[] ch, char[] charElements) {
int index1 = charLen;
if(index1 < 0) {
return charElements;
}
if(index1 >= 0) {
charElements[index] = ch[index1];
}
return callLinear(charLen-1, index+1, ch, charElements);
}
}