Java - crossover algorithm - java

I working on android app for TSP problem.
I have a crossover algorithm and i want minimize number of loops for faster algorithm.
How I can do it?
This is the code:
public static Path crossover(Path dad, Path mom) {
//Create new child path
Path child = new Path();
//Get start and sub path positions for dads path
double startPos = (double) (Math.random() * dad.pathSize());
double endPos = (double) (Math.random() * dad.pathSize());
//Loop and add the sub path from dad to our child
for (int i = 0; i < child.pathSize(); i++) {
//If our start position is less than the end position
if (startPos < endPos && i > startPos && i < endPos) {
child.setDestination(i, dad.getDestination(i));
} // if our start position is larger
else if (startPos > endPos) {
if (!(i < startPos && i > endPos)) {
child.setDestination(i, dad.getDestination(i));
}
}
}
// Loop through mom destination path
for (int i = 0; i < mom.pathSize(); i++){
// If child doesn't have the destination add it
if (!child.containsDestination(mom.getDestination(i))) {
// Loop to find a spare position in the child's path
for (int j = 0; j < child.pathSize(); j++) {
//Spare position found, add destination
if (child.getDestination(j) == null) {
child.setDestination(j, mom.getDestination(i));
break;
}
}
}
}
return child;
}

If I understand the GA crossover correctly, you may only employ one for loop returning a child from parents.
Please have a look at my sample code:
public Chromosomes crossoverChrom(Chromosomes inpChrom1, Chromosomes inpChrom2){
// offspring chromosome has the same size as the target chromosome
Chromosomes offspring = new Chromosomes(inpChrom1.getGenes().length);
for (int i = 0; i < offspring.getGenes().length;i++){
double randOffspring = Math.random();
// System.out.println("i_offspring [" + i + "] , randOffspring = " + randOffspring);
if(randOffspring <= crossoverRate){
// System.out.println("gene from chrom 1");
offspring.setGenes(i, inpChrom1.getGenes()[i]);
} else {
// System.out.println("gene from chrom 2");
offspring.setGenes(i, inpChrom2.getGenes()[i]);
}
}
// System.out.println("Offspring = " + offspring + " | Fitness = " + offspring.getFitness());
// System.out.println("--------------------------------------------------");
return offspring;
}

Related

Traveling salesman code not working (Java)

Traveling salesman code in java below (gives wrong result)
http://www.sanfoundry.com/java-program-solve-travelling-salesman-problem-unweighted-graph/
package com.hinguapps.graph;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TSP {
private int numberOfNodes;
private Stack < Integer > stack;
public TSP() {
stack = new Stack < Integer > ();
}
public void tsp(int adjacencyMatrix[][]) {
numberOfNodes = adjacencyMatrix[1].length - 1;
int[] visited = new int[numberOfNodes + 1];
visited[1] = 1;
stack.push(1);
int element, dst = 0, i;
int min = Integer.MAX_VALUE;
boolean minFlag = false;
System.out.print(1 + "\t");
while (!stack.isEmpty()) {
element = stack.peek();
i = 1;
min = Integer.MAX_VALUE;
while (i <= numberOfNodes) {
if (adjacencyMatrix[element][i] > 1 && visited[i] == 0) {
if (min > adjacencyMatrix[element][i]) {
min = adjacencyMatrix[element][i];
dst = i;
minFlag = true;
}
}
i++;
}
if (minFlag) {
visited[dst] = 1;
stack.push(dst);
System.out.print(dst + "\t");
minFlag = false;
continue;
}
stack.pop();
}
}
public static void main(String...arg) {
int number_of_nodes;
Scanner scanner = null;
try {
System.out.println("Enter the number of nodes in the graph");
scanner = new Scanner(System.in);
number_of_nodes = scanner.nextInt();
int adjacency_matrix[][] = new int[number_of_nodes + 1][number_of_nodes + 1];
System.out.println("Enter the adjacency matrix");
for (int i = 1; i <= number_of_nodes; i++) {
for (int j = 1; j <= number_of_nodes; j++) {
adjacency_matrix[i][j] = scanner.nextInt();
}
}
for (int i = 1; i <= number_of_nodes; i++) {
for (int j = 1; j <= number_of_nodes; j++) {
if (adjacency_matrix[i][j] == 1 &&
adjacency_matrix[j][i] == 0) {
adjacency_matrix[j][i] = 1;
}
}
}
System.out.println("The cities are visited as follows: ");
TSP tspNearestNeighbour = new TSP();
tspNearestNeighbour.tsp(adjacency_matrix);
} catch (InputMismatchException inputMismatch) {
System.out.println("Wrong Input format");
}
scanner.close();
}
}
Matrix should be :
0 10 5 40
2 0 5 1
6 13 0 12
1 8 9 0
Expected result: 1 3 2 4 1
Code result : 1 3 4 2 1
This implementation is wrong. This is a hard problem, because you need to either touch every path, or at the very least CONSIDER every path. This implementation basically boils down to "Each step, move to the closest node that I haven't visited". Since the stack is not keeping memory of where you have been, it does not backtrack to consider that a better path may have existed down one of the longer roads.
To fix this, the algorithm needs to keep the path in memory somehow, and not start printing the solution until the best solution has actually been found. (Can use recursion, a stack that holds the whole path, or some other method.)

