Even-odd sort incompatibility - sorting

I am new to Java and I have faced the following problem. I need to sort array of integers in ascending order so that even numbers will be in one half and odd ones in the other.
So, I have a special comparator:
static class EvenOddSort implements Comparator<Integer> {
#Override
public int compare(Integer x, Integer y) {
if (x == y) {
return 0;
}
if (y % 2 == 0) {
if (x < y) {
return -1;
} else {
return 1;
}
}
if (x % 2 == 0) {
if (x < y) {
return 1;
} else {
return -1;
}
}
return 0;
}
}
And the following sort method:
public Integer[] sortEvenOdd(Integer[] nums) {
EvenOddSort customSort = new EvenOddSort();
Arrays.sort(nums, customSort);
return nums;
}
Also I have the following test:
#Test
public void testSortEvenOdd1() {
Integer[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Integer[] expected = { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 };
assertArrayEquals(expected, tasks5.sortEvenOdd(nums));
}
It fails when I run it on openJDK6 and successful on openJDK7.
arrays first differed at element [0]; expected:<2> but was:<1> junit.framework.AssertionFailedError: arrays first differed at element [0]; expected:<2> but was:<1>
Could you help me to make it compatible across all openJDK's?
Also, it would be great to know what I am doing wrong.
Any ideas are welcome!

Your whole comparator is broken, I kept seeing more problems with it.
Just do something like this:
if (x%2 != y%2) {
if (x%2==0) {
return -1;
} else {
return 1;
}
} else {
return x.compareTo(y);
}
First check to see if they are not both odd or both even. If they are different then sort based on odd or even.
Then if they are both odd or both even fall back to the standard Integer compare functionality.

Related

Suggestion to write a number as a sum of three numbers where each number is at least two

I'm trying to find all possible combinations to write a number as a sum of three numbers, where each number is at least 2.
So basically for 6 it would be like:
2 2 2
For 7 it would be:
2 2 3 or 2 3 2 or 3 2 2
I was wondering if there's a better approach to this than running 3 loops.
EDIT:
public class Problem {
public static void main(String args[]) {
int N = 7, n1, n2, n3;
for (n1 = 2; n1 <= N; n1++) {
for (n2 = 2; n2 <= N; n2++) {
for (n3 = 2; n3 <= N; n3++) {
if ( (n1+n2+n3)==N ) {
System.out.println(n1 + " " + n2 + " " + n3);
}
}
}
}
}
}
This solution works, but I was thinking if there's another approach to this.
You're looking to partition an integer n into k parts, where each part has a minimum value min. The classic approach here would be to use recursion.
Initially we create an array to hold the parts, initialize them to min and remove k*min from n to get the remainder.
static List<int[]> partitions(int n, int k, int min)
{
int[] parts = new int [k];
Arrays.fill(parts, min);
int rem = n - k*min;
List<int[]> results = new ArrayList<>();
partition(results, parts, rem);
return results;
}
We now use a recursive method to explore adding 1 to each of the parts in turn. If the remainder reaches 0 we have a solution and add the current solution to the results.
static void partition(List<int[]> results, int[] parts, int rem)
{
if(rem <= 0)
{
if(rem == 0) results.add(parts.clone());
return;
}
for(int i=0; i<parts.length; i++)
{
parts[i] += 1;
partition(results, parts, rem-1);
parts[i] -= 1;
}
}
Test:
public static void main(String[] args)
{
for(int[] res : partitions(7, 3, 2))
System.out.println(Arrays.toString(res));
}
Output:
[3, 2, 2]
[2, 3, 2]
[2, 2, 3]
it is my suggestion
create a class to model each answer of equation here we create a static inner class to model each answer:
public static class Answer{
private int a;
private int b;
private int c;
public Answer(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
public int getA() {
return a;
}
public int getB() {
return b;
}
public int getC() {
return c;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Answer answer = (Answer) o;
return a == answer.a &&
b == answer.b &&
c == answer.c;
}
#Override
public int hashCode() {
return Objects.hash(a, b, c);
}
#Override
public String toString() {
return "Answer{" +
"a=" + a +
", b=" + b +
", c=" + c +
'}';
}
}
then a recursive algorithm to produce results:
// don't call this method directly only combination method must call it
private Set<Answer> combinationHelper(int n){
Set<Answer> results = new HashSet<>();
if(n < 0)
return results;
if(n == 0) {
results.add(new Answer(0, 0, 0));
return results;
}
Set<Answer> remain = combinationHelper(n - 1);
remain.forEach(element -> {
int a = element.getA();
int b = element.getB();
int c = element.getC();
results.add(new Answer(a + 1, b, c));
results.add(new Answer(a, b + 1, c));
results.add(new Answer(a, b, c + 1));
});
return results;
}
public Set<Answer> combination(int n){
Set<Answer> results = combinationHelper(n - 6);
return results.stream()
.map(a -> new Answer(a.getA() + 2, a.getB() + 2, a.getC() + 2))
.collect(Collectors.toSet());
}
then call it like this:
System.out.println(new Comb().combination(6));
System.out.println(new Comb().combination(7));
which produces results:
[Answer{a=2, b=2, c=2}]
[Answer{a=2, b=3, c=2}, Answer{a=3, b=2, c=2}, Answer{a=2, b=2, c=3}]
if you don't like the idea of adding another model class to your application you can easily use arrays instead
non-recursive approach:
public List<String> combination(int n){
List<String> result = new ArrayList<>();
if(n < 6)
return result;
BitSet bits = new BitSet(n - 6);
bits.set(0, n - 6);
IntStream
.range(0, n - 5)
.forEach(i ->
IntStream.range(i, n - 5).forEach(j ->
result.add(String.format("%s %d %d %d %s", "{", bits.get(0, i).length() + 2, bits.get(i, j).length() + 2, bits.get(j, n).length() + 2, "}"))));
return result;
}
results for non-recursive approach:
for input 7:
[{ 2 2 3 }, { 2 3 2 }, { 3 2 2 }]
for input 6:
[{ 2 2 2 }]

Easy way to sort default array in Vala

I tried it like this, but it doesn't work. And I think it's too complicated a way to sort an array. I need something like System.Array.Sort () of C#
int[] data = { 3, 9, 2, 7, 5 };
var arr = new Array<int> ();
arr.append_vals (data,data.length);
arr.sort((a, b) => {
return (int) (a > b) - (int) (a < b);
});
for (int i=0;i<arr.length;i++) {
print(#"$(arr.index(i))\t");
}
also tried that, the array is still not sorted.
using Posix;
int cmpfunc(ref int a, ref int b) {
return (int) (a > b) - (int) (a < b);
}
void main() {
int[] data = { 3, 9, 2, 7, 5 };
Posix.qsort (data, data.length, sizeof(string), (Posix.compar_fn_t) cmpfunc);
foreach (int st in data) {
print(#"$st\t");
}
}
The Posix.qsort function needs to know the size of each element in the array, sizeof(int), but you're giving it the size of a different type, sizeof(string).

Choose n unique elements from n lists

I have been thinking about a programing problem. If we have n lists, we want to output n diffrent elements (each one from a different list). I suspect this can be solved with some kind of a backtrack algorithm but I don't see how to correctly implement it.
Though you could solve this with backtracking as suggested in a comment, a more efficient solution would be to use a max-flow algorithm.
Model it as a graph. A Source, a Sink a node for each distinct element and a node for each list.
You have the source connected to each distinct element. Each element connected to every list it is in. and the lists connected to a sink node. Each edge with capacity 1.
The maximum flow is the maximum number of distinct elements from distinct lists you can select.
https://en.wikipedia.org/wiki/Maximum_flow_problem
https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm
I'm not exactly sure that this has no bugs and solves what is being asked; and I hope I have understood the question right this time :)
//test
int[][] arr = new int[][] {
new int[] { 1, 1, 1, 1, 6 },
new int[] { 1, 1, 1, 1, 5 },
new int[] { 1, 1, 1, 4, 9 },
new int[] { 1, 1, 3, 8, 1 },
new int[] { 1, 2, 7, 1, 1 },
new int[] { 1, 1, 1, 1, 1 } };
int[] res = getItems(arr).ToArray(); //6,5,4,3,2,1
private static IEnumerable<T> getItems<T>(T[][] array)
{
int N = array.GetLength(0);
item<T>[] items = new item<T>[N];
HashSet<T> hs = new HashSet<T>();
for (int i = 0; i < N; i++)
{
bool ok = false;
T[] arr = array[i];
for (int j = items[i].Index; j < arr.Length; j++)
{
T val = arr[j];
if (hs.Add(val))
{
items[i] = new item<T>() { Val = val, Index = j };
ok = true;
break;
}
}
if (!ok)
{
item<T> item;
do
{
if (i == 0) throw new Exception("no solution");
items[i] = new item<T>();
item = items[--i];
item.Index++;
items[i] = item;
}
while (item.Index >= array[i].Length);
hs.Clear();
for (int j = 0; j < i; j++)
hs.Add(array[j][items[j].Index]);
i--;
}
}
return hs;
}
private struct item<T>
{
public T Val;
public int Index;
public override string ToString()
{
return string.Format("Val:{0} Index:{1}", Val, Index);
}
}

Optimal way to group time intervals based on projected points

Imagine we have sorted list of time intervals (sorted by time of beginning).
I'm looking for optimal solution to 'project' these intervals to axis, having as a result an array of objects, describing: projected interval start&end time and arrays of source intervals that fall into projected intevals.
Let me explain on example: imagine we have 4 intervals as input (sorted by start time, then by end time):
[---R1---)
[-----R2-----)
[---------R3-------)
[----R4----)
--|-----|--|----|----|-----|---> t (time axis)
1 3 2 3 2
In that case I'm expecting to get array of 5 elements, each element is an object describing interval start/end and a list of source intervals. Numbers under axis on chart shows number of items in that list.
Please, help me to find fastest way to solve this task
Something like this?
def groupIntervals(intervals):
events = {}
for start, stop, name in intervals:
if start not in events: events[start] = []
events[start].append(('start', name))
if stop not in events: events[stop] = []
events[stop].append(('stop', name))
last = None
output = []
active = set()
for time in sorted(events.keys()):
if active and last is not None:
output.append((last, time, active.copy()))
last = time
for action, name in events[time]:
if action == 'start': active.add(name)
elif action == 'stop': active.remove(name)
else: assert False
return output
Example usage:
>>> groupIntervals([(1, 3, 'R1'), (2, 5, 'R2'), (2, 6, 'R3'),
... (4, 6, 'R4')])
[(1, 2, set(['R1'])),
(2, 3, set(['R1', 'R2', 'R3'])),
(3, 4, set(['R2', 'R3'])),
(4, 5, set(['R4', 'R2', 'R3'])),
(5, 6, set(['R4', 'R3']))]
C++ version with cleverer data structure usage.
#include <cstdio>
#include <limits>
#include <list>
#include <queue>
#include <string>
#include <vector>
struct Interval {
Interval(std::string name, int start, int stop);
std::string name;
int start;
int stop;
};
Interval::Interval(std::string name, int start, int stop)
: name(name), start(start), stop(stop) {
}
typedef std::list<std::vector<Interval>::const_iterator> ActiveList;
struct StopEvent {
StopEvent(int stop, ActiveList::iterator j);
int stop;
ActiveList::iterator j;
};
StopEvent::StopEvent(int stop, ActiveList::iterator j)
: stop(stop), j(j) {
}
struct StopEventGreater {
bool operator()(StopEvent const& a,
StopEvent const& b) const;
};
bool StopEventGreater::operator()(StopEvent const& a,
StopEvent const& b) const {
return a.stop > b.stop;
}
void Sweep(std::vector<Interval> const& intervals) {
std::vector<Interval>::const_iterator i(intervals.begin());
std::priority_queue<StopEvent,
std::vector<StopEvent>,
StopEventGreater> active_queue;
ActiveList active_list;
int last_time(std::numeric_limits<int>::min());
while (i != intervals.end() || !active_queue.empty()) {
bool start(i != intervals.end() &&
(active_queue.empty() || i->start < active_queue.top().stop));
int time(start ? i->start : active_queue.top().stop);
if (time != last_time && !active_list.empty()) {
std::printf("[%d, %d):", last_time, time);
for (ActiveList::const_iterator j(active_list.begin());
j != active_list.end();
++j) {
std::printf(" %s", (*j)->name.c_str());
}
std::putchar('\n');
}
last_time = time;
if (start) {
active_queue.push(StopEvent(i->stop,
active_list.insert(active_list.end(), i)));
++i;
} else {
active_list.erase(active_queue.top().j);
active_queue.pop();
}
}
}
int main(void) {
std::vector<Interval> intervals;
intervals.push_back(Interval("R1", 0, 4));
intervals.push_back(Interval("R2", 1, 9));
intervals.push_back(Interval("R3", 1, 11));
intervals.push_back(Interval("R4", 6, 11));
Sweep(intervals);
}
Finally I've found the most effective way. It uses one sorting operation and O(N*2) iterations to build result.
public IEnumerable<DateProjectedItems<T>> Project(IList<T> items)
{
if (items.Count <= 1)
{
if (items.Count == 0)
{
yield break;
}
yield return new DateProjectedItems<T>
{
DateRange = items[0].DateRange,
Items = items
};
}
else
{
var endOrdered = items.OrderBy(i => i.DateRange.DateTimeTo).ToList();
var active = new List<T>();
DateTime? last = null;
foreach (var pair in TwoArrayIterator(items, endOrdered))
{
DateTime current = pair.Key == 1 ? pair.Value.DateRange.DateTimeFrom : pair.Value.DateRange.DateTimeTo;
if (last != null && current != last)
{
yield return new DateProjectedItems<T>
{
DateRange = new DateRange(last.Value, current),
Items = active.ToList()
};
}
if (pair.Key == 1)
{
active.Add(pair.Value);
}
else
{
active.Remove(pair.Value);
}
last = current;
}
}
}
public IEnumerable<KeyValuePair<int, T>> TwoArrayIterator(IList<T> arr1, IList<T> arr2)
{
var index1 = 0;
var index2 = 0;
while (index1 < arr1.Count || index2 < arr2.Count)
{
if (index1 >= arr1.Count)
yield return new KeyValuePair<int, T>(2, arr2[index2++]);
else if (index2 >= arr2.Count)
yield return new KeyValuePair<int, T>(1, arr1[index1++]);
else
{
var elt1 = arr1[index1];
var elt2 = arr2[index2];
if (elt1.DateRange.DateTimeFrom < elt2.DateRange.DateTimeTo)
{
index1++;
yield return new KeyValuePair<int, T>(1, elt1);
}
else
{
index2++;
yield return new KeyValuePair<int, T>(2, elt2);
}
}
}
}

An even and sorted distribution problem

I have a given number of boxes in a specific order and a number of weights in a specific order. The weights may have different weights (ie one may weigh 1kg, another 2kg etc).
I want to put the weights in the boxes in a way so that they are as evenly distributed as possible weight wise. I must take the weights in the order that they are given and I must fill the boxes in the order that they are given. That is if I put a weight in box n+1 I cannot put a weight in box n, and I cannot put weight m+1 in a box until I've first put weight m in a box.
I need to find an algorithm that solves this problem for any number of boxes and any set of weights.
A few tests in C# with xUnit (Distribute is the method that should solve the problem):
[Fact]
public void ReturnsCorrectNumberOfBoxes()
{
int[] populatedColumns = Distribute(new int[0], 4);
Assert.Equal<int>(4, populatedColumns.Length);
}
[Fact]
public void Test1()
{
int[] weights = new int[] { 1, 1, 1, 1 };
int[] boxes = Distribute(weights, 4);
Assert.Equal<int>(weights[0], boxes[0]);
Assert.Equal<int>(weights[1], boxes[1]);
Assert.Equal<int>(weights[2], boxes[2]);
Assert.Equal<int>(weights[3], boxes[3]);
}
[Fact]
public void Test2()
{
int[] weights = new int[] { 1, 1, 17, 1, 1 };
int[] boxes = Distribute(weights, 4);
Assert.Equal<int>(2, boxes[0]);
Assert.Equal<int>(17, boxes[1]);
Assert.Equal<int>(1, boxes[2]);
Assert.Equal<int>(1, boxes[3]);
}
[Fact]
public void Test3()
{
int[] weights = new int[] { 5, 4, 6, 1, 5 };
int[] boxes = Distribute(weights, 4);
Assert.Equal<int>(5, boxes[0]);
Assert.Equal<int>(4, boxes[1]);
Assert.Equal<int>(6, boxes[2]);
Assert.Equal<int>(6, boxes[3]);
}
Any help is greatly appreciated!
See the solution below.
Cheers,
Maras
public static int[] Distribute(int[] weights, int boxesNo)
{
if (weights.Length == 0)
{
return new int[boxesNo];
}
double average = weights.Average();
int[] distribution = new int[weights.Length];
for (int i = 0; i < distribution.Length; i++)
{
distribution[i] = 0;
}
double avDeviation = double.MaxValue;
List<int> bestResult = new List<int>(boxesNo);
while (true)
{
List<int> result = new List<int>(boxesNo);
for (int i = 0; i < boxesNo; i++)
{
result.Add(0);
}
for (int i = 0; i < weights.Length; i++)
{
result[distribution[i]] += weights[i];
}
double tmpAvDeviation = 0;
for (int i = 0; i < boxesNo; i++)
{
tmpAvDeviation += Math.Pow(Math.Abs(average - result[i]), 2);
}
if (tmpAvDeviation < avDeviation)
{
bestResult = result;
avDeviation = tmpAvDeviation;
}
if (distribution[weights.Length - 1] < boxesNo - 1)
{
distribution[weights.Length - 1]++;
}
else
{
int index = weights.Length - 1;
while (distribution[index] == boxesNo - 1)
{
index--;
if (index == -1)
{
return bestResult.ToArray();
}
}
distribution[index]++;
for (int i = index; i < weights.Length; i++)
{
distribution[i] = distribution[index];
}
}
}
}
Second try: i think the A* (pronounced "a star") algorithm would work well here, even if it would consume a lot of memory. you are guranteed to get an optimal answer, if one exists.
Each "node" you are searching is a possible combination of weights in boxes. The first node should be any weight you pick at random, put into a box. I would recommend picking new weights randomly as well.
Unforetunately, A* is complex enough that I don't have time to explain it here. It is easy enough to understand by reading on your own, but mapping it to this problem as I described above will be more difficult. Please post back questions on that if you choose this route.

Resources