Reputation: 325
I have a method overload that goes as follows:
public class Odddetector {
public static void main(String[] args) {
int count = countOdd(new int [] {5, 7, 3, 9, 0});
System.out.println(count);
count = countOdd(new int [] {2, 6, 4, 8, 1});
System.out.println(count);
count = countOdd(5, 7, 10);
System.out.println(count);
count = countOdd(8, 2, 7);
System.out.println(count);
count = countOdd(new int[][] {{1, 2}, {3, 4, 5}});//extra point only
System.out.println(count);
count = countOdd(new int[][] {{6, 2}, {3, 4, 0}});//extra point only
System.out.println(count);
}
public static int countOdd(int[] a){
int count=0;
for (int i: a) count = (i %2 != 0)?++count:count;
return count;
// Do Something;
}
public static int countOdd(int[][] a){
// Do Something;
int count=0;
for (int b = 0; b< a.length; b++){
//System.out.println(java.util.Arrays.toString(a[b])); not a necessary line.
count += countOdd(a[b]);
}
return count;
}
// more method overloading
My question is there a way to condense the solution to have one method that takes into account N-Dimensional Arrays. The code runs fine like this however, I would like to know what Java techniques can help account for the increase in dimensions. I would like to add some details and that is that the first method is the base method, and all the other methods call that first int[] a. The new section I added is the full code I am currently in developing this code which my professor gave as a challenge. I currently have the Data Structures by Lang, and I can accept hints. I prefer hints actually because I would like to learn to code this.
Upvotes: 1
Views: 130
Reputation: 2538
Well, I guess there are some very interesting problems around, all coupled together. Namely
I have a good suggestion for points 3: instead of hardcoding payload in the method itself we can produce IntStream
(or generic Stream
for Object
version) which can be processed separately.
On points 1 and 4 my guess it's probably not possible or at least not elegant. java.lang.reflect.Array
doesn't show any wonder in this and my assumption is - if JDK couldn't do this, I cannot neither. So, the best option is probably to allow general signature with Object
accompanied with couple of frequently used overloads, up to depth 3. Of course, this implies danger of ClassCastExceptions
at runtime.
So, final result with implementation of point 2 may look like this
public class FlattenArray {
public static IntStream flatten(int n) {
return IntStream.of(n);
}
public static IntStream flatten(int[] array) {
return IntStream.of(array);
}
public static IntStream flatten(int[][] array) {
return flatten((Object) array);
}
public static IntStream flatten(Object array) {
Class<?> aClass = array.getClass();
if (!aClass.isArray())
return IntStream.of(((Number) array).intValue());
else {
Class<?> componentType = aClass.getComponentType();
if (componentType.isPrimitive())
return IntStream.of((int[]) array);
else
return Arrays.stream((Object[]) array).flatMapToInt(FlattenArray::flatten);
}
}
}
And use this like
long count = FlattenArray.flatten(2, 3, 5, 7).filter(i -> i & 1 != 0).count();
Upvotes: 1
Reputation: 13533
When the parameter is amulti dimensional array, you can recursively call the function that digs down until you end up with a 1d array of numbers. The logic is:
if a is a multi-dimensional array
for each array in a
call recursively
else
count odd numbers in a
I have 2 functions. One that takes a variable number of args, and a recursive one. The first just calls the second with the var args as an array. The varargs function needs a bit of work if you want to allow mixed parameters (eg: countOdd(new int [] {1,2,3}, 4, 5);
)
// The var args version. You call this. It then calls the recursive
// version.
public static <T> int countOdd(T... arguments)
{
return countOddRec(arguments);
}
// Recursive version
private static <T> int countOddRec(T[] a)
{
if (a == null || a.length == 0) return 0;
int count=0;
// Is it an array of Numbers?
if (a[0] instanceof Number) {
for (T i: a) {
// Simplified the counting code a bit. Any # mod 2 is either 0 or 1
count += ((Number)i).intValue() % 2;
}
}
// Is it an multi-dimensional? Call recursively for each sub-array.
else {
for (T sub : a) {
count += countOddRec((T[])sub);
}
}
return count;
}
As mentioned in the comments, this will not work for primitive data types (ex: int
, etc). Instead, use non-primitive types (ex: Integer
, etc).
Upvotes: 2