Printing integer from 2D array using nested FOR Loops

I'm having a bit of a problem with a piece of Java code, part of an AI project. The programm is supposed to take a 11x13 2d array representing a maze. The printed maze we are given uses characters for each cell, but for ease of use I've converted it to integers using a mnemonic code.
My problem is when I try to print the 2d integer array to the screen, to check eveything is OK, I get zeros at every cell, even though I have a check function in place which parses the array cell-by-cell checking for incorrect values.
The project is currently composed of 2 files. The main file - function (AISemesterProject.java) and a file that will implement the UCS algorithm in the future (UCS.java)
AISemesterProject.java
package aisemesterproject;
public class AISemesterProject
{
public static void main(String[] args)
{
UCS a = new UCS();
a.checkArrayInt();
a.printInt();
}
}
UCS.java
package aisemesterproject;
import java.util.Arrays;
public class UCS
{
int row = 11;
int col = 13;
int[][] array_int = new int[row][col];
public UCS()
{
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
int[][] array_int = new int[][] {
{0,1,0,1,1,1,1,0,0,1,0,9,0},
{1,1,1,2,0,1,1,0,0,1,2,1,0},
{0,1,0,1,1,1,1,0,0,1,0,0,0},
{8,1,2,0,1,2,0,1,1,2,1,1,1},
{0,0,1,1,0,1,1,1,0,0,0,0,0},
{1,2,1,0,1,0,1,1,0,0,1,1,1},
{0,1,2,0,1,0,0,2,1,1,2,1,9},
{1,0,1,1,2,1,1,1,0,1,1,1,1},
{1,1,2,1,1,0,0,1,0,0,0,0,0},
{0,0,1,1,1,0,0,1,1,1,1,1,2},
{0,0,1,0,0,1,1,1,0,9,0,1,1}
};
}
public void checkArrayInt()
{
int i = 0, j = 0;
boolean checker = false;
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
if(!(array_int[i][i] == 0 || array_int[i][j] == 1 || array_int[i][j] == 2 || array_int[i][j] == 8 || array_int[i][j] == 9))
{
checker = true;
System.out.print("Error at Row:" + i + " Column:" + j + "\n");
}
}
}
if(checker == false)
{
System.out.print("Array OK... \n");
}
}
public void printInt()
{
int i = 0, j = 0;
//System.out.println(Arrays.deepToString(array_int));
for(i = 0; i < row; i++)
{
System.out.print("Row " + (i + 1) + ":");
for(j = 0; j < col; j++)
{
System.out.print(" " + String.valueOf(array_int[i][j]));
//System.out.print(" " + Integer.toString(array_int[i][j]));
//System.out.printf(" %d", array_int[i][j]);
//System.out.print(" " + array_int[i][j]);
}
System.out.print("\n");
}
}
}
Output
As you can see the output is not what I expected and I have tried 4 different methods for the print (1 active, 3 commented) but the result is always the same.
Anyone have an idea what am I missing or doing wrong?
Thanks for your time.
It looks like you have a scope issue...
int[][] array_int = new int[row][col];
public UCS()
{
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
array_int = new int[][] {
{0,1,0,1,1,1,1,0,0,1,0,9,0},
{1,1,1,2,0,1,1,0,0,1,2,1,0},
{0,1,0,1,1,1,1,0,0,1,0,0,0},
{8,1,2,0,1,2,0,1,1,2,1,1,1},
{0,0,1,1,0,1,1,1,0,0,0,0,0},
{1,2,1,0,1,0,1,1,0,0,1,1,1},
{0,1,2,0,1,0,0,2,1,1,2,1,9},
{1,0,1,1,2,1,1,1,0,1,1,1,1},
{1,1,2,1,1,0,0,1,0,0,0,0,0},
{0,0,1,1,1,0,0,1,1,1,1,1,2},
{0,0,1,0,0,1,1,1,0,9,0,1,1}
};
you already created the array as a class level variable
Your constructor is setting the local variable array_int. This local variable overshadows the field with the same name, and thus it never sees the array you're assigning to it.
You should make sure that you're assigning to the field, which can most easily be done by removing the int[][] word from your constructor.
Thank you everyone. I moved the declatarion from the constructor to the variable at the beggining and it worked.
package aisemesterproject;
import java.util.Arrays;
public class UCS
{
int row = 11;
int col = 13;
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
int[][] array_int = new int[][] {
{0,1,0,1,1,1,1,0,0,1,0,9,0},
{1,1,1,2,0,1,1,0,0,1,2,1,0},
{0,1,0,1,1,1,1,0,0,1,0,0,0},
{8,1,2,0,1,2,0,1,1,2,1,1,1},
{0,0,1,1,0,1,1,1,0,0,0,0,0},
{1,2,1,0,1,0,1,1,0,0,1,1,1},
{0,1,2,0,1,0,0,2,1,1,2,1,9},
{1,0,1,1,2,1,1,1,0,1,1,1,1},
{1,1,2,1,1,0,0,1,0,0,0,0,0},
{0,0,1,1,1,0,0,1,1,1,1,1,2},
{0,0,1,0,0,1,1,1,0,9,0,1,1}
};
public UCS()
{
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
// Array initialization outside the constructor scope
}
public void checkArrayInt()
{
int i = 0, j = 0;
boolean checker = false;
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
if(array_int[i][j] == 0) //Check for 0 = x
{
checker = false;
}
else if(array_int[i][j] == 1) //Check for 1 = e
{
checker = false;
}
else if(array_int[i][j] == 2) //Check for 2 = d
{
checker = false;
}
else if(array_int[i][j] == 8) //Check for 8 = s
{
checker = false;
}
else if(array_int[i][j] == 9) //Check for 9 = g
{
checker = false;
}
else //All other integers, which are false
{
checker = true;
System.out.print("Error at Row:" + i + " Column:" + j + "\n");
}
}
}
if(checker == false)
{
System.out.print("Array OK... \n");
}
}
public void printInt()
{
int i = 0, j = 0;
//System.out.println(Arrays.deepToString(array_int));
for(i = 0; i < row; i++)
{
System.out.print("Row " + (i + 1) + ":");
for(j = 0; j < col; j++)
{
System.out.print(" " + String.valueOf(array_int[i][j]));
//System.out.print(" " + Integer.toString(array_int[i][j]));
//System.out.printf(" %d", array_int[i][j]);
//System.out.print(" " + array_int[i][j]);
}
System.out.print("\n");
}
}
}

How can I optimize my java implementation of Held-Karp algorithm to shorten the running time?

I use Java implemented Held-KarpTSP algorithm algo to solve a 25 cities TSP problem.
The program passes with 4 cities.
When it runs with 25 cities it won't stop for several hours. I use jVisualVM to see what's the hotspot, after some optimization now it shows
98% of time is in real computing instead in Map.contains or Map.get.
So I'd like to have your advice, and here is the code:
private void solve() throws Exception {
long beginTime = System.currentTimeMillis();
int counter = 0;
List<BitSetEndPointID> previousCosts;
List<BitSetEndPointID> currentCosts;
//maximum number of elements is c(n,[n/2])
//To calculate m-set's costs just need to keep (m-1)set's costs
List<BitSetEndPointID> lastKeys = new ArrayList<BitSetEndPointID>();
int m;
if (totalNodes < 10) {
//for test data, generate them on the fly
SetUtil3.generateMSet(totalNodes);
}
//m=1
BitSet beginSet = new BitSet();
beginSet.set(0);
previousCosts = new ArrayList<BitSetEndPointID>(1);
BitSetEndPointID beginner = new BitSetEndPointID(beginSet, 0);
beginner.setCost(0f);
previousCosts.add(beginner);
//for m=2 to totalNodes
for (m = 2; m <= totalNodes; m++) {// sum(m=2..n 's C(n,m)*(m-1)(m-1)) ==> O(n^2 * 2^n)
//pick m elements from total nodes, the element id is the index of nodeCoordinates
// the first node is always present
BitSet[] msets;
if (totalNodes < 10) {
msets = SetUtil3.msets[m - 1];
} else {
//for real data set, will read from serialized file
msets = SetUtil3.getMsets(totalNodes, m-1);
}
currentCosts = new ArrayList<BitSetEndPointID>(msets.length);
//System.out.println(m + " sets' size: " + msets.size());
for (BitSet mset : msets) { //C(n,m) mset
int[] candidates = allSetBits(mset, m);
//mset is a BitSet which makes sure begin point 0 comes first
//so end point candidate begins with 1. candidate[0] is always begin point 0
for (int i = 1; i < candidates.length; i++) { // m-1 bits are set
//set the new last point as j, j must not be the same as begin point 0
int j = candidates[i];
//middleNodes = mset -{j}
BitSet middleNodes = (BitSet) mset.clone();
middleNodes.clear(j);
//loop through all possible points which are second to the last
//and get min(A[S-{j},k] + k->j), k!=j
float min = Float.MAX_VALUE;
int k;
for (int ki = 0; ki < candidates.length; ki++) {// m-1 calculation
k = candidates[ki];
if (k == j) continue;
float middleCost = 0;
BitSetEndPointID key = new BitSetEndPointID(middleNodes, k);
int index = previousCosts.indexOf(key);
if (index != -1) {
//System.out.println("get value from map in m " + m + " y key " + middleNodes);
middleCost = previousCosts.get(index).getCost();
} else if (k == 0 && !middleNodes.equals(beginSet)) {
continue;
} else {
System.out.println("middleCost not found!");
continue;
// System.exit(-1);
}
float lastCost = distances[k][j];
float cost = middleCost + lastCost;
if (cost < min) {
min = cost;
}
counter++;
if (counter % 500000 == 0) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException iex) {
System.out.println("Who dares interrupt my precious sleep?!");
}
}
}
//set the costs for chosen mset and last point j
BitSetEndPointID key = new BitSetEndPointID(mset, j);
key.setCost(min);
currentCosts.add(key);
// System.out.println("===========================================>mset " + mset + " and end at " +
// j + " 's min cost: " + min);
// if (m == totalNodes) {
// lastKeys.add(key);
// }
}
}
previousCosts = currentCosts;
System.out.println("...");
}
calcLastStop(lastKeys, previousCosts);
System.out.println(" cost " + (System.currentTimeMillis() - beginTime) / 60000 + " minutes.");
}
private void calcLastStop(List<BitSetEndPointID> lastKeys, List<BitSetEndPointID> costs) {
//last step, calculate the min(A[S={1..n},k] +k->1)
float finalMinimum = Float.MAX_VALUE;
for (BitSetEndPointID key : costs) {
float middleCost = key.getCost();
Integer endPoint = key.lastPointID;
float lastCost = distances[endPoint][0];
float cost = middleCost + lastCost;
if (cost < finalMinimum) {
finalMinimum = cost;
}
}
System.out.println("final result: " + finalMinimum);
}
You can speed up your code by using arrays of primitives (it's likely to have to better memory layout than a list of objects) and operating on bitmasks directly (without bitsets or other objects). Here is some code (it generates a random graph but you can easily change it so that it reads your graph):
import java.io.*;
import java.util.*;
class Main {
final static float INF = 1e10f;
public static void main(String[] args) {
final int n = 25;
float[][] dist = new float[n][n];
Random random = new Random();
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
dist[i][j] = dist[j][i] = random.nextFloat();
float[][] dp = new float[n][1 << n];
for (int i = 0; i < dp.length; i++)
Arrays.fill(dp[i], INF);
dp[0][1] = 0.0f;
for (int mask = 1; mask < (1 << n); mask++) {
for (int lastNode = 0; lastNode < n; lastNode++) {
if ((mask & (1 << lastNode)) == 0)
continue;
for (int nextNode = 0; nextNode < n; nextNode++) {
if ((mask & (1 << nextNode)) != 0)
continue;
dp[nextNode][mask | (1 << nextNode)] = Math.min(
dp[nextNode][mask | (1 << nextNode)],
dp[lastNode][mask] + dist[lastNode][nextNode]);
}
}
}
double res = INF;
for (int lastNode = 0; lastNode < n; lastNode++)
res = Math.min(res, dist[lastNode][0] + dp[lastNode][(1 << n) - 1]);
System.out.println(res);
}
}
It takes only a couple of minutes to complete on my computer:
time java Main
...
real 2m5.546s
user 2m2.264s
sys 0m1.572s

Find shortest flying time to destination array Java

So I have been assigned this monster program
public class AirlineRoutes
{
private int[][] routes;
/**
* Creates a table with direct flight times for a group of cities.
*/
public AirlineRoutes(int[][] routes)
{
this.routes = routes;
}
/**
* Returns the shortest flying time from start to destination
* going through at most one intermediate city.
* #precondition 1 <= start <= N (where N is size of matrix)
* #precondition 1 <= destination <= N (where N is size of matrix)
* Note that cities are labeled 1 to N , whereas the matrix
* is indexed from 0 to N-1
* #param start the city to start the flight from
* #param destination the city to end the flight at
* #return returns the least number of hours going from start
* city to destination. The flight can be direct or
* have a stop in one other city - Destination travleing
* through at most one intermediate city.
*/
public int minTime(int start, int destination)
{
}
/**
* Returns a string containing a chart showing the times
* to each city in hours.
* #return a table showing the time in hours for direct
* flights from every city.
*/
public String toString()
{
String s = "\t\t\tDestination City\n\t\t";
s += "\n\t\t\t";
for (int k = 1; k <= routes[0].length; k++)
s += "\t" + k;
s += "\n\t\t";
for (int k = 0; k <= routes[0].length; k++)
s += "----";
s += "-\n";
for (int r = 0; r < routes[0].length; r++)
{
if (r == 1)
s += "Start";
else if (r == 2)
s += "City";
else
s += "\t";
s += "\t" + (r+1) + "\t|\t";
for (int c = 0; c < routes[r].length; c++)
s += routes[r][c] + "\t";
s += "\n";
}
return s;
}
}
public class AirlineRoutesDriver
{
public static void main(String[] args)
{
int[][] routes = new int[4][4];
for (int k = 0; k < routes.length; k++)
routes[k][k] = 0;
routes[0][1] = 3;
routes[0][2] = 2;
routes[0][3] = 6;
routes[1][0] = 3;
routes[1][2] = 1;
routes[1][3] = 3;
routes[2][0] = 2;
routes[2][1] = 1;
routes[2][3] = 5;
routes[3][0] = 5;
routes[3][1] = 4;
routes[3][2] = 2;
AirlineRoutes r = new AirlineRoutes(routes);
System.out.println(r);
System.out.println("From city 4 to city 1 takes " + r.minTime(4,1) + " hours");
System.out.println("From city 1 to 3 to city " + r.minTime(1,3) + " hours");
System.out.println("From city 3 to 3 to city " + r.minTime(3,3) + " hours");
}
}
public class AirlineRoutesDriver
{
public static void main(String[] args)
{
int[][] routes = new int[4][4];
for (int k = 0; k < routes.length; k++)
routes[k][k] = 0;
routes[0][1] = 3;
routes[0][2] = 2;
routes[0][3] = 6;
routes[1][0] = 3;
routes[1][2] = 1;
routes[1][3] = 3;
routes[2][0] = 2;
routes[2][1] = 1;
routes[2][3] = 5;
routes[3][0] = 5;
routes[3][1] = 4;
routes[3][2] = 2;
AirlineRoutes r = new AirlineRoutes(routes);
System.out.println(r);
System.out.println("From city 4 to city 1 takes " + r.minTime(4,1) + " hours");
System.out.println("From city 1 to 3 to city " + r.minTime(1,3) + " hours");
System.out.println("From city 3 to 3 to city " + r.minTime(3,3) + " hours");
}
}
I don't know what to do for the minTime() method. I understand that I have to find the shortest time from point A to point B basically, but I don't know how to write this into code.
Thank you so much!
Update: I have found an algorithm, but I don't know how to translate it into java
Update 2: I have started writing code, I'll post it below. It's not finished yet, I need an if statement after the ctr++; statement, but I am not sure what to put in it...And then I also need to return an int in this method
public int minTime(int start, int destination)
{
int ctr = 1;
int ran = routes.length;
int shortest = 0; //keeps track of the shortest time
int longest = 0; //keeps track of the longest time
int[][] otherArray = new int[routes.length][routes[ran].length]; //creates a new array to store the shortest time in
for (int i = 0; i < routes.length; i++)
{
for (int j = 0; j < routes[i].length; j++)
{
otherArray[ctr] = otherArray[i][j+ctr] + otherArray[j+ctr][j];
ctr++;
}
}
//return some integer here!
}
You will have to use dynamic programming.
Algorithm:
Starting at A, calculate all possible paths to B. Select the shortest.

divide bags of candies among three children evenly

I have n bags of candies such that no two bags have the same number of candies inside (i.e. it's a set A[] = {a0,a1,a2,...,ai,...,aj} where ai != aj).
I know how many candies is in each bag and the total number M of candies I have.
I need to divide the bags among three children so that the candies are distributed as fairly as possible (i.e. each child gets as close to M/3 as possible).
Needless to say, I may not tear into the bags to even out the counts -- then the question would be trivial.
Does anyone have any thoughts how to solve this -- preferably in Java?
EDIT:
the interviewer wanted me to use a 2-D array to solve the problem: the first kid gets x, the second kid y, the third gets the rest: S[x][y].
This after I tried following:
1] sort array n lg n
2] starting with largest remaining bag, give bag to kid with fewest candy.
Here is my solution for partitioning to two children (it is the correct answer). Maybe it will help with getting the 3-way partition.
int evenlyForTwo(int[] A, int M) {
boolean[] S = new boolean[M+1];
S[0]=true;//empty set
for(int i=0; i<A.length; i++)
for(int x=M; x >= A[i]; x--)
if(!S[x])
S[x]=S[x-A[i]];
int k = (int) M/2;
while(!S[k])
k--;
return k;//one kid gets k the other the rest.
}//
The problem you describe is known as the 3-Partition problem and is known to be NP-hard. The problem is discussed a bit on MathOverflow. You might find some of the pointers there of some value.
Here is a little solution, crude but gives correct results. And you can even change the number of children, bags, etc.
public class BagOfCandies {
static public void main(String...args) {
int repeat = 10;
int childCount = 3;
int bagsCount = childCount + (int) (Math.random() * 10);
for (int k=0; k<repeat; k++) {
int candyCount = 0, n=0;
int[] bags = new int[bagsCount];
for (int i=0; i<bags.length; i++) {
n += 1 + (int) (Math.random() * 2);
bags[i] = n;
candyCount += n;
}
shuffle(bags); // completely optional! It works regardless
boolean[][] dist = divideBags(bags, childCount);
System.out.println("Bags of candy : " + Arrays.toString(bags) + " = " + bags.length);
System.out.println("Total calculated candies is " + candyCount);
int childCandySum = 0;
for (int c=0; c<childCount; c++) {
int childCandies = countSumBags(bags, dist[c]);
System.out.println("Child " + (c+1) + " = " + childCandies + " --> " + Arrays.toString(dist[c]));
childCandySum += childCandies;
}
System.out.println("For a total of " + childCandySum + " candies");
System.out.println("----------------");
}
}
static private void shuffle(int[] bags) {
for (int i=0, len=bags.length; i<len; i++) {
int a = (int)Math.floor(Math.random()*len);
int b = (int)Math.floor(Math.random()*len);
int v = bags[a];
bags[a] = bags[b];
bags[b] = v;
}
}
static private boolean[][] divideBags(int[] bags, int childCount) {
int bagCount = bags.length;
boolean[][] dist = new boolean[childCount][bagCount];
for (int c=0; c<childCount; c++)
Arrays.fill(dist[c], false);
for (int i=0; i<bagCount; i+=childCount)
for (int j=i, c=0; c<childCount && j<bagCount; j++, c++)
dist[c][j] = true;
if (childCount == 1) return dist; // shortcut here
int sumDiff = 1;
int oldDiff = 0;
while (sumDiff != oldDiff) {
oldDiff = sumDiff;
sumDiff = 0;
// start comparing children in pair
for (int child1=0; child1<childCount-1; child1++) {
for (int child2=child1+1; child2<childCount; child2++) {
int count1 = countSumBags(bags, dist[child1]);
int count2 = countSumBags(bags, dist[child2]);
int diff = Math.abs(count1 - count2);
// a difference less than 2 is negligeable
if (diff > 1) {
// find some bags with can swap to even their difference
int c1=-1, c2=-1, cdiff;
boolean swap = false;
for (int i=0; i<bagCount-1; i++) {
for (int j=i; j<bagCount; j++) {
if (dist[child1][i] && dist[child2][j]) {
cdiff = Math.abs((count1 - bags[i] + bags[j]) - (count2 + bags[i] - bags[j]));
if (cdiff < diff) {
c1 = i; c2 = j;
diff = cdiff;
swap = true;
}
}
if (dist[child1][j] && dist[child2][i]) {
cdiff = Math.abs((count1 - bags[j] + bags[i]) - (count2 + bags[j] - bags[i]));
if (cdiff < diff) {
c1 = j; c2 = i;
diff = cdiff;
swap = true;
}
}
}
}
if (swap) {
//System.out.println("Swaping " + c1 + " with " + c2);
dist[child1][c1] = false; dist[child1][c2] = true;
dist[child2][c1] = true; dist[child2][c2] = false;
}
}
//System.out.println("Diff between " + child1 + "(" + countSumBags(bags, dist[child1]) + ") and " + child2 + "(" + countSumBags(bags, dist[child2]) + ") is " + diff);
sumDiff += diff;
}
}
//System.out.println("oldDiff="+oldDiff+", sumDiff="+sumDiff);
}
return dist;
}
static private int countSumBags(int[] bags, boolean[] t) {
int count = 0;
for (int i=0; i<t.length; i++) {
if (t[i]) {
count+=bags[i];
}
}
return count;
}
}
I don't know if this the result you were looking for, but it seems to be, from my understanding of the question.

Categories