Refactoring into java 8 lambda/stream -
when solve subset sum problem or "p = np" takes 5 minutes following code. curious know how faster if using .parallelstream. don't understand how convert code.
public class mainactivity { final static integer[] pops = {8897109, 12828837, 9461105, 6371773, 5965343, 5946800, 5582170, 5564635, 5268860, 4552402, 4335391, 4296250, 4224851, 4192887, 3439809, 3279833, 3095313, 2812896, 2783243, 2710489, 2543482, 2356285, 2226009, 2149127, 2142508, 2134411}; final static int total = 100000000; /** * @param args */ public static void main(string[] args) { combinations c = new combinations(pops, total); c.chooser(); }
}
import java.util.arraylist; import org.paukov.combinatorics.factory; import org.paukov.combinatorics.generator; import org.paukov.combinatorics.icombinatoricsvector; public class combinations { private integer[] pops; private int total; public combinations(integer[] pops, int total){ this.pops = pops; this.total = total; } public void chooser(){ for(int = 1; i<=pops.length; i++){ system.out.println(i); icombinatoricsvector<integer> initialvector = factory.createvector(pops); generator<integer> gen = factory.createsimplecombinationgenerator(initialvector, i); (icombinatoricsvector<integer> combination : gen) { string temp = combination.tostring(); int size = temp.indexof("size"); temp = temp.substring(22, size-3); int sum = adder(temp); if (sum == total){ system.out.println(temp); } } } } public int adder(string combos){ int total = 0; string[] parts = combos.split(", "); arraylist<integer> nums = new arraylist<>(); for(int = 0; i<parts.length; i++){ nums.add(integer.parseint(parts[i])); } for(int temp : nums){ total += temp; } return total; } }
here code string stuff taken out. takes 15 seconds now. realize .parallelstream() not reduce time much, still @ least give me hints on how it.
import java.util.arraylist; import java.util.list; import org.paukov.combinatorics.factory; import org.paukov.combinatorics.generator; import org.paukov.combinatorics.icombinatoricsvector; public class combinations { private integer[] pops; private int total; public combinations(integer[] pops, int total){ this.pops = pops; this.total = total; } public void chooser(){ for(int = 1; i<=pops.length; i++){ system.out.println(i); icombinatoricsvector<integer> initialvector = factory.createvector(pops); generator<integer> gen = factory.createsimplecombinationgenerator(initialvector, i); (icombinatoricsvector<integer> combination : gen) { list<integer> temp = combination.getvector(); int sum = adder(temp); if (sum == total){ system.out.println(temp); } } } } public int adder(list<integer> combos){ int total = 0; for(integer temp : combos){ total+=temp; } return total; } }
this runs 3 times fast on box (i7-2600 hyper-threading, 8 virtual cores):
public class combinations { private integer[] pops; private int total; public combinations(integer[] pops, int total) { this.pops = pops; this.total = total; } public void chooser() { icombinatoricsvector<integer> initialvector = factory.createvector(pops); intstream.range(1, pops.length + 1).parallel() .peek(system.out::println) .maptoobj(i -> factory.createsimplecombinationgenerator(initialvector, i)) .flatmap(gen -> gentostream(gen, false) .map(icombinatoricsvector::getvector) .filter(v -> adder(v) == total)) .foreach(system.out::println); } public static int adder(iterable<integer> combos) { int total = 0; (integer temp : combos) { total += temp; } return total; } public static <e> stream<icombinatoricsvector<e>> gentostream(generator<e> gen, boolean parallel) { return streamsupport.stream(spliterators.spliterator(gen.iterator(), gen.getnumberofgeneratedobjects(), spliterator.ordered), parallel); } }
this uses parallel stream outer loop, regular stream inner loop, , avoids using stream sum list (for speed). can try parallel inner stream gentostream(gen, true)
, didn't see difference in speed.
also, if want list<list<integer>>
of matches, change foreach line .collect(collectors.tolist());
.
Comments
Post a Comment