Combination of N ordered element - java

I have a set of K element and i need to create a combination of N ordered element.
For examle if K=1 and i have {X1, emptyset} and n = 2 then i have an ordered pair i need to make this:
Example1:
({},{})
({X1},{}), ({},{X1})
({X1},{X1})
Note that I need to get the element in this order: first the element with 0 node as the sum of both pairs, second the element with 1, ecc
My idea is to make the set of parts of the intial set, adding an element at time, but I'm losing my mind. Any suggestions? I need to do this in java.
EDIT 1:
In other words I need to create an Hasse diagram:
http://en.wikipedia.org/wiki/Hasse_diagram
where every node is an element of the set of parts and the partial-ordering function is the inclusion of on all the subset like this:
Example2:
ni = (S1i,S2i) C nj = (S1j,S2j) only if S1i C S1j AND S21 C s2j
EDIT2: #RONALD:
If I have K=2 for a set S = {1, 2} and n =2, i need this output:
level0: ({}, {})
level1: ({1}, {}); ({2}, {}); ({}, {1}); ({}, {2})
level2: ({1,2}, {}); ({1}, {1}); ({1}, {2}); ({2}, {1}); ({2}, {2}); ({}, {1,2});
[..]
the order is important between levels, for example:
If at level1 i have
({1}, {}); ({2}, {}); ({}, {1}); ({}, {2})
OR
({}, {2}); ({}, {1}); ({2}, {}); ({1}, {});
is the same thing. But it's importat that at level 2 i have all superset of level2 and a superset is explained in example 2
EDIT3:
If my set is S= {x,y,z} and i have only one set per node the result (starting from the bottom) is this:
http://upload.wikimedia.org/wikipedia/commons/e/ea/Hasse_diagram_of_powerset_of_3.svg
If I have S={1,2} and two set per nod the result is this (thanks Ronald for the diagram) :
http://www.independit.de/Downloads/hasse.pdf
EDIT4:
Because is a super-exponential problem my idea is: I compute one level at time (in ordered mode!) and with some rule i prune a node and all his superset. Another stop rule may be to stop at a certain level. For this rule it is essential to calculate combinations directly in an orderly manner and not to calculate all and then reorder.
EDIT5:
The Marco13's code work fine, i have make some modify for:
Use function PowerSet because it's helpfull for make all combination of only K element of a set S (I only need to get the first tot element of powerset for do this).
Now the algorithm do all but i need to speed up it. Is there any way to parallelize the computation? such a way to use Map Reduce (Apache hadoop implementation) paradigm?
package utilis;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class HasseDiagramTest4
{
public static void main(String[] args)
{
int numberOfSetsPerNode = 3;
List<Integer> set = Arrays.asList(1, 2, 3, 4, 5,6);
List<Set<Integer>> powerSet = computePowerSet(set);
powerSet = KPowerSet(powerSet, 3);
List<List<Set<Integer>>> prunedNodes =
new ArrayList<List<Set<Integer>>>();
List<Set<Integer>> prunedNode = new ArrayList<Set<Integer>>();
HashSet<Integer> s = new HashSet<Integer>();
HashSet<Integer> s_vuoto = new HashSet<Integer>();
s.add(1);
s.add(2);
prunedNode.add(s);
prunedNode.add(s_vuoto);
prunedNode.add(s);
prunedNodes.add(prunedNode);
compute(ordina(powerSet), numberOfSetsPerNode, prunedNodes);
}
private static <T> HashMap<Integer, List<Set<T>>> ordina(List<Set<T>> powerSet) {
HashMap<Integer, List<Set<T>>> hs = new HashMap<Integer, List<Set<T>>>();
for(Set<T> l: powerSet)
{
List<Set<T>> lput = new ArrayList<Set<T>>();
if(hs.containsKey(l.size()))
{
lput = hs.get(l.size());
lput.add(l);
hs.put(l.size(), lput);
}
else
{
lput.add(l);
hs.put(l.size(), lput);
}
}
return hs;
}
private static <T> List<Set<T>> KPowerSet(List<Set<T>> powerSet, int k)
{
List<Set<T>> result = new ArrayList<Set<T>>();
for(Set<T>s:powerSet)
{
if(s.size() <= k)
{
result.add(s);
}
}
return result;
}
private static <T> List<Set<T>> computePowerSet(List<T> set)
{
List<Set<T>> result = new ArrayList<Set<T>>();
int numElements = 1 << set.size();
for (int j=0; j<numElements; j++)
{
Set<T> element = new HashSet<T>();
for (int i = 0; i < set.size(); i++)
{
long b = 1 << i;
if ((j & b) != 0)
{
element.add(set.get(i));
}
}
result.add(element);
}
return result;
}
private static List<Integer> createList(int numberOfElements)
{
List<Integer> list = new ArrayList<Integer>();
for (int i=0; i<numberOfElements; i++)
{
list.add(i+1);
}
return list;
}
private static <T> void compute(
HashMap<Integer, List<Set<T>>> powerSet, int numberOfSetsPerNode,
List<List<Set<T>>> prunedNodes)
{
Set<List<Set<T>>> level0 = createLevel0(numberOfSetsPerNode);
System.out.println("Level 0:");
print(level0);
Set<List<Set<T>>> currentLevel = level0;
int level = 0;
while (true)
{
Set<List<Set<T>>> nextLevel =
createNextLevel(currentLevel, powerSet, prunedNodes);
if (nextLevel.size() == 0)
{
break;
}
System.out.println("Next level: "+nextLevel.size()+" nodes");
print(nextLevel);
currentLevel = nextLevel;
level++;
}
}
private static <T> Set<List<Set<T>>> createLevel0(int numberOfSetsPerNode)
{
Set<List<Set<T>>> level0 =
new LinkedHashSet<List<Set<T>>>();
List<Set<T>> level0element = new ArrayList<Set<T>>();
for (int i=0; i<numberOfSetsPerNode; i++)
{
level0element.add(new LinkedHashSet<T>());
}
level0.add(level0element);
return level0;
}
private static <T> List<Set<T>> getNext(Set<T> current, HashMap<Integer, List<Set<T>>> powerSet)
{
ArrayList<Set<T>> ritorno = new ArrayList<Set<T>>();
int level = current.size();
List<Set<T>> listnext = powerSet.get(level+1);
if(listnext != null)
{
for(Set<T> next: listnext)
{
if(next.containsAll(current))
{
ritorno.add(next);
}
}
}
return ritorno;
}
private static <T> Set<List<Set<T>>> createNextLevel(
Set<List<Set<T>>> currentLevel, HashMap<Integer, List<Set<T>>> powerSet,
List<List<Set<T>>> prunedNodes)
{
Set<List<Set<T>>> nextLevel = new LinkedHashSet<List<Set<T>>>();
//Per ogni nodo del livello corrente
for (List<Set<T>> currentLevelElement : currentLevel)
{
//Per ogni insieme del nodo preso in considerazione
for (int i=0; i<currentLevelElement.size(); i++)
{
List<Set<T>> listOfnext = getNext (currentLevelElement.get(i), powerSet);
for (Set<T> element : listOfnext)
{
List<Set<T>> nextLevelElement = copy(currentLevelElement);
Set<T> next = element;
nextLevelElement.remove(i);
nextLevelElement.add(i, next);
boolean pruned = false;
for (List<Set<T>> prunedNode : prunedNodes)
{
if (isSuccessor(prunedNode, nextLevelElement))
{
pruned = true;
}
}
if (!pruned)
{
nextLevel.add(nextLevelElement);
}
else
{
System.out.println("Pruned "+nextLevelElement+ " due to "+prunedNodes);
}
}
}
}
return nextLevel;
}
private static <T> boolean isSuccessor(
List<Set<T>> list, List<Set<T>> successor)
{
for (int i=0; i<list.size(); i++)
{
Set<T> set = list.get(i);
Set<T> successorSet = successor.get(i);
//System.out.println("Successor:" + successorSet + "pruned:" + set);
if (!successorSet.containsAll(set))
{
return false;
}
}
return true;
}
private static <T> List<Set<T>> copy(List<Set<T>> list)
{
List<Set<T>> result = new ArrayList<Set<T>>();
for (Set<T> element : list)
{
result.add(new LinkedHashSet<T>(element));
}
return result;
}
private static <T> void print(
Iterable<? extends Collection<? extends Collection<T>>> sequence)
{
for (Collection<? extends Collection<T>> collections : sequence)
{
System.out.println(" "+collections);
}
}
}

After 4 EDITs and a lot of discussion, it's slowly becoming more clear what the goal of this application is. Indeed, one would have to think about an appropriate formalization, but it finally does not seem to be so difficult.
In contrast to my first answer ( https://stackoverflow.com/a/22092523 ) this new one iteratively computes the next level from the previous level (and the core of this, createNextLevel, is just 10 lines of code).
In the compute method, the pruning that was asked for in "EDIT4" could be integrated into the while loop.
EDIT: Still more requests in the comments. Integrated them. But this is becoming ridiculous. Um den Rest kannst du dich selbst kümmern.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class HasseDiagramTest2
{
public static void main(String[] args)
{
int numberOfElements = 2;
int numberOfSetsPerNode = 2;
List<Integer> list = createList(numberOfElements);
List<List<Set<Integer>>> prunedNodes =
new ArrayList<List<Set<Integer>>>();
List<Set<Integer>> prunedNode = new ArrayList<Set<Integer>>();
prunedNode.add(Collections.singleton(1));
prunedNode.add(Collections.singleton(1));
prunedNodes.add(prunedNode);
compute(list, numberOfSetsPerNode, prunedNodes);
}
private static List<Integer> createList(int numberOfElements)
{
List<Integer> list = new ArrayList<Integer>();
for (int i=0; i<numberOfElements; i++)
{
list.add(i+1);
}
return list;
}
private static <T> void compute(
List<T> elements, int numberOfSetsPerNode,
List<List<Set<T>>> prunedNodes)
{
Set<List<Set<T>>> level0 = createLevel0(numberOfSetsPerNode);
System.out.println("Level 0:");
print(level0);
Set<List<Set<T>>> currentLevel = level0;
int level = 0;
while (true)
{
Set<List<Set<T>>> nextLevel =
createNextLevel(currentLevel, elements, prunedNodes);
if (nextLevel.size() == 0)
{
break;
}
System.out.println("Next level: "+nextLevel.size()+" nodes");
print(nextLevel);
currentLevel = nextLevel;
level++;
}
}
private static <T> Set<List<Set<T>>> createLevel0(int numberOfSetsPerNode)
{
Set<List<Set<T>>> level0 =
new LinkedHashSet<List<Set<T>>>();
List<Set<T>> level0element = new ArrayList<Set<T>>();
for (int i=0; i<numberOfSetsPerNode; i++)
{
level0element.add(new LinkedHashSet<T>());
}
level0.add(level0element);
return level0;
}
private static <T> Set<List<Set<T>>> createNextLevel(
Set<List<Set<T>>> currentLevel, List<T> elements,
List<List<Set<T>>> prunedNodes)
{
Set<List<Set<T>>> nextLevel = new LinkedHashSet<List<Set<T>>>();
for (List<Set<T>> currentLevelElement : currentLevel)
{
for (int i=0; i<currentLevelElement.size(); i++)
{
for (T element : elements)
{
List<Set<T>> nextLevelElement = copy(currentLevelElement);
Set<T> next = nextLevelElement.get(i);
boolean changed = next.add(element);
if (!changed)
{
continue;
}
boolean pruned = false;
for (List<Set<T>> prunedNode : prunedNodes)
{
if (isSuccessor(prunedNode, nextLevelElement))
{
pruned = true;
}
}
if (!pruned)
{
nextLevel.add(nextLevelElement);
}
else
{
// System.out.println(
// "Pruned "+nextLevelElement+
// " due to "+prunedNodes);
}
}
}
}
return nextLevel;
}
private static <T> boolean isSuccessor(
List<Set<T>> list, List<Set<T>> successor)
{
for (int i=0; i<list.size(); i++)
{
Set<T> set = list.get(i);
Set<T> successorSet = successor.get(i);
if (!successorSet.containsAll(set))
{
return false;
}
}
return true;
}
private static <T> List<Set<T>> copy(List<Set<T>> list)
{
List<Set<T>> result = new ArrayList<Set<T>>();
for (Set<T> element : list)
{
result.add(new LinkedHashSet<T>(element));
}
return result;
}
private static <T> void print(
Iterable<? extends Collection<? extends Collection<T>>> sequence)
{
for (Collection<? extends Collection<T>> collections : sequence)
{
System.out.println(" "+collections);
}
}
}

As mentioned in the comments, I'm rather sure that the formalization of what actually should be done is either unclear or plainly wrong. The criterion for comparing the "nodes" does not match the examples. However, once the sorting criterion (in form of a Comparator) has been specified, this should be rather easy to implement.
Here, the criterion for comparing two "nodes" is the sum of the sizes of all sets in the node, which matches the example that was given (although it intuitively does not make sense, because it does not correspond to any real subset relationship....)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class HasseDiagramTest
{
public static void main(String[] args)
{
List<Integer> set = Arrays.asList(1, 2);
List<List<Integer>> powerSet = computePowerSet(set);
List<List<List<Integer>>> combinations =
computeCombinations(powerSet, 2);
Comparator<List<List<Integer>>> comparator = createComparator();
Collections.sort(combinations, comparator);
List<List<List<List<Integer>>>> levels = createLevels(combinations);
for (List<List<List<Integer>>> level : levels)
{
System.out.println(level);
}
}
private static <T> List<List<List<List<T>>>> createLevels(
List<List<List<T>>> sortedCombinations)
{
List<List<List<List<T>>>> levels = new ArrayList<List<List<List<T>>>>();
int previousTotalSize = -1;
List<List<List<T>>> currentLevel = null;
for (int i=0; i<sortedCombinations.size(); i++)
{
List<List<T>> combination = sortedCombinations.get(i);
int totalSize = totalSize(combination);
if (previousTotalSize != totalSize)
{
previousTotalSize = totalSize;
currentLevel = new ArrayList<List<List<T>>>();
levels.add(currentLevel);
}
currentLevel.add(combination);
}
return levels;
}
private static <T> Comparator<List<List<T>>> createComparator()
{
return new Comparator<List<List<T>>>()
{
#Override
public int compare(List<List<T>> list0, List<List<T>> list1)
{
return Integer.compare(totalSize(list0), totalSize(list1));
}
};
}
private static <T> int totalSize(List<List<T>> lists)
{
int totalSize = 0;
for (List<T> list : lists)
{
totalSize += list.size();
}
return totalSize;
}
private static <T> List<List<T>> computePowerSet(List<T> set)
{
List<List<T>> result = new ArrayList<List<T>>();
int numElements = 1 << set.size();
for (int j=0; j<numElements; j++)
{
List<T> element = new ArrayList<T>();
for (int i = 0; i < set.size(); i++)
{
long b = 1 << i;
if ((j & b) != 0)
{
element.add(set.get(i));
}
}
result.add(element);
}
return result;
}
private static <T> List<List<T>> computeCombinations(List<T> list, int sampleSize)
{
int numElements = (int) Math.pow(list.size(), sampleSize);
int chosen[] = new int[sampleSize];
List<List<T>> result = new ArrayList<List<T>>();
for (int current = 0; current < numElements; current++)
{
List<T> element = new ArrayList<T>(sampleSize);
for (int i = 0; i < sampleSize; i++)
{
element.add(list.get(chosen[i]));
}
result.add(element);
increase(chosen, list.size());
}
return result;
}
private static void increase(int chosen[], int inputSize)
{
int index = chosen.length - 1;
while (index >= 0)
{
if (chosen[index] < inputSize - 1)
{
chosen[index]++;
return;
}
chosen[index] = 0;
index--;
}
}
}

So if you have a basic set S = {1, 2}, then K = 2 and the set of subsets of S is {{}, {1}, {2}, {1,2}}. Assume n is still 2. Then your output will be something like
({}, {})
({1}, {}); ({2}, {}); ({}, {1}); ({}, {2})
({1,2}, {}); ({}, {1,2})
({1}, {1}); ({1}, {2}); ({2}, {1}); ({2}, {2})
({1}, {1,2}); ({1,2}, {1}); ({2}, {1,2}); ({1,2}, {2})
({1,2}, {1,2})
Correct? The ordering with the output is a bit difficult because the result isn't fully ordered. But it still boils down to counting. Not, as I initially thought, (K+1)-ary but more (2^K)-ary.
In order to determine if one set is a subset of another, using primes might be an idea.
You assign a prime number to each element of your original set. In my example, that would be 2 and 3. The set of subsets can be build by generating all products of the prime numbers. In my example that would be {1 /* empty set */, 2, 3, 6}.
If you have two sets, represented by your product it is easy to test the inclusion:
if (a % b == 0) then b is a subset of a
It's just a bunch of ideas, but they might help you finding a solution. Of course, the prime trick only works for a relatively small number of elements in your original set, but as soon as K and N grow, you'll get problems anyway. (The number of elements in your output will be (2^K)^N = 2^(NK). If K == N == 5, you'll have 2^(5 * 5) = 2^25, about 32 million output elements. And here the prime thought still works).
Edit: Well I wrote a small Java Program to show my ideas.
save it to Hasse.java
compile it: javac Hasse.java
run it: java Hasse > hasse.dot
run dot: dot -Tpdf -ohasse.pdf hasse.dot
view it: acroread hasse.pdf
Source Code:
import java.lang.*;
import java.util.*;
public class Hasse {
private static int K[] = { 1, 2, 3 };
private static int N = 2;
private static int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
//
// PK[0][] is the array of "subsets"
// PK[1][] is the array of number of elements of K participating in the subset
//
private static int PK[][];
// some constants; the initialization is clear enough
private static final long twoNK = pow(2, N * K.length);
private static final int twoK = (int) pow(2, K.length);
private static final int NK = N * K.length;
private static final long NKf = fac(NK);
//
// this power function isn't suitable for large powers
// but in the range we are working, it's OK
//
public static long pow(int b, int p)
{
long result = 1;
for (int i = 0; i < p; ++i)
result *= b;
return result;
}
// fac calculates n! (needed for the a over b calculation)
public static long fac(int n)
{
long result = 1;
for (int i = n; i > 0; --i) result *= i;
return result;
}
//
// constructPK builds the set of subsets of K
// a subset is represented by a product of primes
// each element k_i of K has an associated prime p_i
// since the prime factorization of a number is unique,
// the product can be translated into a subset and vice versa
//
public static void constructPK()
{
int i, cnt;
int numElms = twoK;
PK = new int[2][numElms];
for (i = 0; i < numElms; ++i) {
int j = i;
cnt = 0;
PK[0][i] = 1;
PK[1][i] = 0;
while (j > 0) {
if (j % 2 == 1) {
PK[0][i] *= prime[cnt];
PK[1][i]++;
}
cnt++;
j /= 2;
}
}
}
// we have a k-ary number (that is: binary if k == 2, octal if k == 8
// and so on
// the addOne() function calculates the next number based on the input
public static void addOne(int kAry[])
{
int i = 0;
kAry[i] += 1;
while (kAry[i] >= twoK) {
kAry[i] = 0;
++i;
kAry[i] += 1;
}
}
// the addN() function is similar to the addOne() function
// with the difference that it add n to the input, not just 1
public static void addN(int kAry[], int n)
{
int i = 0;
kAry[i] += n;
for (i = 0; i < N - 1; ++i) {
while (kAry[i] >= twoK) {
kAry[i] -= twoK;
kAry[i+1] += 1;
}
}
}
// from the k-ary number, which represents a node in the graph,
// the "level" is calculated.
public static int getLevel(int kAry[])
{
int level = 0;
for (int i = 0; i < N; ++i) {
level += PK[1][kAry[i]];
}
return level;
}
// output function for a node
public static String renderNode(int kAry[])
{
StringBuffer sb = new StringBuffer();
String sep = "";
sb.append("(");
for (int i = 0; i < N; ++i) {
String setSep = "";
int p = PK[0][kAry[i]];
sb.append(sep);
sb.append("{");
for (int j = 0; j < K.length; ++j) {
if (p % prime[j] == 0) {
sb.append(setSep + K[j]);
setSep = ", ";
}
}
sb.append("}");
sep = ", ";
}
sb.append(")");
return sb.toString();
}
// This function calculates the numerical representation
// of a node, addressed by its level and position within the level,
// in the k-ary number system
// if there's a more elegant way of finding the node, it would
// largely speed up the calculation, since this function is needed
// for calculating the edges
public static int[] getKAry(int level, int node)
{
int kAry[] = new int[N];
int nodesSoFar = 0;
for (int i = 0; i < N; ++i) kAry[i] = 0;
for (int cnt = 0; cnt < twoNK; ++cnt) {
if (getLevel(kAry) == level) {
if (nodesSoFar == node) {
return kAry;
} else
nodesSoFar++;
}
if (cnt + 1 < twoNK)
addOne(kAry);
}
return null;
}
// this function converts the decimal nodeNumber to
// its k-ary representation
public static int[] getKAry(int nodeNumber)
{
int kAry[] = new int[N];
for (int i = 0; i < N; ++i) kAry[i] = 0;
addN(kAry, nodeNumber);
return kAry;
}
public static String getLabel(int level, int node)
{
int kAry[] = getKAry(level, node);
return (kAry == null ? "Oops!" : renderNode(kAry));
}
public static void printPK()
{
System.out.println("# Number of elements: " + PK[0].length);
for (int i = 0; i < PK[0].length; ++i) {
System.out.println("# PK[0][" + i + "] = " + PK[0][i] + ",\tPK[1][" + i + "] = " + PK[1][i]);
}
}
public static void printPreamble()
{
System.out.println("digraph G {");
System.out.println("ranksep = 3");
System.out.println();
}
public static void printEnd()
{
System.out.println("}");
}
public static void printNodes()
{
int numNodes;
for (int i = 0; i <= NK; ++i) {
int level = i + 1;
numNodes = (int) (NKf / (fac(i) * fac(NK - i)));
for (int j = 0; j < numNodes; ++j) {
System.out.println("level_" + level + "_" + (j+1) + " [shape=box,label=\"" + getLabel(i, j) + "\"];");
}
System.out.println();
}
System.out.println();
}
// having two vectors of "sets", this function determines
// if each set in the ss (small set) vector is a subset of
// the corresponding set in the ls (large set) vector
public static boolean isSubset(int ss[], int ls[])
{
for (int i = 0; i < N; ++i)
if (PK[0][ls[i]] % PK[0][ss[i]] != 0) return false;
return true;
}
// this function finds and prints the edges
// it is called about twoNK times (once for each node)
// therefore performance optimizations have to be done here
public static void printEdges(int level, int node, int nodeNumber)
{
int kAry[] = getKAry(node);
int nlAry[];
int numNodes = (int) (NKf / (fac(level + 1) * fac(NK - level - 1)));
String myNode = "level_" + (level + 1) + "_" + (node + 1);
for (int i = 0; i < numNodes; ++i) {
nlAry = getKAry(level + 1, i);
if (nlAry == null) System.exit(1);
if (isSubset(kAry, nlAry)) {
System.out.println(myNode + " -> level_" + (level + 2) + "_" + (i + 1));
}
}
}
// this function renders the dot file
// first some initial text (preamble),
// then the nodes and the edges
// and finally the closing brace
public static void renderDot()
{
int numNodes;
int nodeNumber = 0;
printPreamble();
printNodes();
for (int level = 0; level < NK; ++level) {
numNodes = (int) (NKf / (fac(level) * fac(NK - level)));
for (int node = 0; node < numNodes; ++node) {
// find the edges to the nodes on the next level
printEdges(level, node, nodeNumber);
++nodeNumber;
}
System.out.println();
}
printEnd();
}
public static void main (String argv[])
{
constructPK();
renderDot();
}
}

Related

Compare Lists in ArrayList

I have a text file containing the following strings (which are versions of a software):
1_10_2_0_154
3_10_5_2_10
2_10_4_1
3_10_5_1_37
I'm trying to find the most recent version, in this case 3_10_5_2_10 is the version that I'm trying to display using java.
For the moment, here is my code:
BufferedReader br;
String version;
ArrayList<List<Integer>> array = new ArrayList<List<Integer>>();
List<Integer> liste = new ArrayList<Integer>();
try{
br = new BufferedReader(new FileReader(new File(FILEPATH)));
while((version= br.readLine()) != null)
{
liste = Arrays.asList(version.split("_")).stream().
map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
array.add(liste);
}
for(int i = 0; i < array.size(); i++)
{
for (List l: array)
{
Object z = l.get(i);
List<Object> listes = new ArrayList<Object>();
listes.add(z);
System.out.println(listes);
}
}
br.close();
System.out.println(array);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
I made a loop to save strings to ArrayList> like:
[[1,10,2,0,154] , [3,10,5,2,10], [2,10,4,1], [3,10,5,1,37]]
I want to get the elements of each list and compare them to find the most biggest one (most recent one) but I don't know to do that..
I sugguest you a object approach, define a class named Version with compareTo method, then using method sort on Collections class you can simply sort your versions.
Advantages
Clean and Clear code
Data validation
Main:
public class Main {
public static void main(String[] args){
List<Version> versions = Arrays.asList(
Version.create("1_10_2_0_154"),
Version.create("3_10_5_2_10"),
Version.create("2_10_4_1_49"),
Version.create("3_10_5_1_37"));
versions.sort(Version::compareTo);
System.out.println(versions.get(0).toString());
}
}
Version:
public class Version implements Comparable<Version> {
private final int major;
private final int minor;
private final int bug;
private final int release;
private final int build;
public Version(int major, int minor, int bug, int release, int build) {
this.major = major;
this.minor = minor;
this.bug = bug;
this.release = release;
this.build = build;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getBug() {
return bug;
}
public int getRelease() {
return release;
}
public int getBuild() {
return build;
}
#Override
public String toString() {
return "Version{" +
"major=" + major +
", minor=" + minor +
", bug=" + bug +
", release=" + release +
", build=" + build +
'}';
}
public static Version create(String value){
String[] splitRes = value.split("_");
List<Integer> intValues = new ArrayList<>();
for(String v : splitRes){
intValues.add(Integer.parseInt(v));
}
return create(intValues);
}
public static Version create(List<Integer> values){
if(Objects.requireNonNull(values).size() < 5)
throw new IllegalArgumentException();
return new Version(
values.get(0),
values.get(1),
values.get(2),
values.get(3),
values.get(4)
);
}
#Override
public int compareTo(Version that) {
if (this.major > that.major) {
return -1;
} else if (this.major < that.major) {
return 1;
}
if (this.minor > that.minor) {
return -1;
} else if (this.minor < that.minor) {
return 1;
}
if (this.bug > that.bug) {
return -1;
} else if (this.bug < that.bug) {
return 1;
}
if (this.release > that.release) {
return -1;
} else if (this.release < that.release) {
return 1;
}
if (this.build > that.build) {
return -1;
} else if (this.build < that.build) {
return 1;
}
return 0;
}
}
UPDATE 1
As suggested by #Henrik i updated the list sorting with a Java 8 approach.
UPDATE 2
I reversed the compareTo method so now you can simply do plain sort calling sort method on list and passing method reference Version::compareTo
UPDATE 3
A more dynamic solution for Version class:
public class Version implements Comparable<Version> {
private final List<Integer> values;
public Version(List<Integer> values) {
this.values = values;
}
public List<Integer> getValues() {
return values;
}
#Override
public String toString() {
return String.join("_", values
.stream()
.map(Object::toString)
.collect(Collectors.toList()));
}
#Override
public int compareTo(Version that) {
List<Integer> thatValues = that.getValues();
for(int index = 0; index < values.size(); index++){
Integer value = values.get(index);
Integer thatValue = thatValues.get(index);
if (value > thatValue) {
return -1;
} else if (value < thatValue) {
return 1;
}
}
return 0;
}
public static Version create(String value){
String[] splitRes = value.split("_");
List<Integer> intValues = new ArrayList<>();
for(String v : splitRes){
intValues.add(Integer.parseInt(v));
}
return new Version(intValues);
}
}
You can write a Comparator to compare two Lists
Comparator<List<Integer>> comparator = (list1, list2) -> {
Iterator<Integer> iteratorA = list1.iterator();
Iterator<Integer> iteratorB = list2.iterator();
//It iterates through each list looking for an int that is not equal to determine which one precedes the other
while (iteratorA.hasNext() && iteratorB.hasNext()) {
int elementA = iteratorA.next();
int elementB = iteratorB.next();
if (elementA > elementB) {
return 1;
} else if (elementA < elementB) {
return -1;
}
}
//All elements seen so far are equal. Use the list size to decide
return iteratorA.hasNext() ? 1 : iteratorB.hasNext() ? -1 : 0;
};
You can sort it as
Collections.sort(list, comparator);
EDIT: You can refer to David Geirola's answer to convert the version string as a POJO and move the comparator logic inside that. But that is highly tied/coupled to the input string format. My solution works for any List<List<Integer>>.
A simple object oriented approach would be to create object, representing version number, let's call it VersionNumber, which would have a constructor of a factory method that does the parsing of the string. This VersionNumber class should implement interface Comparable and implement method compareTo.
Here is a hint for using Comparable Why should a Java class implement comparable?
Then you can easily write an algorithm to find the max version or google some library that would do it for you.
It is not optimized but should work. You can use both of comparators.
static List<String> versions = Arrays.asList(
"1_10_2_0_154",
"3_10_5_2_10",
"2_10_4_1_49",
"3_10_5_1_37");
static Comparator<List<Integer>> c = (o1,o2) -> {
int length = o1.size()>o2.size()?o2.size():o1.size();
for (int i = 0; i < length; i++) {
int i1 = o1.get(i);
int i2 = o2.get(i);
if (i1 != i2)
return i1 - i2;
}
return 0;
};
static Comparator<List<Integer>> c2 = (o1,o2) -> {
Iterator<Integer> i1=o1.iterator();
Iterator<Integer> i2=o2.iterator();
while (i1.hasNext() && i2.hasNext()){
int i = i1.next()-i2.next();
if (i!=0) return i;
}
return 0;
};
static Optional<List<Integer>> getTheMostRecentVersion(List<String> versions) {
return versions.stream().
map(s -> Arrays.stream(s.split("_")).
map(Integer::parseInt).
collect(Collectors.toList())).max(c2);
}
I think that this text file could be very big and it is better to compare each line on the fly (instead of store all line into collection to sort it after):
public static String getMostRecentVersion(BufferedReader in) throws IOException {
final Comparator<String[]> version = (s1, s2) -> {
int res = 0;
for (int i = 0; i < 5 && res == 0; i++)
res = Integer.compare(Integer.parseInt(s1[i]), Integer.parseInt(s2[i]));
return res;
};
String str;
String resStr = null;
String[] resPparts = null;
while ((str = in.readLine()) != null) {
String[] parts = str.split("_");
if (resStr == null || version.compare(parts, resPparts) > 0) {
resStr = str;
resPparts = parts;
}
}
return resStr;
}
A general ListComparator should help.
static class ListComparator<T extends Comparable<T>> implements Comparator<List<T>> {
#Override
public int compare(List<T> o1, List<T> o2) {
for (int i = 0; i < Math.max(o1.size(), o2.size()); i++) {
int diff =
// Off the end of both - same.
i >= o1.size() && i >= o2.size() ? 0
// Off the end of 1 - the other is greater.
: i >= o1.size() ? -1
: i >= o2.size() ? 1
// Normal diff.
: o1.get(i).compareTo(o2.get(i));
if (diff != 0) {
return diff;
}
}
return 0;
}
}
private static final Comparator<List<Integer>> BY_VERSION = new ListComparator<Integer>().reversed();
public void test(String[] args) {
String[] tests = {
"1_10_2_0_154",
"3_10_5_2_10",
"2_10_4_1_49",
"3_10_5_1_37",
"3_10_5_1_37_0"
};
System.out.println("Before: " + Arrays.toString(tests));
System.out.println("After: " + Arrays.stream(tests)
// Split into parts.
.map(s -> s.split("_"))
// Map String[] to List<Integer>
.map(a -> Arrays.stream(a).map(s -> Integer.valueOf(s)).collect(Collectors.toList()))
// Sort it.
.sorted(BY_VERSION)
// Back to a new list.
.collect(Collectors.toList()));
}
slap your arrays together into a number then just do number comparison.
class Scratch
{
public static void main(String[] args)
{
List<List<Integer>> arr = new ArrayList<>();
arr.add(fromArray(new Integer[]{1,10,2,0,154}));
arr.add(fromArray(new Integer[]{3,10,5,2,10}));
arr.add(fromArray(new Integer[]{2,10,4,1,49}));
arr.add(fromArray(new Integer[]{3,10,5,1,37}));
Integer[] maxLengths = {0,0,0,0,0};
for (List<Integer> v : arr)
{
for(int idx = 0; idx < v.size(); idx++)
{
Integer n = v.get(idx);
int curMaxLen = maxLengths[idx];
maxLengths[idx] = Math.max(n.toString().length(), curMaxLen);
}
}
Long largest = arr.stream().map(v -> {
StringBuilder result = new StringBuilder();
for(int idx = 0; idx < v.size(); idx++)
{
Integer n = v.get(idx);
int maxLen = maxLengths[idx];
result.append(String.format("%-" + maxLen + 's', n).replace(' ', '0'));
}
return result.toString();
}).map(Long::valueOf).max(Comparator.naturalOrder()).get();
System.out.println(largest);
}
public static List<Integer> fromArray(Integer[] array)
{
List<Integer> list = new ArrayList<>();
Collections.addAll(list, array);
return list;
}
}

n-ary Cartesian product inRxJava

Now I hold an Observable<Observable<Integer>, how can I transfer it into Observable<int[]> that contains the n-ary Cartesian product?
For example:
Observable<Observable<Integer> ob = Observable.just(
Observable.just(0,1),
Observable.just(2,3),
Observable.just(4,5)
);
ob...... -> (0,2,4), (0,3,4), (0,2,5), (0,3,5), (1,2,4), (1,3,4), (1,2,5), (1,3,5)
First of all, you need a fixed number of input Observables. Second, there is no need for blocking but there is likely the need for caching because the 2nd, 3rd etc Observables need to be consumed multiple times.
import java.util.*;
import io.reactivex.Observable;
public class Cartesian {
static Observable<int[]> cartesian(Observable<Observable<Integer>> sources) {
return sources.toList().flatMapObservable(list -> cartesian(list));
}
static Observable<int[]> cartesian(List<Observable<Integer>> sources) {
if (sources.size() == 0) {
return Observable.<int[]>empty();
}
Observable<int[]> main = sources.get(0).map(v -> new int[] { v });
for (int i = 1; i < sources.size(); i++) {
int j = i;
Observable<Integer> o = sources.get(i).cache();
main = main.flatMap(v -> {
return o.map(w -> {
int[] arr = Arrays.copyOf(v, j + 1);
arr[j] = w;
return arr;
});
});
}
return main;
}
public static void main(String[] args) {
cartesian(Observable.just(
Observable.just(0, 1),
Observable.just(2, 3),
Observable.just(4, 5)
))
.subscribe(v -> System.out.println(Arrays.toString(v)));
}
}
Creating Cartesian product in an asynchronous way is hard or in some sense is impossible. And if blocking is OK, you can do something like this
public class Main
{
static class ProductIterator<T> implements Iterator<T[]>
{
private final List<List<T>> componentsList;
private final Class<T> componentClass;
private final int[] indices;
private boolean hasNext;
public ProductIterator(List<List<T>> componentsList, Class<T> componentClass)
{
this.componentsList = componentsList;
this.componentClass = componentClass;
this.indices = new int[componentsList.size()];
this.hasNext = this.indices[componentsList.size() - 1] < componentsList.get(componentsList.size() - 1).size();
}
#Override
public boolean hasNext()
{
return hasNext;
}
#Override
public T[] next()
{
T[] res = (T[]) Array.newInstance(componentClass, componentsList.size());
for (int i = 0; i < componentsList.size(); i++)
{
res[i] = componentsList.get(i).get(indices[i]);
}
// move next
indices[0]++;
for (int i = 0; i < componentsList.size() - 1; i++)
{
if (indices[i] == componentsList.get(i).size())
{
indices[i] = 0;
indices[i + 1]++;
}
}
hasNext = indices[componentsList.size() - 1] < componentsList.get(componentsList.size() - 1).size();
return res;
}
}
public static <T> Observable<T[]> product(Observable<Observable<T>> components, Class<T> componentClass)
{
return Observable.fromIterable(new Iterable<T[]>()
{
#Override
public Iterator<T[]> iterator()
{
// postpone blocking up until iterator is requested
// and by this point we can't postpone anymore
Single<List<List<T>>> componentsList = components.map(o -> o.toList().blockingGet()).toList();
return new ProductIterator<T>(componentsList.blockingGet(), componentClass);
}
});
}
public static void main(String[] args) throws Exception
{
Observable<Observable<Integer>> ob = Observable.just(
Observable.just(0, 1),
Observable.just(2, 3),
Observable.just(4, 5)
);
Observable<Integer[]> product = product(ob, Integer.class);
product.forEach(a -> System.out.println(Arrays.toString(a)));
}
}
It is possible to improve this code to avoid blocking but you still will have to cache all results from all Observables and code will be much more complicated. Most probably is blocking is not acceptable for you, trying to get Cartesian product is bad idea anyway.
Well, I can resolve it myself. But is there any more elegant way?
(The toArray method convert an Observable<T> to T[])
Observable<int[]> toObservableArray(Observable<Observable<Integer>> obs) {
List<int[]> list = obs.map(ob -> toArray(ob)).toList().toBlocking().last();
return Observable.create(new SyncOnSubscribe<int[], int[]>() {
#Override
protected int[] generateState() {
int[] array = new int[list.size()];
Arrays.fill(array, 0);
return array;
}
#Override
protected int[] next(int[] state, Observer<? super int[]> observer) {
int[] next = new int[list.size()];
for (int i = 0; i < next.length; i++) {
next[i] = list.get(i)[state[i]];
}
observer.onNext(next);
state[state.length - 1]++;
for (int i = state.length - 1; i >= 0; i--) {
int delta = list.get(i).length - state[i];
if (delta > 0) {
break;
} else if (delta == 0) {
state[i] = 0;
if (i == 0) {
observer.onCompleted();
break;
}
state[i - 1]++;
}
}
return state;
}
});
}

Sort objects highest-lowest in Java with ArrayList?

Write a method to return the Toy that occurs in the list most frequent and another method to sort the toys by count.
This is my code
import java.util.ArrayList;
public class ToyStore {
private ArrayList<Toy> toyList;
public ToyStore() {
}
public void loadToys(String toys) {
toyList = new ArrayList<Toy>();
for (String item : toys.split(" ")) {
Toy t = getThatToy(item);
if (t == null) {
toyList.add(new Toy(item));
} else {
t.setCount(t.getCount() + 1);
}
}
}
public Toy getThatToy(String nm) {
for (Toy item : toyList) {
if (item.getName().equals(nm)) {
return item;
}
}
return null;
}
public String getMostFrequentToy() {
int position = 0;
int maximum = Integer.MIN_VALUE;
for (int i = toyList.size() - 1; i >= 0; i--) {
if (toyList.get(i).getCount() > maximum)
maximum = toyList.get(i).getCount();
position = i;
}
return toyList.get(position).getName();
}
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
int count = 0;
int size = toyList.size();
for (int i = size; i > 0; i--) {
t.add(new Toy(getMostFrequentToy()));
t.get(count).setCount(getThatToy(getMostFrequentToy()).getCount());
toyList.remove(getThatToy(getMostFrequentToy()));
count++;
}
toyList = t;
}
public String toString() {
return toyList + "" + "\n" + "max == " + getMostFrequentToy();
}
}
Here is the method I care about
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
int count = 0;
int size = toyList.size();
for (int i = size; i > 0; i--) {
t.add(new Toy(getMostFrequentToy()));
t.get(count).setCount(getThatToy(getMostFrequentToy()).getCount());
toyList.remove(getThatToy(getMostFrequentToy()));
count++;
}
toyList = t;
}
Here is my output
[sorry 4, bat 1, train 2, teddy 2, ball 2]
Here is what I want
[sorry 4, train 2, teddy 2, ball 2, bat 1];
What is wrong in my code? How do I do it?
The problem is in your getMostFrequentToy() method:
Replace
if (toyList.get(i).getCount() > maximum)
maximum = toyList.get(i).getCount();
position = i;
with
if (toyList.get(i).getCount() > maximum) {
maximum = toyList.get(i).getCount();
position = i;
}
because you want to get the position that corresponds to that maximum.
You have some in-efficiencies in your code. Every single time you call getMostFrequentToy(), you are iterating over the whole list, which may be fine as you are constantly removing objects, but you really don't need to make new Toy objects for those that already exist in the list.
So, this is "better", but still not sure you need to getThatToy when you should already know which one is the most frequent.
String frequent;
for (int i = size; i > 0; i--) {
frequent = getMostFrequentToy();
t.add(new Toy(frequent));
t.get(count).setCount(getThatToy(frequent).getCount());
toyList.remove(getThatToy(frequent));
count++;
}
Anyways, I think the instructions asked you to return the Toy object, not its name.
It's quite simple, just keep track of the max count.
public Toy getMostFrequentToy() {
Toy mostFrequent = null;
int maximum = Integer.MIN_VALUE;
for (Toy t : toyList) {
if (t.getCount() > maximum)
mostFrequent = t;
}
return t;
}
Now, the above code can become
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
// int count = 0;
int size = toyList.size();
Toy frequent;
for (int i = size; i > 0; i--) {
frequent = getMostFrequentToy();
t.add(frequent);
// t.get(count).setCount(frequent.getCount()); // Not sure about this
toyList.remove(frequent);
// count++;
}
toyList.clear();
toyList.addAll(t);
}
Realistically, though, when you want to sort, you really should see how to create a Comparator for your Toy objects.

Can't locate the problems in this simple Genetic Algorithm program

I have written a simple genetic algorithm program in java. What it is does is maximize the decimal value represented by the bits in the chromosome. Somehow mutation is not working as expected, e.g. causing two genes to mutate when just one is to change. The print statements I have included there show which to mutate, but in addition to that some more chromosomes get mutated. I can't figure out what the problem is :-(
Here are my java classes.
Gene.java
public class Gene {
private int value;
public Gene() {
value = Math.random() < 0.5 ? 0 : 1;
}
public Gene(int value) {
if (value != 0 && value != 1) {
throw new IllegalArgumentException("value must be either 0 or 1");
}
else {
this.value = value;
}
}
public void mutate() {
value = 1 - value;
}
public int value() {
return value;
}
#Override
public String toString() {
return String.valueOf(value);
}
}
Chromosome.java
import java.util.ArrayList;
import java.util.List;
public class Chromosome implements Comparable {
private ArrayList<Gene> genes;
private final int chromosomeLength;
public Chromosome(int length) {
this.genes = new ArrayList<>();
this.chromosomeLength = length > 0 ? length : 16;
for (int i = 0; i < chromosomeLength; i++) {
this.genes.add(i, new Gene());
}
}
public List<Gene> getAllele(int fromIndex, int toIndex) {
return new ArrayList<>(genes.subList(fromIndex, toIndex));
}
public void setAllele(int fromIndex, List<Gene> allele) {
int lastIndex = fromIndex + allele.size();
if (lastIndex > chromosomeLength) {
throw new IndexOutOfBoundsException("the allele exceeds beyond the size of the chromosome");
}
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
}
public int getChromosomeLength() {
return chromosomeLength;
}
public void setGeneAt(int index, Gene gene) {
genes.set(index, gene);
}
public Gene getGeneAt(int index) {
return genes.get(index);
}
public int value() {
return Integer.parseInt(this.toString(), 2);
}
#Override
public String toString() {
StringBuilder chromosome = new StringBuilder("");
genes.stream().forEach((Gene g) -> chromosome.append(g));
return chromosome.toString();
}
#Override
public int compareTo(Object anotherChromosome) {
Chromosome c = (Chromosome) anotherChromosome;
return this.value() - c.value();
}
}
GenePool.java
import java.util.ArrayList;
import java.util.Arrays;
public class GenePool {
private final ArrayList<Chromosome> genePool;
private final int genePoolSize;
private final int chromosomeLength;
private final double crossOverRate;
private final double mutationRate;
private int[] crossPoints;
public GenePool(int numOfChromosome, int chromosomeLength, double crossOverRate, double mutationRate) {
this.genePoolSize = numOfChromosome;
this.chromosomeLength = chromosomeLength > 0 ? chromosomeLength : 16;
this.crossOverRate = crossOverRate;
this.mutationRate = mutationRate;
crossPoints = new int[1];
crossPoints[0] = this.chromosomeLength / 2;
genePool = new ArrayList<>();
for (int i = 0; i < numOfChromosome; i++) {
genePool.add(new Chromosome(chromosomeLength));
}
}
public int getGenePoolSize() {
return genePoolSize;
}
public Chromosome getChromosomeAt(int index) {
return genePool.get(index);
}
public void setChromosomeAt(int index, Chromosome c) {
genePool.set(index, c);
}
public int getChromosomeLength() {
return chromosomeLength;
}
public Chromosome[] crossOver(Chromosome c1, Chromosome c2) {
Chromosome[] offsprings = new Chromosome[2];
offsprings[0] = new Chromosome(c1.getChromosomeLength());
offsprings[1] = new Chromosome(c1.getChromosomeLength());
Chromosome[] parentChromosomes = {c1, c2};
int selector = 0;
for (int i = 0, start = 0; i <= crossPoints.length; i++) {
int crossPoint = i == crossPoints.length ? c1.getChromosomeLength() : crossPoints[i];
offsprings[0].setAllele(start, parentChromosomes[selector].getAllele(start, crossPoint));
offsprings[1].setAllele(start, parentChromosomes[1 - selector].getAllele(start, crossPoint));
selector = 1 - selector;
start = crossPoint;
}
return offsprings;
}
public void mutateGenePool() {
int totalGeneCount = genePoolSize * chromosomeLength;
System.out.println("Mutating genes:");
for (int i = 0; i < totalGeneCount; i++) {
double prob = Math.random();
if (prob < mutationRate) {
System.out.printf("Chromosome#: %d\tGene#: %d\n", i / chromosomeLength, i % chromosomeLength);
genePool.get(i / chromosomeLength).getGeneAt(i % chromosomeLength).mutate();
}
}
System.out.println("");
}
public int getLeastFitIndex() {
int index = 0;
int min = genePool.get(index).value();
int currentValue;
for (int i = 1; i < genePoolSize; i++) {
currentValue = genePool.get(i).value();
if (currentValue < min) {
index = i;
min = currentValue;
}
}
return index;
}
public void saveFittest(ArrayList<Chromosome> offsprings) {
// sort in ascending order
offsprings.sort(null);
offsprings.stream().forEach((offspring) -> {
int leastFitIndex = getLeastFitIndex();
if (offspring.value() > genePool.get(leastFitIndex).value()) {
genePool.set(leastFitIndex, offspring);
}
});
}
public void evolve(int noOfGeneration) {
for (int generation = 1; generation <= noOfGeneration; generation++) {
System.out.println("Generation :" + generation);
ArrayList<Integer> selection = new ArrayList<>();
for (int i = 0; i < genePoolSize; i++) {
if (Math.random() <= crossOverRate) {
selection.add(i);
}
}
if (selection.size() % 2 == 1) {
selection.remove(selection.size() - 1);
}
ArrayList<Chromosome> offsprings = new ArrayList<>();
for (int i = 0; i < selection.size(); i += 2) {
int index1 = selection.get(i);
int index2 = selection.get(i + 1);
offsprings.addAll(Arrays.asList(crossOver(genePool.get(index1), genePool.get(index2))));
}
System.out.println("Before saving the offsprings");
displayChromosomes(genePool, "GenePool");
displayChromosomes(offsprings, "Offsprings");
saveFittest(offsprings);
System.out.println("Before mutation:");
displayChromosomes(genePool, "GenePool");
mutateGenePool();
System.out.println("After mutation:");
displayChromosomes(genePool, "GenePool");
System.out.println("\n\n");
}
}
public void displayChromosomes(ArrayList<Chromosome> geneList, String name) {
System.out.println(name);
if (geneList.isEmpty()) {
System.out.println("Empty list");
}
geneList.stream().forEach((c) -> {
System.out.println(c + " -> " + c.value());
});
System.out.println("");
}
}
GADemo.java
public class GADemo {
public static void main(String[] args) {
GenePool gp = new GenePool(6, 8, 0.25, 0.01);
gp.evolve(10);
}
}
After evolving for a number of generations, the chromosomes all tend to become exactly the same, or very similar. And the problem is that that value is not the maximum for that many bits, and sometimes even a small value. For example, for 8 bits the values should (tend to) approach 255, but this doesn't do so in my code. Someone please provide a hint where/how to look for and solve the problem.
Focus on these lines and imagine the references. These are from setAllele()
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
You are basically copying the reference from one onto the other. They are the same Gene so whatever mutation you do on those genes, will also affect even other Chromosomes.
You must produce a deep copy here.
Initially each chromosome has an own list of genes. But when you do the crossover operation you set gene objects from one chromosome into the gene list of other chromosome.
When you evolve the system, the number of shared genes will rise and therefore ultimately all chromosomes will share the same genes. No matter how you mutate a gene the chromosomes are not affected.
EDIT:
As Incognito also answered the setAllele method seems to be the culprit where gene sharing starts. You may want to introduce a method in the gene class where you can set its value given another gene.

Given a target sum, find if there is a pair of element in the given array which sums up to it

import java.util.HashMap;
public class target
{
public static void hash(int []a,int sum)
{
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
int i;
for (i = 0; i < a.length; ++i)
map.put(a[i], sum-a[i]);
for (i = 0; i < a.length; ++i)
if(map.containsValue(a[i]) && map.get(a[i])!=null)
{
System.out.println("("+a[i]+","+map.get(a[i])+")");
map.remove(a[i]);
}
}
public static void main(String[] args)
{
int []a={1, 2, 13, 34, 9, 3, 23, 45, 8, 7, 8, 3, 2};
hash(a,11);
}
}
I want to know if there is a better and more efficient solution that the above one. Complexity of this is n. Can I do better?
Your implementation misses duplicated pairs.
You could
sort the array
iterate from the start and for each element
calculate the required complement (sum - element)
do a reverse binary search (from the end of the sorted array) looking for that precise value
if found, remove both
It boils down to the observation that, with elements sorted:
n1 < n2 < n3 < n4 < n5 < n6
the most likely pairs are coming symmetrically from both ends to the middle. Now, the worst case is still bad, but at least you don't have the hashtable overhead
As I commented, your sollution is not O(N), because the containsValue make a search of all values stored at the HashMap. To solve it, I made a different approach using your solution:
public static void newVersion(int[] a, int sum){
HashMap<Integer, Boolean> map = new HashMap<Integer, Boolean>();
for (int i= 0; i< a.length; i++) {
map.put(sum - a[i], true);
}
for (int i = 0; i < a.length; i++) {
if (map.containsKey(a[i]) && map.get(a[i])) {
System.out.println("("+(sum-a[i])+","+a[i]+")");
map.put(a[i], false);
map.put(sum-a[i], false);
}
}
}
At the first step, it stores the "complement value" of each integer and at the second step it checks if the complement exists. If it exists, mark both pair as used.
This complexity is:
* O(N) for the first looping
* O(N) * (O(1) + O(1)) for the second loop and the containsValue and get.
* Finally: O(N) + O(N) .:. O(N) solution,
I have the following solution for this problem. The time complexity should be O(N) because the HashMap operations put, get and keySet are O(1).
import java.util.HashMap;
import java.util.Map;
/**
* Find a pair of numbers in an array given a target sum
*
*
*/
public class FindNums {
public static void findSumsForTarget(int[] input, int target)
{
// just print it instead of returning
Map<Integer, String> myMap = populateMap(input);
// iterate over key set
for (Integer currKey : myMap.keySet()) {
// find the diff
Integer diff = target - currKey;
// check if diff exists in the map
String diffMapValue = myMap.get(diff);
if(diffMapValue!=null)
{
// sum exists
String output = "Sum of parts for target " + target + " are " + currKey + " and " + diff;
System.out.println(output);
return; // exit; we're done - unless we wanted all the possible pairs and permutations
}
// else
// keep looking
}
System.out.println("No matches found!");
}
private static Map<Integer, String> populateMap(int[] input)
{
Map<Integer,String> myMap = new HashMap<Integer,String>();
for (int i = 0; i < input.length; i++) {
String currInputVal = myMap.get(input[i]);
if(currInputVal!=null) // value already exists
{
// append current index location to value
currInputVal = currInputVal + ", " + i;
// do a put with the updated value
myMap.put(input[i], currInputVal);
}
else
{
myMap.put(input[i], Integer.toString(i)); // first argument is autoboxed to Integer class
}
}
return myMap;
}
// test it out!
public static void main(String[] args)
{
int[] input1 = {2,3,8,12,1,4,7,3,8,22};
int[] input2 = {1,2,3,4,5,6,7,8,9,10};
int[] input3 = {2,-3,8,12,1,4,7,3,8,22};
int target1 = 19;
int target2 = 16;
// test
FindNums.findSumsForTarget(input1, target1);
FindNums.findSumsForTarget(input1, -1);
FindNums.findSumsForTarget(input2, target2);
FindNums.findSumsForTarget(input3, target1);
}
}
import java.util.*;
import java.io.*;
class hashsum
{
public static void main(String arg[])throws IOException
{
HashMap h1=new HashMap();
h1.put("1st",new Integer(10));
h1.put("2nd",new Integer(24));
h1.put("3rd",new Integer(12));
h1.put("4th",new Integer(9));
h1.put("5th",new Integer(43));
h1.put("6th",new Integer(13));
h1.put("7th",new Integer(5));
h1.put("8th",new Integer(32));
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter no.");
int no=Integer.parseInt(br.readLine());
Iterator i=h1.entrySet().iterator();
boolean flag=false;
while(i.hasNext())
{
Map.Entry e1=(Map.Entry)i.next();
Integer n1=(Integer)e1.getValue();
Iterator j=h1.entrySet().iterator();
while(j.hasNext())
{
Map.Entry e2=(Map.Entry)j.next();
Integer n2=(Integer)e2.getValue();
if(no==(n1+n2))
{
System.out.println("Pair of elements:"+n1 +" "+n2);
flag=true;
}
}
}
if(flag==false)
System.out.println("No pairs");
}
}
public static void hash1(int[] a, int num) {
Arrays.sort(a);
// printArray(a);
int top = 0;
int bott = a.length - 1;
while (top < bott) {
while (a[bott] > num)
bott--;
int sum = a[top] + a[bott];
if (sum == num) {
System.out.println("Pair " + a[top] + " " + a[bott]);
top++;
bott--;
}
if (sum < num)
top++;
if (sum > num)
bott--;
}
}
Solution: O(n) time and O(log(n)) space.
public static boolean array_find(Integer[] a, int X)
{
boolean[] b = new boolean[X];
int i;
for (i=0;i<a.length;i++){
int temp = X-a[i];
if(temp >= 0 && temp < X) //make sure you are in the bound or b
b[temp]=true;
}
for (i=0;i<a.length;i++)
if(a[i]<X && b[a[i]]) return true;
return false;
}
Recursively to find the subset whose sum is the targeted sum from given array.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static Set<List<Integer>> set = new HashSet<>();
public static void main(String[] args) {
int[] biggerArray = {1, 2, 1, 1};
int targetedSum = 3;
findSubset(biggerArray, targetedSum);
}
public static void findSubset(int[] biggerArray, int targetedSum) {
for (int i = 0; i < biggerArray.length; i++) {
List<Integer> subset = new ArrayList<>();
if (biggerArray[i] > targetedSum)
continue;
else
subset.add(biggerArray[i]);
if (i + 1 < biggerArray.length)
find(subset, i, biggerArray, targetedSum, i);
}
System.out.println(set);
}
public static List<Integer> find(List<Integer> subset, int startIndex, final int[] biggerArray, final int targetedSum, final int skipIndex) {
if (skipIndex == startIndex) {
find(subset, startIndex + 1, biggerArray, targetedSum, skipIndex);
return null;
}
int subsetSum = findSumOfList(subset);
int remainedSum = targetedSum - subsetSum;
int i = startIndex;
if (remainedSum == 0) {
set.add(subset);
return null;
}
if ((startIndex < biggerArray.length) && (biggerArray[startIndex] == remainedSum)) {
List<Integer> temp = new ArrayList<Integer>(subset);
temp.add(biggerArray[i]);
set.add(temp);
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] < remainedSum)) {
while (i + 1 <= biggerArray.length) {
List<Integer> temp = new ArrayList<Integer>(subset);
if (i != skipIndex) {
temp.add(biggerArray[i]);
find(temp, ++i, biggerArray, targetedSum, skipIndex);
}
else {
i = i + 1;
}
}
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] > remainedSum)) {
find(subset, ++i, biggerArray, targetedSum, skipIndex);
}
return null;
}
public static int findSumOfList(List<Integer> list) {
int i = 0;
for (int j : list) {
i = i + j;
}
return i;
}
}
We need not have two for loops. The match can be detected in the same loop while populating the map it self.
public static void matchingTargetSumPair(int[] input, int target){
Map<Integer, Integer> targetMap = new HashMap<Integer, Integer>();
for(int i=0; i<input.length; i++){
targetMap.put(input[i],target - input[i]);
if(targetMap.containsKey(target - input[i])){
System.out.println("Mathcing Pair: "+(target - input[i])+" , "+input[i]);
}
}
}
public static void main(String[] args) {
int[] targetInput = {1,2,4,5,8,12};
int target = 9;
matchingTargetSumPair(targetInput, target);
}
We can easily find if any pair exists while populating the array itself. Use a hashmap and for every input element, check if sum-input difference element exists in the hashmap or not.
import java.util.*;
class findElementPairSum{
public static void main(String[] args){
Map<Integer, Integer> hm = new HashMap<Integer, Integer>();
Scanner sc = new Scanner(System.in);
System.out.println("Enter the sum key: ");
int sum=sc.nextInt();
for(int i=0; i<10; i++){
int x = sc.nextInt();
if(!hm.containsKey(sum-x)){
hm.put(x, 1);
} else {
System.out.println("Array contains two elements with sum equals to: "+sum);
break;
}
}
}
}

Categories

Resources