I am trying to make radix sort function that calculates the number of digits of integer numbers using the radix sort as a base, and then sort the numbers from least significant to most significant.
I am using an array that holds random integers.
How can I make this method works well?
I am using this code:
public static void sort( int[] a, int radix)
{
int i, m = a[0], exp = 1, n = a.length;
int[] b = new int[10];
for (i = 1; i < n; i++)
if (a[i] > m)
m = a[i];
while (m / exp > 0)
{
int[] bucket = new int[10];
for (i = 0; i < n; i++)
bucket[(a[i] / exp) % 10]++;
for (i = 1; i < 10; i++)
bucket[i] += bucket[i - 1];
for (i = n - 1; i >= 0; i--)
b[--bucket[(a[i] / exp) % 10]] = a[i];
for (i = 0; i < n; i++)
a[i] = b[i];
exp *= 10;
}
}
Try
int[] b = new int[a.length];
or since n = a.length
int[] b = new int[n];
I am just pointing out the most obvious problems and leave the details to you.
Each bucket will have to hold a list of numbers so using just an int as a bucket is not going to work. Use something like this instead:
List<Integer>[] bucket = new List<Integer>[10];
The array used to collect the elements in the new order needs to be the same size as the original array. You just have made it 10 long.
Statement in last for loop
a[i] = b[i];
tells that size of b must be equal to or greater than a. Hence go for #rcgldr answer. Also the value of radix passed to your function is lying unused. You can also make your function a tad faster by swapping array pointers instead of copying the elements i.e. avoiding the last for loop.
int swap[] = a;
a = b;
b = swap;
then finally after all the loops are over, return the array a
return a;
Above is your program for sorting in ascending order. I am giving below the program to sort in descending order. The only change that was required was to start adding frequencies from the end of the base array( in this case Z ) to index zero.
public static int[] DSC(int A[], int radix, int base)
{
int length = A.length ;
int B[] = new int[length] ;
int div = 1 ;
int swap[] ;
int i ;
while(radix > 0)
{
int Z[] = new int[base] ;
i = 0 ;
while(i < length)
{
Z[( A[i] / div ) % base]++ ;
i++ ;
}
i = base ;
while(i > 1)
{
i--;
Z[i-1] += Z[i] ;
}
i = length ;
while(i > 0)
{
i-- ;
B[--Z[( A[i] / div ) % base]] = A[i];
}
swap = A;
A = B;
B = swap;
div *= base;
radix--;
}
return A;
}
For non-negative integers, using binary instead of decimal, might be more efficient & intuitive for machine.
Here is an implementation I wrote, with test case:
RadixSort.java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* Radix sort.
*
* #author eric
* #date 3/12/20 12:05 PM
*/
public class RadixSort {
/**
* Sort given array, the array will be modified.
*
* #param data array of integer of non-negative integers,
* #throws IllegalArgumentException if input contain negative integer,
*/
public static void sort(int[] data) {
int numSys = 2;
int bits = validAndfindHighestBit(data); // find highest bit,
// create queues,
List<List<Integer>> queues = new ArrayList<>(numSys);
for (int i = 0; i < numSys; i++) queues.add(new LinkedList<>());
// sort bit by bit, low to high,
for (int i = 0; i < bits; i++) {
// re-init queues,
for (int j = 0; j < numSys; j++) queues.get(j).clear();
// array -> queues,
for (int x : data) {
int bit = (x >> i) & 1; // get the i-th bit,
queues.get(bit).add(x);
}
// queues -> array,
int t = 0;
for (List<Integer> queue : queues) {
for (int x : queue) data[t++] = x;
}
}
}
/**
* Valid input number, and find highest bit that has 1.
*
* #param data
* #return
* #throws IllegalArgumentException if input contain negative integer,
*/
private static int validAndfindHighestBit(int[] data) {
// find max number,
int max = 0;
for (int x : data) {
if (x < 0) throw new IllegalArgumentException("negative integers are not supported");
if (x > max) max = x;
}
System.out.printf("max number: %d, ", max);
// find highest bit,
int highestBit = 0;
while (max != 0) {
highestBit++;
max >>= 1;
}
System.out.printf("highest bit: %d\n", highestBit);
return highestBit;
}
}
RadixSortTest.java
(Test case via TestNG)
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import static org.testng.Assert.*;
/**
* RadixSort test.
*/
public class RadixSortTest {
#Test
public void testSort() {
int[] data;
// generated un-sorted random array,
do data = genRandomArr(); while (data.length > 1 && isSorted(data));
System.out.printf("input arr:\t%s\n", Arrays.toString(data));
if (data.length > 1) Assert.assertFalse(isSorted(data));
// sort
RadixSort.sort(data);
System.out.printf("output arr:\t%s\n", Arrays.toString(data));
Assert.assertTrue(isSorted(data));
}
// corner case,
#Test
public void testSort_corner() {
int[] dataEmpty = new int[0]; // empty array,
RadixSort.sort(dataEmpty);
Assert.assertTrue(isSorted(dataEmpty));
int[] dataSingle = new int[]{5}; // single element,
RadixSort.sort(dataSingle);
Assert.assertTrue(isSorted(dataSingle));
}
// invalid input,
#Test(expectedExceptions = IllegalArgumentException.class)
public void testSort_invalid() {
int[] dataSingle = new int[]{1, -1}; // negative number,
RadixSort.sort(dataSingle);
}
/**
* generate random array, of size 10, in range [0, 1024),
*
* #return
*/
public static int[] genRandomArr() {
return genRandomArr(10, 100);
}
/**
* generate random array,
*
* #param size array size, default to 10,
* #param bound upper bound, default to 100,
* #return
*/
public static int[] genRandomArr(int size, int bound) {
if (size <= 0) size = 10;
if (bound <= 0) bound = 100;
ThreadLocalRandom rd = ThreadLocalRandom.current();
int[] arr = new int[size];
for (int i = 0; i < arr.length; i++) arr[i] = rd.nextInt(bound);
return arr;
}
// check whether array is sorted,
private static boolean isSorted(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) return false;
}
return true;
}
}
Related
This is the original question
"Shell Sort worst case. Construct an array of 100 elements containing the numbers 1 through 100 for which shellsort, with the increments 1 4 13 40, uses as large a number of compares as you can find."
There are 100! permutations for an array of 100 elements, it's terrifying to go through each permutation and find which one has the maximum number of compares. Is there any smarter way to approach this problem? My approach this problem is through violence, but only randomly shuffle the array 100000000 time which is less than 100! and it take me half an hour to get the final output.
I pasted my code below. I appreciate any suggestions from you guys!
`
package ch_2_1;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import java.util.Arrays;
public class exer_19
{
public static void main(String[] args)
{
// initial permutation
int[] array = new int[100];
for ( int i = 1; i < 101; i++)
{
array[i-1] = i;
}
// find the worst case and the number of compares
worst_input(array);
}
private static void worst_input(int[] array)
{
int max_count = 0;
int[] copy = new int[100];
int[] worst_case = new int[100];
for ( int i = 0; i < 100000000; i++)
{
int[] temp = generate(array);
for (int j = 0; j < 100; j++){ copy[j] = temp[j];}
Shell_sort operation = new Shell_sort();
operation.shell_sort(temp);
if (operation.compare() > max_count)
{
max_count = operation.compare();
worst_case = copy;
}
System.out.println(i);
}
for ( int s : worst_case){ System.out.print(s + " ");}
System.out.println();
System.out.println(max_count);
System.out.println();
}
private static int[] generate( int[] array)
{
StdRandom.shuffle(array);
return array;
}
private static class Shell_sort // it's necessary to create a private class to hold the shell sort method
// b/c the method must record the # of compares to sort the array, and this # count need to be returned
// to the worst_input method. Therefore, having a class to encapsulate the two methods is very helpful
{
private int count = 0;
private void shell_sort(int[] test)
{
int N = test.length;
int h = 1;
while (h < N/3) h = 3*h + 1; // 1, 4, 13, 40, 121...
while ( h > 0)
{
for ( int i = h; i < N; i++) // starting from the largest h-value th element of the array (simplified: ith element)
{
// if ith element is less than i-h th element, swap the two, continue this process until the condition is not met
for ( int j = i; j >= h && less( test[j], test[j-h]); j = j - h)
{
exchange( test, j, j-h);
count++;
}
}
// when reached the end of the array, update h value
h = h/3;
}
}
private int compare()
{
return count;
}
}
private static boolean less( int current, int previous)
{
return current < previous;
}
private static void exchange(int[] array, int cur_index, int pre_index)
{
int temp = array[pre_index];
array[pre_index] = array[cur_index];
array[cur_index] = temp;
}
}
`
This method due to restrictions can not use ArrayLists. The method accepts an array, the desired value to find, and then the certain number of near values. It uses integers and integer arrays only. This is what I have so far
/**
* Return the k elements of a nearest to val.
* The array a is not changed as a result of calling this method.
* This method throws an IllegalArgumentException if k is negative.
* This method returns an array of zero length if k == 0 or if
* k > a.length.
*
* #param a the array to be searched
* #param val the reference value
* #param k the number of near elements to identify
* #return the k elements a[i] such that ABS(a[i] - val)
* are the k smallest evaluations
*
*/
public static int[] nearestK(int[] a, int val, int k) {
int x = 0;
int[] answer = new int[k];
if (k < x || a.length == 0 || a == null)
{
throw new IllegalArgumentException();
}
if (k == 0 || k > a.length)
{
int[] badAnswer = new int[0];
return badAnswer;
}
int[] copy = Arrays.copyOf(a, a.length);
Arrays.sort(copy);
int nearest = copy[0];
for (int i = 0; (i < copy.length); i++) {
if (Math.abs(nearest - val) > Math.abs(copy[i] - val)) {
nearest = copy[i]; x = i;
}
}
int index = 0;
while (index < answer.length) {
answer[index] = nearest;
nearest = copy[x + (index + 1)];
index++;
}
return answer;
}
This method works sometimes but i began to realize that it only used values after the desired element.
i.e
int[1,3,5,7,10,11,12} this method, if searched for 6, with 3 nearest values, would only return
7,10,11 as an array. This clearly is not correct. I am very new to java so at this point I am wondering what are some alternatives to this or ways of correcting this method.
Here's a clever answer: Instead of sorting the array in natural order, sort it according to the distance to val. Then, all you need to do is pick the first k elements:
public static int[] nearestK(int[] a, int val, int k) {
// omitted your checks for brevity
final int value = val; // needs to be final for the comparator, you can also make the parameter final and skip this line
Integer[] copy = new Integer[a.length]; // copy the array using autoboxing
for (int i = 0; i < a.length; i++) {
copy[i] = a[i];
}
Arrays.sort(copy, new Comparator<Integer>() { // sort it with a custom comparator
#Override
public int compare(Integer o1, Integer o2) {
int distance1 = Math.abs(value - o1);
int distance2 = Math.abs(value - o2);
return Integer.compare(distance1, distance2);
}
});
int[] answer = new int[k]; // pick the first k elements
for (int i = 0; i < answer.length; i++) {
answer[i] = copy[i];
}
return answer;
}
I've been submitting programs to this problem at ACM. Problem ID=1922 but my solution keeps getting Time Limit Exceeded on test 3.
My idea is to use brute-force but with some branches-cutting-off. The below is my Java code, any faster solutions or improvements would be appreciated... I guess this isn't difficult at all because the difficulty is only 195, but I just can't get it accepted.
Finally got it accepted. The algorithm is to first sort the heroes, and start with the smallest-wish first. Just O(n)..
My Java code is so far the fastest Solution Rank
Many thanks!
public class testtest
{
static boolean[] used;
// length of heros
static int ulen;
// list of heros
static Wish[] w;
// number of possible teams
static int count = 0;
// and output
static StringBuilder str = new StringBuilder();
// add the team
// check if it is a valid team
static boolean check(int len)
{
for (int i = 0; i < ulen; i ++)
{
if (!used[i])
{
// adding another hero makes it reliable, so invalid
if (w[i].wish <= len + 1)
{
return false;
}
}
}
return true;
}
// search the teams, team size = total, current pick = len, start from root + 1
static void search(int root, int total, int len)
{
if (len >= total) // finish picking len heros
{
if (check(total)) // valid
{
print(total); // add to output
}
return;
}
for (int i = root + 1; i < ulen; i ++)
{
if (w[i].wish > len + ulen - i)
{
return; // no enough heros left, so return
}
else
if (w[i].wish <= total) // valid hero for this team
{
used[i] = true;
search(i, total, len + 1); // search next hero
used[i] = false;
}
}
}
public static void main(String[] args) throws IOException
{
BufferedReader rr = new BufferedReader(new InputStreamReader(System.in));
ulen = Integer.parseInt(rr.readLine());
w = new Wish[ulen];
for (int i = 0; i < ulen; i ++)
{
w[i] = new Wish(i + 1, Integer.parseInt(rr.readLine()));
}
Arrays.sort(w);
used = new boolean[ulen];
Arrays.fill(used, false);
for (int i = 1; i <= ulen; i ++)
{
for (int j = 0; j <= ulen - i; j ++)
{
if (w[j].wish <= i) // this hero is valid
{
used[j] = true;
search(j, i, 1);
used[j] = false;
}
}
}
System.out.println(count);
System.out.print(str);
}
}
First, my results (of Java) is the fastest.
http://acm.timus.ru/rating.aspx?space=1&num=1922&lang=java
The fact that I didn't make full use before is that I have sorted list of heroes according to their wishes.
Therefore, the main loop just needs to be changed to O(n) instead of O(n^2)
for (int i = 1; i <= ulen; i ++)
{
if (w[0].wish <= i)
{
used[0] = true;
search(0, i, 1);
used[0] = false;
}
}
Here is what I have that executes for the sample test in ~0.00013 seconds (on my CPU):
import java.io.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Arrays;
/**
* Hero.java
*
* This program solves the Super Hero problem put forth by Timus Online Judge
* http://acm.timus.ru/problem.aspx?space=1&num=1922
*
* #author Hunter McMillen
* #version 1.0 12/29/2012
*/
public class Hero {
private static Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
private static List<Integer> indices = new ArrayList<Integer>();
private static boolean[] used;
/**
* Entry point into the application
*
* #args command line arguments
*/
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int numHeroes, wish;
List<Integer> heroes = new ArrayList<Integer>();
List<List<Integer>> groups;
// read number of heroes
numHeroes = Integer.parseInt(in.readLine());
// read 'numHeroes' wishes from stdin
// filter out heroes that have a minimum required that exceeds
// the number of heroes
for(int i = 0; i < numHeroes; i++) {
wish = Integer.parseInt(in.readLine());
if(wish <= numHeroes)
heroes.add(wish);
}
// split into groups
groups = reliableGroups(heroes);
// output results
System.out.println(groups.size());
for(List<Integer> g : groups) {
System.out.println(g.size() + " " + g.toString().replaceAll("[\\]\\[\\,]", ""));
}
}
/**
* Determines whether a group is effective, meaning that all wishes
* for that group are met
*
* #group The group to evaluate for effectiveness
*/
public static boolean isEffective(List<Integer> group) {
int maxWish = Integer.MIN_VALUE;
int temp;
// find the maximum wish size of all members in group
for(int i = 0; i < group.size(); i++) {
if((temp = indexMap.get(group.get(i))) > maxWish)
maxWish = temp;
}
// make sure that the maximum wish size is respected
return group.size() >= maxWish;
}
/**
* Checks to see if there exists some other superhero
* that when added to this group makes another effective group
*
* #effectiveGroup The current grouping that is effective but might
* not be reliable
*/
public static boolean isReliable(List<Integer> effectiveGroup) {
for(int i = 1; i <= indices.size(); i++) {
if(!used[i]) {
// add another hero to this group to see if it remains effective
effectiveGroup.add(i);
// if it is still effective, then this group is not reliable
if(isEffective(effectiveGroup))
return false;
// remove the hero that was temporarily added
effectiveGroup.remove(effectiveGroup.size()-1);
}
}
// true if adding any unused member to this group made it ineffective
return true;
}
/**
* Separates the List<Integer> of heroes into reliable groups
*
* #heroes The List of heroes
*/
public static List<List<Integer>> reliableGroups(List<Integer> heroes) {
List<List<Integer>> groups = new ArrayList<List<Integer>>();
boolean effective = true;
int h, current;
// create HashMap with mapping between hero wish values and their index
for(int i = 1; i <= heroes.size(); i++) {
indices.add(i);
indexMap.put(i, heroes.get(i-1));
}
// create an array to track which heroes have been used
used = new boolean[indices.size()+1];
Arrays.fill(used, false);
List<int[]> combinations;
List<Integer> tempList;
for(int i = 1; i <= indices.size(); i++) {
h = indexMap.get(i);
combinations = combination(heroes, h);
// iterate over all combinations making sure the wish values are below
// the threshold for this hero at map index `i`
for(int[] aCombination : combinations) {
for(int j = 0; j < aCombination.length; j++) {
current = aCombination[j];
used[current] = true;
if(indexMap.get(current) > h) {
effective = false;
break;
}
}
// create a List from the integer[] combination
tempList = asList(aCombination);
// if the group makeup is reliable, save it
if(effective && !groups.contains(tempList) && isReliable(tempList))
groups.add(new ArrayList<Integer>(tempList));
// reset flags
effective = true;
Arrays.fill(used, false);
}
}
return groups;
}
/**
* Helper method that returns a List<Integer> given
* an array of primitive ints
*
* #array The array to convert to a List<Integer>
*/
public static List<Integer> asList(int[] array) {
List<Integer> boxed = new ArrayList<Integer>();
for(int i = 0; i < array.length; i++) {
boxed.add(array[i]);
}
return boxed;
}
/**
* Generates the intial r combination in ascending order
* i.e [1, 2, 3, 4, ..., r]
*
* #r The size of the intial combination
*/
public static int[] initialCombination(int r) {
int[] indices = new int[r];
for(int i = 0; i < r; i++)
indices[i] = i+1;
return indices;
}
/**
* Generates the next combination given an array of indices
*
* #indicesIn The array of indices
* #n The size of this combination
*/
public static int[] nextCombination(int[] indicesIn, int n) {
int[] indices = (int[])indicesIn.clone();
int r = indices.length;
// find the rightmost index that is not at its final highest value
int i = 0;
for (i = r - 1; i >= 0; i--) {
if (indices[i] != (i + n - r + 1)) {
break;
}
}
// return null if no more combinations exist
if (i == -1)
return null;
// increment rightmost index
indices[i]++;
// reset all the indices to the right of indices[i]
// to their smallest possible value.
for (int j = i + 1; j < r; j++) {
indices[j] = indices[j-1] + 1;
}
return indices;
}
/**
* Generates all r-combinations of the indices array
*
* #heroes The array of heroes wishes
* #r The length of the combination to generate
*/
public static List<int[]> combination(List<Integer> heroes, int r) {
List<int[]> combinations = new ArrayList<int[]>();
int[] indices = initialCombination(r);
while(indices != null) {
combinations.add(indices);
indices = nextCombination(indices, heroes.size());
}
return combinations;
}
}
I want to write a method that when supplied an array of ints will do the following. For each pair of array elements it will combine them and put them into a list of an inner class objects. Then it will compare each element in the array and check if it will fit between each pair values. (i.e. I have an array 0, 2, 4 it will make for example pair (0,4) and then it will check that value 2 is indeed between 0 and 4 and so for pair (4,0). When pair (0, 2) is evaluated it won't find anything and therefore counter will increase (and so for pair (2, 0)). I have constructed the following code to evaluate number of values that indeed will fit in pairs and I hoped then to get the total number of pairs that match my need by extracting it from the total number of pairs. Now I want to optimize this query (in case I have very big arrays with thousands of members and very big or negative integers e.g. 1,000,000,000 or - 2,000,000,000). Please let me know how to do that. Mainly please focus on optimization issues thank you.
import java.util.*;
import java.util.Map;
import java.lang.*;
public class Prac1 {
public int count(int[] A){
int k = 0;
class PTemp{
int first = 0;
int second = 0;
public PTemp(int first, int second){
this.first = first;
this.second = second;
}
}
List<PTemp> r = new ArrayList<PTemp>();
int z = 0;
for (int i = 0; i < A.length; i++) {
for (int j = i+1; j < A.length; j++) {
r.add(new PTemp(A[i], A[j]));
r.add(new PTemp(A[j], A[i]));
z = z + 2;
System.out.println("["+A[i] +","+A[j]+"]");
System.out.println("["+A[j] +","+A[i]+"]");
}
}
Iterator<PTemp> ir = r.iterator();
while (ir.hasNext()){
PTemp p = ir.next();
label1:
for (int i = 0; i < A.length-1; i++){
if (((p.first < A[i]) && (A[i] < p.second)) || ((p.first > A[i]) && (A[i] > p.second))){
k = k + 1;
break label1;
}
}
}
System.out.println(z);
k = z - k;
return k;
}
public int c(int[] A) {
int z = (A.length - 1) * 2;
return z;
}
public static void main(String[] args){
int[] A = {0, 2, 2, 6, 5, 5};
Prac1 pr = new Prac1();
System.out.println(pr.count(A));
System.out.println(pr.c(A));
}
}
Without loss of generality, we can consider the array to be sorted. Assuming all numbers in the array are distinct, the pairs without elements in between are the pairs formed by neighbours. There are (array.length - 1) * 2 such pairs, i.e. you could simply do:
public int count(int[] A) {
return (A.length - 1) * 2;
}
If the array may contain duplicates, you should specify how they are to be counted.
Sort the array. Make a single pass over the array, identifying groups of equal elements. For each such group, multiply the number of elements in the group, the number of smaller elements, and the number of larger elements. Add that to a running count.
public int count(int[] A) {
int i = 0, k = 0, j = 0;
Arrays.sort(A); // you need to import java.util.Arrays
while(i < A.length) {
for(j = i+1; j < A.length && A[j] == A[i]; j++);
k += (j - i) * i * (A.length - j);
i = j;
}
return k;
}
I'm trying to make an implementation of 'adding' the elements of two arrays in Java.
I have two arrays which contain integers and i wanna add them. I dont want to use immutable variables. I prefer do sth like that : a.plus(b);
The problem is when i add 2 arrays with different length.It tries to add the elements of b to a, but if b has a bigger length it flags an error "ArrayIndexOutOfBoundsException".
I can understand why that's happening. But how can i solve this?
How can i expand array a? :/
public void plus(int[] b)
{
int maxlength = Math.max( this.length, b.length );
if (maxlength==a.length)
{
for (int i = 0; i <= maxlength; i++)
{
a[i] = a[i] + b[i]; //ArrayIndexOutOfBoundsException error
}
}
}
i <= maxlength replace this with i < maxlength.
Your array index is starting at zero, not at one.
So the length of the array is one less than the end index of the array.
When you use <= you are trying to go one element after the last element in your array, Hence the exception.
Also you got to check the length of array b. If length of array b is smaller than a, you will end up facing the same exception.
int maxlength = Math.min( this.length, b.length ); is more appropriate.
Or incase if you don't want to miss out any elements in either of the arrays while adding, ArrayList is the answer for you. ArrayList is the self expanding array you are looking for.
Here is how you can do that -
// First ArrayList
ArrayList<Integer> a = new ArrayList<Integer>();
a.add(1);
a.add(2);
a.add(3);
// Second ArrayList
ArrayList<Integer> b = new ArrayList<Integer>();
b.add(1);
b.add(2);
b.add(3);
b.add(4);
int maxlength = Math.max(a.size(), b.size());
// Add the elements and put them in the first ArrayList in the corresponding
// position
for (int i = 0; i < maxlength; i++) {
if (i < a.size()) {
if (i < b.size()) {
int j = a.get(i);
a.set(i, j + b.get(i));
}
} else {
a.add(i, b.get(i));
}
}
for (int j : a) {
System.out.println(j);
}
How can i expand array a?
Don't use arrays if you need variable-size data structures. Use Lists.
How about this:
private int[] a;
/**
* Adds the specified array to our array, element by element, i.e.
* for index i, a[i] = a[i] + b[i]. If the incoming array is
* longer, we pad our array with 0's to match the length of b[].
* If our array is longer, then only the first [b.length] values
* of our array have b[] values added to them (which is the same
* as if b[] were padded with 0's to match the length of a[].
*
* #param b the array to add, may not be null
*/
public void plus(final int[] b)
{
assert b != null;
if (a.length < b.length) {
// Expand a to match b
// Have to move a to a larger array, no way to increase its
// length "dynamically", i.e. in place.
final int[] newA = new int[b.length];
System.arraycopy(a, 0, newA, 0, a.length);
// remaining new elements of newA default to 0
a = newA;
}
for (int i = 0; i < b.length; i++)
{
a[i] = a[i] + b[i];
}
}
Another version:
private ArrayList<Integer> aList;
public void plusList(final int[] b)
{
assert b != null;
if (aList.size() < b.length) {
aList.ensureCapacity(b.length);
}
for (int i = 0; i < b.length; i++)
{
if (i < aList.size()) {
aList.set(i, aList.get(i) + b[i]);
} else {
aList.add(b[i]);
}
}
}
Edit: Here's the full class with sample run from data in comments
public class AddableArray {
private int[] a;
public AddableArray(final int... a) {
this.a = a;
}
/**
* Adds the specified array to our array, element by element, i.e.
* for index i, a[i] = a[i] + b[i]. If the incoming array is
* longer, we pad our array with 0's to match the length of b[].
* If our array is longer, then only the first [b.length] values
* of our array have b[] values added to them (which is the same
* as if b[] were padded with 0's to match the length of a[].
*
* #param b the array to add, may not be null
*/
public void plus(final int[] b)
{
assert b != null;
if (a.length < b.length) {
// Expand a to match b
// Have to move a to a larger array, no way to increase its
// length "dynamically", i.e. in place.
final int[] newA = new int[b.length];
System.arraycopy(a, 0, newA, 0, a.length);
// remaining new elements of newA default to 0
a = newA;
}
for (int i = 0; i < b.length; i++)
{
a[i] = a[i] + b[i];
}
}
int[] get() {
return a;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder("a[] = [ ");
for (int i = 0; i < a.length; i++) {
if (i > 0) sb.append(", ");
sb.append(a[i]);
}
sb.append(" ]");
return sb.toString();
}
public static void main (final String[] args) {
final AddableArray myAddableArray = new AddableArray(1,2,3);
System.out.println("Elements before plus(): ");
System.out.println(myAddableArray.toString());
final int b[]={1,2,3,4};
myAddableArray.plus(b);
System.out.println("Elements after plus(): ");
System.out.println(myAddableArray.toString());
}
}
Sample run:
Elements before plus():
a[] = [ 1, 2, 3 ]
Elements after plus():
a[] = [ 2, 4, 6, 4 ]
maxlength is the max between the size of a[] and b[], so in a loop from 0 to maxlength, you will get an ArrayIndexOutOfBoundsException when i exceeds the min of the size of a[] and b[].
Try this:
public void plus(int[] b)
{
Polynomial a = this;
int[] c;
int maxlength;
if (a.length>b.length) {
c=a;
maxlength=a.length;
} else {
c=b;
maxlength=b.length;
}
int ca, cb;
for (int i = 0; i < maxlength; i++)
{
if (i<this.length)
ca=a[i];
else
ca=0;
if (i<b.length)
cb=b[i];
else
cb=0;
c[i] = ca + cb;
}
}
Try replacing:
for (int i = 0; i <= maxlength; i++)
with:
for (int i = 0; i < maxlength; i++)