I am having problems with the logic behind this multiplication method. It is using a 1D array of LongNumber. We can't use the Math class, must write our own logic. The two previous methods were addition and subtraction, I am having issues with how to setup the for loop in order to move one num index as we stay at the index of the other, and then changing to the next index of the number that wasn't moved.
This logic has been more confusing for me, addition and subtraction were all in once simple for loop and it was easy, with multiplication I cant figure out how to setup the loop so it only moves num index and not num2, so we can get the correct product.
public static Long_Number multiply(String num,String num2)
{
//data
String resultString3 = "";
Long_Number result3 = new Long_Number("");
int total, carry = 0, temp;
int v1 = 0, v2 = 0;
//set longest length to indexrange
int indexrange = num.length();
if(num2.length()>indexrange)
indexrange = num2.length();
//logic
for(int i = 0; i < indexrange; i++)
{
if(num.length()-1-i >= 0)
v1 = (num.charAt(num.length()-1-i)-'0');
else
v1 = 0;
if(num2.length()-1-i >= 0)
v2 = (num2.charAt(num2.length()-1-i)-'0');
else
v2 = 0;
sumofdigits = v1 * v2 + carry;
carry = sumofdigits % 10;
System.out.println(sumofdigits + "hi" + carry); //test print
}
result3.setNumber(resultString3);
return result3;
}
Related
I am a beginner(first year uni student) programmer trying to solve this problem which i'm finding somewhat difficult. If you are to answer this question, don't provide me with a complex daunting algorithm that will leave me scratching my head. I'll really appreciate it if you explain it step my step (both logically/conceptually then through code)
The problem is as follows:image
I have tried to attempt it and my code only works for a certain case that i tested.
package com.company;
import java.lang.Math;
public class Main {
public static int[][] binary_partition(int array[], int k){
int x = (int) Math.pow(2,k);
int[][] partition = new int[((array.length/x)*2)][array.length/x];
int divisor = array.length/x;
if ((array.length % 2) != 0){
return partition;
}
if (divisor >= array.length-1){
return partition;
}
if (k==1){
return partition;
}
int p = 0;
for(int i=0;i<((array.length/x)*2);i++)
{
for (int j = 0; j<array.length/x;j++)
{
partition[i][j] = array[p];
p += 1;
}
}
return partition;
}
public static void main(String[] args){
int[] array = {3, 2, 4, 7, 8, 9, 2, 3};
int[][] result = binary_partition(array,2);
for (int[] x : result){
for (int y : x)
{
System.out.print(y + " ");
}
System.out.println();
}
}
}
Your question is unclear, but this solution creates a function that partitions an array with the right length into 2^k sets.
First, an interesting fact: using the bitshift operator << on an integer increases its value by a power of two. So to find out the size of your partition, you could write
int numPartitions = 1 << k; // Equivalent to getting the integer value of 2^k
With this fact, the function becomes
public static int[][] partition(int[] set, int k) {
if (set == null)
return null; // Don't try to partition a null reference
// If k = 0, the partition of the set is just the set
if (k == 0) {
int[][] partition = new int[1][set.length];
// Copy the original set into the partition
System.arraycopy(set, 0, partition[0], 0, set.length);
return partition;
}
int numPartitions = 1 << k; // The number of sets to partition the array into
int numElements = set.length / numPartitions; // The number of elements per partition
/* Check if the set has enough elements to create a partition and make sure
that the partitions are even */
if (numElements == 0 || set.length % numElements != 0)
return null; // Replace with an error/exception of your choice
int[][] partition = new int[numPartitions][numElements];
int index = 0;
for (int r = 0; r < numPartitions; r++) {
for (int c = 0; c < numElements; c++) {
partition[r][c] = set[index++]; // Assign an element to the partition
}
}
return partition;
}
There are a few lines of your code where the intention is not clear. For example, it is not clear why you are validating divisor >= array.length-1. Checking k==1 is also incorrect because k=1 is a valid input to the method. In fact, all your validation checks are not needed. All you need to validate is that array.length is divisible by x.
The main problem that you have seems to be that you mixed up the lengths of the resulting array.
The resulting array should have a length of array.length / x, and each of the subarrays should have a length of x, hence:
int[][] partition = new int[array.length/x][x];
If you also fix your bounds on the for loops, your code should work.
Your nested for loop can be rewritten as a single for loop:
for(int i = 0 ; i < array.length ; i++)
{
int index = i / x;
int subArrayIndex = i % x;
partition[index][subArrayIndex] = array[i];
}
You just need to figure out which indices a an element array[i] belongs by dividing and getting the remainder.
I am trying to write a method that creates and returns an array of random Integers that has a length of eight and is within the range [25, 725].
Every Integer in the array must be higher or lower than every other Integer in the array by at least 15. However, my method isn't returning arrays that meet this requirement.
I set up a main() method that checks the output of my method 100,000 times, and throws an Exception if there are any Integers that are too close.
How can I create a method that will return an array of Integers where the difference between every Integer and every other Integer is at least 15?
public class Test {
public static void main(String[] args) throws Exception {
Integer[] distances = new Integer[8];
for (int i = 0; i < 100000; i++) {
distances = createPlanetDistances(distances.length);
// check distances for values within 15
for (int x = 0; x < distances.length; x++) {
for (int y = 0; y < distances.length; y++) {
if (x == y)
continue;
if (Math.abs(distances[x] - distances[y]) < 15) {
System.out.println(distances[x] + " " + distances[y]);
throw new Exception("Doesn't work");
}
}
}
for (int distance : distances)
System.out.print(distance + " ");
System.out.println(System.lineSeparator());
}
}
/**
* Creates an array of distances-from-the-sun for a given number of Planets.
* It does not allow distances to be within 15 of any other distance.
*
* #param planetAmount The number of distances to return.
* #return An array of distances-from-the-sun.
*/
private static Integer[] createPlanetDistances(int planetAmount) {
SplittableRandom random = new SplittableRandom();
final int min = 25;
final int max = 726;
HashSet<Integer> distanceSet = new HashSet<>();
// make sure there are no duplicate Integers
for(int i = 0; i < planetAmount; i++) {
int num = random.nextInt(min, max);
while (distanceSet.contains(num))
num = random.nextInt(min, max);
distanceSet.add(num);
}
// make sure each distance is 15 away from all others
Integer[] distances = distanceSet.toArray(new Integer[]{});
for(int i = 0; i < distances.length; i++) {
// check distances[i] with all other Integers
for (int j = 0; j < distances.length; j++) {
// do not compare an element with itself
if (j == i)
continue;
int difference = Math.abs(distances[i] - distances[j]);
if (difference < 15) {
while (difference < 15) {
distances[i] = random.nextInt(min, max);
difference = Math.abs(distances[i] - distances[j]);
}
// check all Integers again
System.out.println("HERE " + i + " " + j);
i = 0;
break;
}
}
}
return distanceSet.toArray(new Integer[]{});
}
}
To find COUNT numbers in range MIN to MAX (exclusive) that are more than DISTANCE apart, build a TreeSet and use the ceiling(...) method to find nearby values.
Example
final int DISTANCE = 15, MIN = 25, MAX = 726, COUNT = 8;
ThreadLocalRandom random = ThreadLocalRandom.current();
TreeSet<Integer> numbers = new TreeSet<>();
while (numbers.size() < COUNT) {
int value = random.nextInt(MIN, MAX);
Integer ceiling = numbers.ceiling(value - DISTANCE);
if (ceiling == null || ceiling > value + DISTANCE)
numbers.add(value);
}
System.out.println(numbers);
Sample Output
[86, 104, 120, 369, 425, 532, 682, 713]
You can always shuffle the result if you don't want them in ascending order.
How It Works
The ceiling method returns the least value in the set greater than or equal to the given value, or null if there is no such value.
So if e.g. value is 134 and DISTANCE is 15, then ceiling(value - DISTANCE) will find the smallest value that is >= 119. If that value is >= 149, then we know the nearby range 119-149 is clear and we can use the 134 value.
You are generating planetary orbits, so it should be OK to have monotonically increasing numbers. Each number you generate has constraints imposed on it by the following numbers, and in turn imposes constraints on them once it is generated.
Constraint: If you want to generate N orbits between min and max separated by D, then your bounds for the first orbit are [min, max - D * (N - 1)]. This is simply because you can't pack the following N - 1 planets into a space that is less than D * (N - 1).
You can update the second constraint as you go, since the new minimum is going to be the last generated number + D. Here is a simple O(n) implementation (assuming that genrating a random number is O(1)):
final int DISTANCE = 15, MIN = 25, MAX = 726, COUNT = 8;
Random random = Random();
orbits = new int[COUNT];
if(MAX - MIN < DISTANCE * COUNT) {
throw new IllegalArgumentException("Insert pithy comment about COUNT");
}
min = MIN;
for(int i = 0; i < COUNT; i++) {
max = MAX - DISTANCE * (COUNT - i - 1);
orbits[i] = random.nextInt(max - min + 1) + min;
min = orbits[i] + DISTANCE;
}
The following approach avoids acceptance/rejection sampling by removing the spacing requirement, generating values uniformly over the correspondingly shortened range, adding the spacing gaps back, and shuffling to yield the results in a randomized order.
static Random r = new Random();
public static ArrayList<Integer>
gen_array(int lower_bound, int upper_bound, int n, int separation) {
upper_bound -= (n - 1) * separation;
if(upper_bound < lower_bound) {
throw new IllegalArgumentException("Infeasible arguments");
}
ArrayList<Integer> ary = new ArrayList<>();
while(ary.size() < n) {
ary.add(lower_bound + r.nextInt(upper_bound - lower_bound + 1));
}
Collections.sort(ary);
for (int i = 0; i < n; ++i) {
ary.set(i, ary.get(i) + i * separation);
}
Collections.shuffle(ary);
return ary;
}
If you call it with a value of 8 for n, a lower_bound of 25, an upper_bound of 130, and a separation of 15, it yields the correct result immediately where an acceptance/rejection approach could take an awful lot of iterations to cough up the unique set of values for the answer.
I'm working on a data structures assignment and my attempt to increment a double hash function is stuck in an infinite loop.
My book defines a strategy to double hash as
h′(k) = q−(k mod q), for some prime number q < N. Also, N
should be a prime.
I've identified that the double hash increment is causing the issue, as switching to linear probing runs fine.
private int findSlot(int h, K k) {
totalProbes = 0;
int avail = -1; // no slot available (thus far)
int j = h; // index while scanning table
do {
totalProbes++;
if (totalProbes > maxProbes) maxProbes = totalProbes;
if (isAvailable(j)) { // may be either empty or defunct
if (avail == -1) avail = j; // this is the first available slot!
if (table[j] == null) {
break;
} // if empty, search fails immediately
} else if (table[j].getKey().equals(k))
return j; // successful match
//j = (j + 1) % capacity; // keep looking (cyclically)
j = hashTwo(k); //increment using double hash
} while (j != h); // stop if we return to the start
return -(avail + 1); // search has failed
}
private int hashTwo(K key) {
String keyString = key.toString(); //convert generic -> string -> int
int keyInt = Integer.parseInt(keyString);
return 7 - (keyInt % 7);
}
There is some ugliness with the hash 2 function - namely converting from a generic to an integer, but besides that it follows the same instructions as the book.
1.error in your code: it has to be "j = hashTwo(j)"
2.error in the formula: for k=q 0> h′(k) = q−(k mod q) = q-0=q=k
(you better look https://en.wikipedia.org/wiki/Double_hashing for a valid formula)
Instead of "Integer.parseInt" you should start iteration with
private int findSlot(K k, int size) {
return findSlot(hashTwo(k.hashCode()), size);
}
private int findSlot(int h, int size) {...}
It actually is problem to find lucky number - those numbers whose sum of digits and sum of square of digits are prime. I have implemented Sieve of Eratosthenes. Now to optimize it further I commented my getDigitSum method, that I suppose was heavy and replaced with two hard-coded value , but it is still taking minutes to solve one test case. Here is a reference to actual problem asked
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;
public class Solution {
private static int[] getDigitSum(long num) {
long sum = 0;
long squareSum = 0;
for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
if (tempNum < 0) {
sum = sum + tempNum;
squareSum = squareSum + (tempNum * tempNum);
} else {
long temp = tempNum % 10;
sum = sum + temp;
squareSum = squareSum + (temp * temp);
}
}
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
return twosums;
}
public static Set<Integer> getPrimeSet(int maxValue) {
boolean[] primeArray = new boolean[maxValue + 1];
for (int i = 2; i < primeArray.length; i++) {
primeArray[i] = true;
}
Set<Integer> primeSet = new TreeSet<Integer>();
for (int i = 2; i < maxValue; i++) {
if (primeArray[i]) {
primeSet.add(i);
markMutiplesAsComposite(primeArray, i);
}
}
return primeSet;
}
public static void markMutiplesAsComposite(boolean[] primeArray, int value) {
for (int i = 2; i*value < primeArray.length; i++) {
primeArray[i * value] = false;
}
}
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
Set set = getPrimeSet(1600);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = Integer.parseInt(br.readLine());
for (int cases = 0; cases < totalCases; cases++) {
String[] str = br.readLine().split(" ");
long startRange = Long.parseLong(str[0]);
long endRange = Long.parseLong(str[1]);
int luckyCount = 0;
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); \\this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
}
what I should use to cache the result so that it takes lesser amount of time to search, currently it takes huge no. of minutes to complete 10000 test cases with range 1 99999999999999(18 times 9 -the worst case) , even thought the search values have been hard-coded for testing purpose( 1600, 1501 ).
You need a different algorithm. Caching is not your problem.
If the range is large - and you can bet some will be - even a loop doing almost nothing would take a very long time. The end of the range is constrained to be no more than 1018, if I understand correctly. Suppose the start of the range is half that. Then you'd iterate over 5*1017 numbers. Say you have a 2.5 GHz CPU, so you have 2.5*109 clock cycles per second. If each iteration took one cycle, that'd be 2*108 CPU-seconds. A year has about 3.1*107 seconds, so the loop would take roughly six and a half years.
Attack the problem from the other side. The sum of the squares of the digits can be at most 18*92, that's 1458, a rather small number. The sum of the digits itself can be at most 18*9 = 162.
For the primes less than 162, find out all possible decompositions as the sum of at most 18 digits (ignoring 0). Discard those decompositions for which the sum of the squares is not prime. Not too many combinations are left. Then find out how many numbers within the specified range you can construct using each of the possible decompositions (filling with zeros if required).
There are few places in this implementation that can be improved. In order to to start attacking the issues i made few changes first to get an idea of the main problems:
made the total start cases be the value 1 and set the range to be a billion (1,000,000,000) to have a large amount of iterations. also I use the method "getDigitSum" but commented out the code that actually makes the sum of digits to see how the rest runs: following are the methods that were modified for an initial test run:
private static int[] getDigitSum(long num) {
long sum = 0;
long squareSum = 0;
// for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
// if (tempNum < 0) {
// sum = sum + tempNum;
// squareSum = squareSum + (tempNum * tempNum);
// } else {
// long temp = tempNum % 10;
// sum = sum + temp;
// squareSum = squareSum + (temp * temp);
//
// }
// }
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
return twosums;
}
and
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
Set set = getPrimeSet(1600);
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = 1;
for (int cases = 0; cases < totalCases; cases++) {
//String[] str = br.readLine().split(" ");
long startRange = Long.parseLong("1");
long endRange = Long.parseLong("1000000000");
int luckyCount = 0;
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); //this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
Running the code takes 5 minutes 8 seconds.
now we can start optimizing it step by step. I will now mention the various points in the implementation that can be optimized.
1- in the method getDigitSum(long num)
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
the above is not good. on every call to this method, two String objects are created , e.g. (sum+"") , before they are parsed into an int. considering the method is called billion times in my test, that produces two billion String object creation operations. since you know that the value is an int (according to the math in there and based on the links you provided), it would be enough to use casting:
twosums[0] = (int)sum;
twosums[1] = (int)squareSum;
2- In the "Main" method, you have the following
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); \\this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
here there are few issues:
a- set.contains(longArray[0]) will create an Integer object (with autoboxing) because contains method requires an object. this is a big waste and is not necessary. in our example, billion Integer objects will be created. Also, usage of set, whether it is a treeset or hash set is not the best for our case.
what you are trying to do is to get a set that contains the prime numbers in the range 1 .. 1600. this way, to check if a number in the range is prime, you check if it is contained in the set. This is not good as there are billions of calls to the set contains method. instead, your boolean array that you made when filling the set can be used: to find if the number 1500 is prime, simply access the index 1500 in the array. this is much faster solution. since its only 1600 elements (1600 is greater than max sum of sqaures of digits of your worst case), the wasted memory for the false locations is not an issue compared to the gain in speed.
b- int[] longArray = getDigitSum(num);
an int array is being allocated and returned. that will happen billion times. in our case, we can define it once outside the loop and send it to the method where it gets filled. on billion iterations, this saved 7 seconds, not a big change by itslef. but if the test cases are repeated 1000 times as you plan, that is 7000 second.
therefore, after modifying the code to implement all of the above, here is what you will have:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;
public class Solution {
private static void getDigitSum(long num,int[] arr) {
long sum = 0;
long squareSum = 0;
// for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
// if (tempNum < 0) {
// sum = sum + tempNum;
// squareSum = squareSum + (tempNum * tempNum);
// } else {
// long temp = tempNum % 10;
// sum = sum + temp;
// squareSum = squareSum + (temp * temp);
//
// }
// }
arr[0] = (int)sum;
arr[1] = (int)squareSum;
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
}
public static boolean[] getPrimeSet(int maxValue) {
boolean[] primeArray = new boolean[maxValue + 1];
for (int i = 2; i < primeArray.length; i++) {
primeArray[i] = true;
}
for (int i = 2; i < maxValue; i++) {
if (primeArray[i]) {
markMutiplesAsComposite(primeArray, i);
}
}
return primeArray;
}
public static void markMutiplesAsComposite(boolean[] primeArray, int value) {
for (int i = 2; i*value < primeArray.length; i++) {
primeArray[i * value] = false;
}
}
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
boolean[] primeArray = getPrimeSet(1600);
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = 1;
for (int cases = 0; cases < totalCases; cases++) {
//String[] str = br.readLine().split(" ");
long startRange = Long.parseLong("1");
long endRange = Long.parseLong("1000000000");
int luckyCount = 0;
int[] longArray=new int[2];
for (long num = startRange; num <= endRange; num++) {
getDigitSum(num,longArray); //this method was commented for testing purpose and was replaced with any two hardcoded values
if(primeArray[longArray[0]] && primeArray[longArray[1]]){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
}
Running the code takes 4 seconds.
the billion iterations cost 4 seconds instead of 5 minutes 8 seconds, that is an improvement. the only issue left is the actual calculation of the sum of digits and sum of squares of digits. that code i commented out (as you can see in the code i posted). if you uncomment it, the runtime will take 6-7 minutes. and here, there is nothing to improve except if you find some mathematical way to have incremental calculation based on previous results.
I have source array, and I want to generate new array from the source array by removing a specified number of elements from the source array, I want the elements in the new array to cover as much as possible elements from the source array (the new elements are uniformly distributed over the source array) and keeping the first and last elements the same (if any).
I tried this :
public static void printArr(float[] arr)
{
for (int i = 0; i < arr.length; i++)
System.out.println("arr[" + i + "]=" + arr[i]);
}
public static float[] removeElements(float[] inputArr , int numberOfElementToDelete)
{
float [] new_arr = new float[inputArr.length - numberOfElementToDelete];
int f = (inputArr.length ) / numberOfElementToDelete;
System.out.println("f=" + f);
if(f == 1)
{
f = 2;
System.out.println("f=" + f);
}
int j = 1 ;
for (int i = 1; i < inputArr.length ; i++)
{
if( (i + 1) % f != 0)
{
System.out.println("i=" + i + " j= " + j);
if(j < new_arr.length)
{
new_arr[j] = inputArr[i];
j++;
}
}
}
new_arr[0] = inputArr[0];
new_arr[new_arr.length - 1] = inputArr[inputArr.length - 1];
return new_arr;
}
public static void main(String[] args)
{
float [] a = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
a = removeElements(a, 6);
printArr(a);
}
I have made a test for(removeElements(a, 5) and removeElements(a, 4) and removeElements(a, 3)) but removeElements(a, 6); gave :
arr[0]=1.0
arr[1]=3.0
arr[2]=5.0
arr[3]=7.0
arr[4]=9.0
arr[5]=11.0
arr[6]=13.0
arr[7]=15.0
arr[8]=0.0
arr[9]=16.0
the problem is (arr[8]=0.0) it must take a value ..
How to solve this? is there any code that can remove a specified number of elements (and keep the elements distributed over the source array without generating zero in some elements)?
EDIT :
examples :
removeElements(a, 1) ==> remove one element from the middle (7) {1,2,3,4,5,6,7,9,10,11,12,13,14,15,16}
removeElements(a, 2) ==> remove two elements at indexes (4,19) or (5,10) or (4,10) (no problem)
removeElements(a, 3) ==> remove three elements at indexes (4,9,14) or (4,10, 15) or(no problem also)
removeElements(a, 4) ==> remove four elements at indexes (3,7,11 , 15) or ( 3 ,7,11,14) for example ..
what I want is if I draw the values in the source array on (chart on Excel for example) and I draw the values from the new array , I must get the same line (or close to it).
I think the main problem in your code is that you are binding the selection to
(inputArr.length ) / numberOfElementToDelete
This way you are not considering the first and the last elements that you don't want to remove.
An example:
if you have an array of 16 elements and you want to delete 6 elements it means that the final array will have 10 elements but, since the first and the last are fixed, you'll have to select 8 elements out of the remaining 14. This means you'll have to select 8/14 (0,57) elements from the array (not considering the first and the last).
This means that you can initialize a counter to zero, scan the array starting from the second and sum the value of the fraction to the counter, when the value of the counter reach a new integer number (ex. at the third element the counter will reach 1,14) you'll have an element to pick and put to the new array.
So, you can do something like this (pseudocode):
int newLength = originalLength - toDelete;
int toChoose = newLength - 2;
double fraction = toChoose / (originalLength -2)
double counter = 0;
int threshold = 1;
int newArrayIndex = 1;
for(int i = 1; i < originalLength-1; i++){
**counter += fraction;**
if(integerValueOf(counter) == threshold){
newArray[newArrayIndex] = originalArray[i];
threshold++;
**newArrayIndex++;**
}
}
newArray[0] = originalArray[0];
newArray[newArray.length-1] = originalArray[originalArray.length-1];
You should check for the particular cases like originalArray of length 1 or removal of all the elements but I think it should work.
EDIT
Here is a Java implementation (written on the fly so I didn't check for nulls etc.)
public class Test {
public static void main(String[] args){
int[] testArray = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int[] newArray = remove(testArray, 6);
for(int i = 0; i < newArray.length; i++){
System.out.print(newArray[i]+" ");
}
}
public static int[] remove(int[] originalArray, int toDelete){
if(toDelete == originalArray.length){
//avoid the removal of all the elements, save at least first and last
toDelete = originalArray.length-2;
}
int originalLength = originalArray.length;
int newLength = originalLength - toDelete;
int toChoose = newLength - 2;
int[] newArray = new int[newLength];
double fraction = ((double)toChoose) / ((double)originalLength -2);
double counter = 0;
int threshold = 1;
int newArrayIndex = 1;
for(int i = 1; i < originalLength-1; i++){
counter += fraction;
if(((int)counter) == threshold ||
//condition added to cope with x.99999999999999999... cases
(i == originalLength-2 && newArrayIndex == newLength-2)){
newArray[newArrayIndex] = originalArray[i];
threshold++;
newArrayIndex++;
}
}
newArray[0] = originalArray[0];
newArray[newArray.length-1] = originalArray[originalArray.length-1];
return newArray;
}
}
Why cant you just initialize i=0
for (int i = 0; i < inputArr.length; i++) {
if ((i + 1) % f != 0) {
Following is the output:
arr[0]=1.0
arr[1]=1.0
arr[2]=3.0
arr[3]=5.0
arr[4]=7.0
arr[5]=9.0
arr[6]=11.0
arr[7]=13.0
arr[8]=15.0
arr[9]=16.0
This is Reservoir sampling if I understand it right i.e from a large array, create a small array by randomly choosing.