Why aren't my objects that implement Comparable sorted? - java

my simple example (compiled working code) just does not sort fruits by their weight.
import java.util.Arrays;
public class Test {
public static class Fruit implements Comparable<Fruit> {
public int weight = 0;
public Fruit(int w) { weight = w; }
// compare this fruit to a given fruit f
public int compareTo(Fruit f) {
return (weight > f.weight) ? 1 : 0;
}
}
public static void main(String[] args) {
// get some fruits (we intentionally create a box for 100 fruits)
Fruit[] fruits = new Fruit[100];
for (int i = 0; i < 10; i++) {
fruits[i] = new Fruit((int)(Math.random() * 50 + 1));
}
// sort fruits by weight
Arrays.sort(fruits, 0, 10);
// print fruit weights
for (int i = 0; i < 10; i++) {
System.out.print(fruits[i].weight + " ");
}
}
}
Why it is so?
Alright, in my problem (not about fruits), I have objects that are never pairwise equal, that is why I thought one object is either bigger or smaller than another. So how can I handle this situation when I know that 0 (objects are equal) will never happen?

compareTo must return one of 3 values:
>0 --> Bigger than
0 --> Equal
<0 --> Less than
Your compareTo method only returns 0 or 1; fix that.

Use the method public static int compare(int x, int y) from the class java.lang.Integer (since Java 7).
public int compareTo(Fruit f) {
return Integer.compare(weight, f.weight);
}

If weight is never negative then you can try
return weight - f.weight;
instead of
return (weight > f.weight) ? 1 : 0;
to sort from lowest to highest value.

The best approach is to use the JDK-supplied method for comparing int values, which also makes it crystal clear what the code is doing
public int compareTo(Fruit f) {
return Integer.compare(weight, f.weight);
}
Prior to version 7 java, you have two choices:
public int compareTo(Fruit f) {
return weight - f.weight; // terse, but slightly obtuse
}
public int compareTo(Fruit f) {
return new Integer(weight).compareTo(f.weight); // ugly, but supposedly clear
}
My preference is the subtraction, because once you understand it, it's clear from then on.

Your compareTo method should return -1, 0, 1
LESSER = -1;
EQUAL = 0;
BIGGER = 1;

Related

Setting up array of complex coefficients, avoiding the leading zero's

I have created a class for complex numbers:
public class Complex {
private double x; //Real part x of the complex number x+iy.
private double y; //Imaginary part y of the complex number x+iy.
public Complex(double x, double y) { //Constructor: Initializes x, y.
this.x=x;
this.y=y;
}
public Complex(double x) { //Real constructor - initialises with a real number.
this(x, 0.0);
}
public Complex() { //Default constructor; initialiase x and y to zero.
this(0.0, 0.0);
}
}
What I would like to do is create a function Polynomial, which would take an array of coefficients, and filter it so that if for example [1,0,0,1,0,0,0,0,0...], it would return an array of length 4. Since the zero's that are left, have no use in a polynomial.
Here's how a complex array would look like
Complex [] coeff = new Complex [] {
new Complex(-1.0 ,0.0), new Complex(),
new Complex() , new Complex(1.0, 0.0)
};
A polynomial would be defined as
Polynomial p = new Polynomial(coeff);
Here's the problem formulation:
Here is how the polynomial would have to look like, typing in the complex array coefficients
I was thinking of constructing an algorithm which searches for the first zero of the zero sequence(which is until the end of the array), and then deletes the zeros.
Also I was thinking of inverting the entries of the array so that [0,1,1,0,1,0,0,0] would be [0,0,0,1,0,1,1,0] and then creating a function which would start "recording" my new array from the first non Trivial entry.
How would I go with creating such a function?
My attempt for this is:
int j=0;
for(int i=coeff.length-1; i>=0; i-=1)
{
if(coeff[i].getReal()== 0 && coeff[i].getImag() == 0 ){
j=+1;
}
else {
break;
}
}
int a = coeff.length-j;
this.coeff = new Complex[a];
for (int i=0;i<this.coeff.length;i+=1){
this.coeff[i]=coeff[i];
}
}
And for example I would like to print :
Complex a1=new Complex(-3, 1);
Complex a2=new Complex(2, 0.3);
Complex a3=new Complex();
Complex b=new Complex();
Complex[] com=new Complex[] {a1,b, a2, a3,b};
and the output is :
(-3.0+1.0i)+ (0.0+0.0i)X^1+(2.0+0.3i)X^2+(0.0+0.0i)X^3
But is supposed to be :
(-3.0+1.0i)+ (0.0+0.0i)X^1+(2.0+0.3i)X^2
And I've tried adding a "-1" to int a = coeff.length-j; :
int a = coeff.length-j-1;
but then if i print out
Complex[] com=new Complex[] {a1,b, a2, a3,b,b,b,b,b,b};
It's going to give me the same results (ie storing the trivial coefficients).
How can i make the contructor not store those trivial coefficients?
I think that the way to go in here is by iterating over the Array for the end to the start, just like you were trying. The problem with your code is the next:
if(coeff[i].getReal()== 0 && coeff[i].getImag() == 0 ){
j=+1; //Here! I think you wanted to do j+=1
}
At doing j=+1 you are making j to always have a value of 1. So, changing j=+1 to j+=1 will fix this.
Also, I did a different code if you want to check it. At the end, it does the same but I think is cleaner.
public class Polynomial {
private Complex[] coeff;
public Polynomial(Complex[] coeff) {
this.coeff = cleanCoeff(coeff);
}
private Complex[] cleanCoeff(Complex[] coeff) {
int length = coeff.length;
Complex complex = null;
for (int i = coeff.length - 1; i >= 0 ; i--) {
complex = coeff[i];
if(complex.getX() == 0 && complex.getY() == 0) {
length--;
}else {
break;
}
}
return Arrays.copyOf(coeff, length);
}
public Complex[] getCoeff() {
return coeff;
}
}
I hope this answer helps you.
This could be done relatively easily using something like the following:
int effective_len(Complex coeff[]) {
int pos = 0;
Complex zero();
for (int i=0; i<coeff.lengh; i++) {
if (!zero.equals(coeff[i])) {
pos = i;
}
}
return pos + 1;
}
For this you will need to define the equals method where you just check the real and imaginary components, but this should get you where you need to go.

Java, Creating an object vector that should have n zeros in it's array after compilation

This is kind of hard but I will try to make my question as clear as possible.
So I'm working on a project that deals with operations on vectors. I have different classes for different dimensions: Vector3D, Vector5D and VectorND. So I have interface and abstract class that describe methods like Sum, Subtraction etc. And for result of operation I create a new object Vector where I put coordinates after sum/subtraction etc. So here is the part of code as an example:
interface sample
{
Vector Sum(Vector vec);
Vector Subtraction(Vector vec);
int Product(Vector vec);
boolean Compare(Vector vec);
String ToString();
}
abstract class Vector implements sample
{
int[] coordinates;
public Vector (int[] coordinates)
{
this.coordinates=coordinates;
}
protected abstract Vector resVec();
public Vector Sum(Vector vec)
{
Vector result = resVec();
if (this.coordinates.length == vec.coordinates.length)
{
for (int i = 0; i< vec.coordinates.length; i++)
{
result.coordinates[i] = this.coordinates[i] + vec.coordinates[i];
}
}
else
{
throw new ArithmeticException("Can't sum vectors of different length");
}
return result;
Here is have protected abstart Vector resVec(); - method that creates new vector with length that depends on dimension of vectors that we operate with.
Example of realization for Vector3D:
class Vector3D extends Vector
{
public Vector3D(int n1,int n2,int n3)
{
super(new int[]{n1,n2,n3});
}
public Vector3D resVec()
{
Vector3D resVec = new Vector3D(0,0,0);
return resVec;
}
So here I create a new vector with length 3 and fill it with zeros. I need to create same vector for VectorND. Like this:
class VectorND extends Vector
{
public VectorND(int...n)
{
super(n);
}
public VectorND resVec()
{
VectorND resVec = new VectorND();
return resVec;
}
Any ideas how I can pass not declared number of zeros? Or maybe any idea of different implementation? Thanks!
Within the resVec() method, you can populate an array of 0s and then pass it to your Vector super constructor. Since your super constructor takes an array of ints, you could do something like this:
public VectorND resVec(int n)
{
int[] coordinates = new int[n];
Arrays.fill(coordinates, 0);
VectorND resVec = new VectorND(coordinates);
return resVec;
}
Foremost you could make use of generics since you would get problems as soon you need float or double for a vector type.
public interface Vector<T extends Number>{
T getX();
void setX(T x);
// [...]
T length();
T lengthSquared();
// [...]
To your problem, it can be solved by adding a helper variable which contains the dimension amount and than process the math operations as algorthm / loop. This way the amount of dimension don't matter anymore and you also avoid issues like divide by zero.
this is a excample for a matrix .. but the aproche is the same:
public final void multiply(float factor) {
// in your case it would be getDimension() or something
for(int i = 0; i < getRows()*getColumns();++i){
m[i]*=factor;
}
}
Oh and I know this advice is hard for java developer but don't over engineer it otherwise you will waste preformence.
The values of arrays are automatically defaulted.
int[] ints = new int[4]; // Filled with 0
double[] doubles = new double[5]; // Filled with 0.0
boolean[] booleans = new boolean[6]; // Filled with false
String[] strings = new String[7]; // Filled with null
I am not entirely sure about your classes, but for a multi-dimensional matrix-like class one only needs one version. The values can be stored in a linearized array by using a calculated index.
public class DoubleMatrix {
final int[] sizes;
final double[] values;
public DoubleMatrix(int... sizes) {
this.sizes = Arrays.copyOf(sizes, sizes.length); // Or sizes.clone()
int valueCount = 1;
for (int size : this.sizes) {
assert size > 0 : "Every given size must be at least 1.";
valueCount *= size;
}
values = new int[valueCount];
}
public int dimesion() {
return sizes.length;
}
public double get(int... is) {
int i = index(is);
return values[i];
}
// new DoubleMatrix(2, 3, 4).set(3.14259, 0, 1, 2); // 24 values in 3D
public void set(double x, int... is) {
int i = index(is);
values[i] = x;
}
The setter is a bit unconventional placing the value first because of the var-args is.
The linearisation from several indices to an index into the values array:
private int index(int... is) {
assert is.length == sizes.length: "Wrong number of indices.";
int singleI = 0;
for (int dim = 0; dim < sizes.length) {
if (0 > is[dim] || is[dim] >= sizes[dim]) {
throw new IndexOutOfBoundsException();
}
if (dim > 0) {
singleI *= sizes[i - 1];
}
singleI += is[i];
}
}
(I am not sure the index calculation is correct.)
Instead of asserts throwing runtime exceptions (IllegalArgumentException) would be better.
Of course if get and set were protected you could make a child class without var-args, and have a public get(int i, int j) for a DoubleMatrix2D.

Java rarrange enum array

i was wondering how can i reorder enum so that all goats are at the beginning and all sheep are at the end of the array. Right now it actually does the trick but until the array size > 100.. The reordering speed also matters so api methods are bit too slow. Any suggestions?
public class Sheep {
enum Animal {sheep, goat};
public static void main (String[] param) {
reorder(Animal.values());
}
public static void reorder (Animal[] animals) {
int l, r, i, j;
i = l = 0; //left most element
r = animals.length - 1;//right most element
int mid = (r+l)/2; // middle element of the array
for(i=0; i < animals.length;i++)
{
if(i < mid)
{
animals[i] = animals[l+1];
System.out.println(animals[r]);
} else if(i >= mid )
{
animals[i] = animals[r-1];
System.out.println(animals[r]);
}
}
}
}
Since an enum implements Comparable, you can simply sort and then reverse the array:
public static void reorder(Animal[] animals) {
Arrays.sort(animals);
for (int i = 0, j = animals.length - 1; i < j; ++i, --j) {
Animal tmp = animals[i];
animals[i] = animals[j];
animals[j] = tmp;
}
}
You might also be able to do it with:
List<Animal> list = Arrays.asList(animals);
Collections.sort(list);
Collections.reverse(list);
This basically does the same thing with API calls with the (very slight) overhead of wrapping the array in a List object. You can even do this:
Arrays.sort(animals, Collections.reverseOrder());
(Thanks to Bhesh Gurung for the idea.)
EDIT: If you have to deal with exactly two values, you can do much better by simply scanning from both ends, swapping as you find two elements out of order:
public static void reorder(Animal[] animals) {
int first = 0;
int last = animals.length - 1;
while (first < last) {
/*
* The unsorted elements are in positions first..last (inclusive).
* Everything before first is the higher animal; everything after
* last is the lower animal.
*/
while (animals[first].ordinal() == 1 && first < last) {
++first;
}
while (animals[last].ordinal() == 0 && first < last) {
--last;
}
if (first < last) {
/*
* At this point, the sort conditions still hold and also we know
* that the animals at first and last are both out of order
*/
Animal temp = animals[first];
animals[first] = animals[last];
animals[last] = temp;
++first;
--last;
}
}
}
However, if all you need to do is generate the right output (and not actually sort the array), then the approach suggested by #ajb in a comment is the best: just count how many sheep and goats there are and print the corresponding values that many times.
If you want to have maximum performance for such a special case you may simply count the number of one of the two possible values and overwrite the array accordingly to get the result that sorting would create:
public static void reorder (Animal[] animals) {
assert Animal.values().length==2;
int numGoat=0;
for(Animal a:animals) if(a==Animal.goat) numGoat++;
Arrays.fill(animals, 0, numGoat, Animal.goat);
Arrays.fill(animals, numGoat, animals.length, Animal.sheep);
}
You can see it as a modified version of counting sort.

How do I return these using only one method?

public class newClass {
public static void main(String[] args)
{
int nullValue=0;
int nullValue2=1;
int nullValue3=0;
int nullValue4=0;
int [] sourceArray = {4,5,6,7};
int [] targetArray = new int [4];
for (int i=0; i<sourceArray.length; i++)
{
nullValue+=sourceArray[i];
}
targetArray[0]=nullValue;
// I added all sourceArray elements together and passed it to targetArray[0]
for (int i=0; i<sourceArray.length; i++)
{
nullValue2*=sourceArray[i];
}
targetArray[1]=nullValue2;
// I multiplied all sourceArray elements together and assigned the result to targetArray[1]
for (int i=0; i<sourceArray.length; i++)
{
nullValue3 += getResult(sourceArray[i]);
}
targetArray[2]=nullValue3;
// I tried to add all odd numbers in sourceArray together and assign it to targetArray[2]
for (int i=0; i<sourceArray.length; i++)
{
nullValue4 += getResult(sourceArray[i]);
}
targetArray[3]=nullValue4;
// Same as previous except I need to do that with even numbers.
}
public static int getResult (int x)
{
if (x%2 == 0)
{
return x;
}
else
{
return 0;
}
}
}
You can read my comments above. I realize I can create another method for the last part but I am supposed to use only one method to return odds and evens. I tried almost anything. I can't think of any other ways anymore. Obviously I can't return x in both cases(Yeah I was too desperate to try that).
Straight to the point. I need one method to return x if it's odd or if it's even(We can say it's impossible by the look of that sentence already). I guess that's impossible to do with only one method. I'm not good at java yet so I'm not sure. Maybe there are other ways to do that with only one method which may be so easy. I worked on it for like 6 hours so I'm asking you guys. Thanks.
Create a method to return a boolean if the number is even like so
public static boolean isEven(int x)
{
return (x%2 == 0)
}
Then in your loop for evens
for (int i=0; i<sourceArray.length; i++)
{
if(isEven(x))
nullValue3 += sourceArray[i];
}
For odds just change to if(!isEven(x))
But this is probably deviating from the requirements as you probably want a method that returns an int and you could just put the condition directly in the loop and not need a method
If I understand your question correctly, what you want is to be able to tell the getResult function whether to give you only odd numbers or only even numbers. Without getting complicated, this is what I would do:
public static int getResult(int x, boolean evens) {
if (x % 2 == 0) {
return evens ? x : 0; // shorthand for: if(evens) {return x;} else {return 0;}
} else {
return evens ? 0 : x;
}
}
Simply speaking, I pass a flag value (evens) to the getResult function. This flag tells me whether to filter for even numbers or for odd numbers.
I test whether x is even (x % 2 == 0). If it is, I return it if I'm looking for evens, and I return 0 if I'm looking for odds. If x wasn't even, then I do the opposite.
It would be a little cleaner to write a pair of helper functions, which you could then call from your getResult function.
private static int getIfEven(x) {
if (x % 2 == 0) {
return x;
}
return 0;
}
private static int getIfOdd(x) {
if (x % 2 == 0) {
return 0;
}
return x;
}
public static int getResult(int x, boolean evens) {
// shorthand for:
// if (evens) {
// return getIfEven(x);
// } else {
// return getIfOdd(x);
// }
return evens ? getIfEven(x) : getIfOdd(x);
}
Depending on how much you're allowed to deviate from the current setup (I assume this is homework), you could also just write an isEven(int x) function and call that at each step through the loop, only adding the number if it is/isn't even.

Finding the largest positive int in an array by recursion

I decided to implement a very simple program recursively, to see how well Java handles recursion*, and came up a bit short. This is what I ended up writing:
public class largestInIntArray {
public static void main(String[] args)
{
// These three lines just set up an array of ints:
int[] ints = new int[100];
java.util.Random r = new java.util.Random();
for(int i = 0; i < 100; i++) ints[i] = r.nextInt();
System.out.print("Normal:"+normal(ints,-1)+" Recursive:"+recursive(ints,-1));
}
private static int normal(int[] input, int largest) {
for(int i : input)
if(i > largest) largest = i;
return largest;
}
private static int recursive(int[] ints, int largest) {
if(ints.length == 1)
return ints[0] > largest ? ints[0] : largest;
int[] newints = new int[ints.length - 1];
System.arraycopy(ints, 1, newints, 0, ints.length - 1);
return recursive(newints, ints[0] > largest ? ints[0] : largest);
}
}
And that works fine, but as it's a bit ugly I wondered if there was a better way. If anyone has any thoughts/alternatives/syntactic sugar to share, that'd be much appreciated!
P.s. If you say "use Lisp" you win nothing (but respect). I want to know if this can be made to look nice in Java.
*and how well I handle recursion
Here's how I might make the recursive method look nicer:
private static int recursive(int[] ints, int largest, int start) {
if (start == ints.length) {
return largest;
}
return recursive(ints, Math.max(ints[start], largest), start + 1);
}
This avoids the expensive array copy, and works for an empty input array. You may implement an additional overloaded method with only two parameters for the same signature as the iterative function:
private static int recursive(int[] ints, int largest) {
return recursive(ints, largest, 0);
}
2 improvements:
no copy of the array (just using the offset)
no need to give the current max
private static int recursive(int[] ints, int offset) {
if (ints.length - 1 == offset) {
return ints[offset];
} else {
return Math.max(ints[offset], recursive(ints, offset + 1));
}
}
Start the recursion with recursive(ints, 0).
You could pass the current index as a parameter rather than copying almost the entire array each time or you could use a divide and conquer approach.
public static int max(int[] numbers) {
int size = numbers.length;
return max(numbers, size-1, numbers[size-1]);
}
public static int max(int[] numbers, int index, int largest) {
largest = Math.max(largest, numbers[index]);
return index > 0 ? max(numbers, index-1, largest) : largest;
}
... to see how well Java handles recursion
The simple answer is that Java doesn't handle recursion well. Specifically, Sun java compilers and Hotspot JVMs do not implement tail call recursion optimization, so recursion intensive algorithms can easily consume a lot of stack space.
However, I have seen articles that say that IBM's JVMs do support this optimization. And I saw an email from some non-Sun guy who said he was adding it as an experimental Hotspot extension as a thesis project.
Here's a slight variation showing how Linked Lists are often a little nicer for recursion, where "nicer" means "less parameters in method signature"
private static int recursive(LinkedList<Integer> list) {
if (list.size() == 1){
return list.removeFirst();
}
return Math.max(list.removeFirst(),recursive(list));
}
Your recursive code uses System.arrayCopy, but your iterative code doesn't do this, so your microbenchmark isn't going to be accurate. As others have mentioned, you can clean up that code by using Math.min and using an array index instead of the queue-like approach you had.
public class Maximum
{
/**
* Just adapted the iterative approach of finding maximum and formed a recursive function
*/
public static int max(int[] arr,int n,int m)
{
if(m < arr[n])
{
m = arr[n];
return max(arr,n - 1,m);
}
return m;
}
public static void main(String[] args)
{
int[] arr = {1,2,3,4,5,10,203,2,244,245,1000,55000,2223};
int max1 = max(arr,arr.length-1,arr[0]);
System.out.println("Max: "+ max1);
}
}
I actually have a pre made class that I setup for finding the largest integer of any set of values. You can put this class into your project and simply use it in any class like so:
System.out.println(figures.getLargest(8,6,12,9,120));
This would return the value "120" and place it in the output. Here is the methods source code if you are interested in using it:
public class figures {
public static int getLargest(int...f) {
int[] score = new int[f.length];
int largest=0;
for(int x=0;x<f.length;x++) {
for(int z=0;z<f.length;z++) {
if(f[x]>=f[z]) {
score[x]++;
}else if(f[x]<f[z]) {
}else {
continue;
}
if(z>=f.length) {
z=0;
break;
}
}
}
for(int fg=0;fg<f.length;fg++) {
if(score[fg]==f.length) {
largest = f[fg];
}
}
return largest;
}
}
The following is a sample code given by my Java instructor, Professor Penn Wu, in one of his lectures. Hope it helps.
import java.util.Random;
public class Recursion
{
static int s = 0;
public static Double max(Double[] d, int n, Double max)
{
if (n==0) { return max;}
else
{
if (d[n] > max)
{
max = d[n];
}
return max(d, n-1, max);
}
}
public static void main(String[] args)
{
Random rn = new Random();
Double[] d = new Double[15];
for (int i=0; i
{
d[i] = rn.nextDouble();
System.out.println(d[i]);
}
System.out.print("\nMax: " + max(d, d.length-1, d[0]));
}
}
Here is my alternative
public class recursion
{
public static int max( int[] n, int index )
{
if(index == n.length-1) // If it's simple, solve it immediately:
return n[index]; // when there's only one number, return it
if(max(n, index+1) > n [index]) // is one number bigger than n?
return max(n, index+1); // return the rest, which contains that bigger number
return n[index]; // if not, return n which must be the biggest number then
}
public static void main(String[] args)
{
int[] n = {100, 3, 5, 1, 2, 10, 2, 15, -1, 20, -1203}; // just some numbers for testing
System.out.println(max(n,0));
}
}

Categories

Resources