Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Based on @tholy's comment about instead of using the actual numbers, I could use positions (to avoid problems with numbers not being unique) and setdiff to get the "other group" (the non-selected numbers), I came up with the following. The first function grabs values out of an array based on indices (ie. arraybyindex([11,12,13,14,15], [2,4]) => [12,14]). This seems like it could be part of the standard library (I did look for it, but might have missed it).</p> <p>The second function does what combinationgroups was doing above, creating all groups of a certain size, and their complements. It can be called by itself, or through the third function, which extracts groups of all possible sizes. It's possible that this could all be written much faster, and more idiomatical. </p> <pre><code>function arraybyindex(a::Array, indx::Array) res = {} for e in indx push!(res, a[e]) end res end function combinationsbypos(a::Array, n::Integer) res = {} positions = 1:length(a) for e in combinations(positions, n) push!(res, { arraybyindex(a, e) ; arraybyindex(a, setdiff(positions, e)) }) end res end function allcombinationgroups(a::Array) maxsplit = floor(length(a) / 2) res = {} for e in 1:5 println("Calculating for $e, so far $(length(res)) groups calculated") push!(res, combinationsbypos(a, e)) end res end </code></pre> <p>Running this in IJulia on a 3 year old MacBook pro gives</p> <pre><code>@time c=allcombinationgroups([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]) println(length(c)) c Calculating for 1, so far 0 groups calculated Calculating for 2, so far 20 groups calculated Calculating for 3, so far 210 groups calculated Calculating for 4, so far 1350 groups calculated Calculating for 5, so far 6195 groups calculated Calculating for 6, so far 21699 groups calculated Calculating for 7, so far 60459 groups calculated Calculating for 8, so far 137979 groups calculated Calculating for 9, so far 263949 groups calculated Calculating for 10, so far 431909 groups calculated elapsed time: 11.565218719 seconds (1894698956 bytes allocated) Out[49]: 616665 616665-element Array{Any,1}: {{1},{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}} {{2},{1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}} ⋮ {{10,12,13,14,15,16,17,18,19,20},{1,2,3,4,5,6,7,8,9,11}} {{11,12,13,14,15,16,17,18,19,20},{1,2,3,4,5,6,7,8,9,10}} </code></pre> <p>ie. 53,334 groups calculated per second. </p> <p>As a contrast, using the same outer allcombinationgroups function, but replacing the call to combinationsbypos with a call to combinationgroups (see previous answer), is 10x slower.</p> <p>I then rewrote the array by index group using true or false flags as suggested by @tholy (I couldn't figure out how to get it work using [], so I used setindex! explicitly, and moved it into one function. Another 10x speedup! 616,665 groups in 1 second! </p> <p>Final code (so far):</p> <pre><code>function combinationsbypos(a::Array, n::Integer) res = {} positions = 1:length(a) emptyflags = falses(length(a)) for e in combinations(positions, n) flag = copy(emptyflags) setindex!(flag, true, e) push!(res, {a[flag] ; a[!flag]} ) end res end function allcombinationgroups(a::Array) maxsplit = floor(length(a) / 2) res = {} for e in 1:maxsplit res = vcat(res, combinationsbypos(a, e)) end res end </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload