If we make x
a vector of tuples (i.e. x = [(1, 2, 3), (4, 5, 6)]
), then sum(x)
errors, but (.+)(x...)
still works.
Also:
LinearIndices(lim)[I]
CartesianIndices(lim)[x]
Of course! But those allocate… Mine do too, but the non-one-liner originals don’t…
Actually, a big reason this came up for me is getting the indices in cases of unknown dimension (which breaks type stability in case of CartesianIndices
and LinearIndices
!)
I believe these are designed not to allocate?
Do they not allocate a CartesianIndices
object, or does indexing the CartesianIndices
compile away?
In any case I was wrong to bring up allocations as a reason. I have only used something like the above for reasons of type stability when the number of dimensions is not inferable, since
typeof(LinearIndices((2,2))) != typeof(LinearIndices((2,2,2)))
As with many immutables in Julia, they disappear entirely upon compilation if you don’t return them.
As far as the type instability goes, that’s true of the tuples themselves — typeof((1,2)) != typeof((1,2,3))
. And you’ll see the same thing with arrays.
True, dealing with the Tuples themselves would be unstable as well.
Here’s another cool one-liner (from hitting up-arrow a million times at the REPL looking for something interesting )
unzip(a) = [getindex.(a, i) for i in eachindex(a[1])]
Assuming a is some uniform collection
I just had this fun one liner.
Let say you wish to do polynomial interpolation given an array v
and f.(v) == w
, you wish to find f(x)
.
([y^i for y in v, i in 0:length(v)] \ w)'*[x^i for i in 0:length(v)-1]
ooo that’s super slick!
Perhaps you are already aware of this, but note that the Vandermonde matrix is very badly conditioned. Orthogonal polynomials usually do much better, and may have faster interpolators.
You can fix the ill-conditioning issue for Vardermonde matrices with Arnoldi orthogonalization, but that won’t fit in a nice one liner.
The goal of the code is to get the “first and last number in a sequence of consecutive numbers”, or by example, from:
df = DataFrame([])
df.list = [[1,2,3,6,12,13,14],[20,21,23,24,50],[1,3,5,7,10,11,12,13]]
to add the following field:
df.new = [[1,3,12,14],[20,21,23,24],[10,13]] #it is important that they are made up of pairs!
Various solutions with better run-time are shown in thread:
https://discourse.julialang.org/t/how-to-reduce-redundancy-in-a-list-inside-a-dataframe/88585
But a neat one-line solution is:
transform(df, :list => ByRow(f->filter(x->(x-1 ∈ f) ⊻ (x+1 ∈ f),f)) => :new)
Kudos to @rafael.guerra for pointing me to this thread.
Not just elegant, but also one of the most efficient ways to traverse through all subsets of a given superset S
of enumerated elements, only requiring a single variable (no further index, tmp-variable or whatnot). O(n)
-time & O(1)
-space
# carry-rippler - finite-state-machine for subset-traversal
i=0; while( (i = (i-S) & S) !=0 ) println(bitstring(i)); end
defining the superset like so…
# example input: 8 elements in the superset (bits 25..28 & 33..36) are set to one...
julia> S = 0x0000000f0f000000
julia> bitstring(S)
"0000000000000000000000001111000011110000000000000000000000000000"
Output (caution: 2^n-1
lines for n bits set in S )…
0000000000000000000000000000000000000001000000000000000000000000
0000000000000000000000000000000000000010000000000000000000000000
0000000000000000000000000000000000000011000000000000000000000000
0000000000000000000000000000000000000100000000000000000000000000
0000000000000000000000000000000000000101000000000000000000000000
0000000000000000000000000000000000000110000000000000000000000000
0000000000000000000000000000000000000111000000000000000000000000
0000000000000000000000000000000000001000000000000000000000000000
0000000000000000000000000000000000001001000000000000000000000000
0000000000000000000000000000000000001010000000000000000000000000
0000000000000000000000000000000000001011000000000000000000000000
0000000000000000000000000000000000001100000000000000000000000000
0000000000000000000000000000000000001101000000000000000000000000
0000000000000000000000000000000000001110000000000000000000000000
0000000000000000000000000000000000001111000000000000000000000000
0000000000000000000000000000000100000000000000000000000000000000
0000000000000000000000000000000100000001000000000000000000000000
0000000000000000000000000000000100000010000000000000000000000000
0000000000000000000000000000000100000011000000000000000000000000
0000000000000000000000000000000100000100000000000000000000000000
0000000000000000000000000000000100000101000000000000000000000000
0000000000000000000000000000000100000110000000000000000000000000
0000000000000000000000000000000100000111000000000000000000000000
0000000000000000000000000000000100001000000000000000000000000000
0000000000000000000000000000000100001001000000000000000000000000
0000000000000000000000000000000100001010000000000000000000000000
0000000000000000000000000000000100001011000000000000000000000000
0000000000000000000000000000000100001100000000000000000000000000
0000000000000000000000000000000100001101000000000000000000000000
0000000000000000000000000000000100001110000000000000000000000000
0000000000000000000000000000000100001111000000000000000000000000
0000000000000000000000000000001000000000000000000000000000000000
0000000000000000000000000000001000000001000000000000000000000000
0000000000000000000000000000001000000010000000000000000000000000
0000000000000000000000000000001000000011000000000000000000000000
0000000000000000000000000000001000000100000000000000000000000000
0000000000000000000000000000001000000101000000000000000000000000
0000000000000000000000000000001000000110000000000000000000000000
0000000000000000000000000000001000000111000000000000000000000000
0000000000000000000000000000001000001000000000000000000000000000
0000000000000000000000000000001000001001000000000000000000000000
0000000000000000000000000000001000001010000000000000000000000000
0000000000000000000000000000001000001011000000000000000000000000
0000000000000000000000000000001000001100000000000000000000000000
0000000000000000000000000000001000001101000000000000000000000000
0000000000000000000000000000001000001110000000000000000000000000
0000000000000000000000000000001000001111000000000000000000000000
0000000000000000000000000000001100000000000000000000000000000000
0000000000000000000000000000001100000001000000000000000000000000
0000000000000000000000000000001100000010000000000000000000000000
0000000000000000000000000000001100000011000000000000000000000000
0000000000000000000000000000001100000100000000000000000000000000
0000000000000000000000000000001100000101000000000000000000000000
0000000000000000000000000000001100000110000000000000000000000000
0000000000000000000000000000001100000111000000000000000000000000
0000000000000000000000000000001100001000000000000000000000000000
0000000000000000000000000000001100001001000000000000000000000000
0000000000000000000000000000001100001010000000000000000000000000
0000000000000000000000000000001100001011000000000000000000000000
0000000000000000000000000000001100001100000000000000000000000000
0000000000000000000000000000001100001101000000000000000000000000
0000000000000000000000000000001100001110000000000000000000000000
0000000000000000000000000000001100001111000000000000000000000000
0000000000000000000000000000010000000000000000000000000000000000
0000000000000000000000000000010000000001000000000000000000000000
0000000000000000000000000000010000000010000000000000000000000000
0000000000000000000000000000010000000011000000000000000000000000
0000000000000000000000000000010000000100000000000000000000000000
0000000000000000000000000000010000000101000000000000000000000000
0000000000000000000000000000010000000110000000000000000000000000
0000000000000000000000000000010000000111000000000000000000000000
0000000000000000000000000000010000001000000000000000000000000000
0000000000000000000000000000010000001001000000000000000000000000
0000000000000000000000000000010000001010000000000000000000000000
0000000000000000000000000000010000001011000000000000000000000000
0000000000000000000000000000010000001100000000000000000000000000
0000000000000000000000000000010000001101000000000000000000000000
0000000000000000000000000000010000001110000000000000000000000000
0000000000000000000000000000010000001111000000000000000000000000
0000000000000000000000000000010100000000000000000000000000000000
0000000000000000000000000000010100000001000000000000000000000000
0000000000000000000000000000010100000010000000000000000000000000
0000000000000000000000000000010100000011000000000000000000000000
0000000000000000000000000000010100000100000000000000000000000000
0000000000000000000000000000010100000101000000000000000000000000
0000000000000000000000000000010100000110000000000000000000000000
0000000000000000000000000000010100000111000000000000000000000000
0000000000000000000000000000010100001000000000000000000000000000
0000000000000000000000000000010100001001000000000000000000000000
0000000000000000000000000000010100001010000000000000000000000000
0000000000000000000000000000010100001011000000000000000000000000
0000000000000000000000000000010100001100000000000000000000000000
0000000000000000000000000000010100001101000000000000000000000000
0000000000000000000000000000010100001110000000000000000000000000
0000000000000000000000000000010100001111000000000000000000000000
0000000000000000000000000000011000000000000000000000000000000000
0000000000000000000000000000011000000001000000000000000000000000
0000000000000000000000000000011000000010000000000000000000000000
0000000000000000000000000000011000000011000000000000000000000000
0000000000000000000000000000011000000100000000000000000000000000
0000000000000000000000000000011000000101000000000000000000000000
0000000000000000000000000000011000000110000000000000000000000000
0000000000000000000000000000011000000111000000000000000000000000
0000000000000000000000000000011000001000000000000000000000000000
0000000000000000000000000000011000001001000000000000000000000000
0000000000000000000000000000011000001010000000000000000000000000
0000000000000000000000000000011000001011000000000000000000000000
0000000000000000000000000000011000001100000000000000000000000000
0000000000000000000000000000011000001101000000000000000000000000
0000000000000000000000000000011000001110000000000000000000000000
0000000000000000000000000000011000001111000000000000000000000000
0000000000000000000000000000011100000000000000000000000000000000
0000000000000000000000000000011100000001000000000000000000000000
0000000000000000000000000000011100000010000000000000000000000000
0000000000000000000000000000011100000011000000000000000000000000
0000000000000000000000000000011100000100000000000000000000000000
0000000000000000000000000000011100000101000000000000000000000000
0000000000000000000000000000011100000110000000000000000000000000
0000000000000000000000000000011100000111000000000000000000000000
0000000000000000000000000000011100001000000000000000000000000000
0000000000000000000000000000011100001001000000000000000000000000
0000000000000000000000000000011100001010000000000000000000000000
0000000000000000000000000000011100001011000000000000000000000000
0000000000000000000000000000011100001100000000000000000000000000
0000000000000000000000000000011100001101000000000000000000000000
0000000000000000000000000000011100001110000000000000000000000000
0000000000000000000000000000011100001111000000000000000000000000
0000000000000000000000000000100000000000000000000000000000000000
0000000000000000000000000000100000000001000000000000000000000000
0000000000000000000000000000100000000010000000000000000000000000
0000000000000000000000000000100000000011000000000000000000000000
0000000000000000000000000000100000000100000000000000000000000000
0000000000000000000000000000100000000101000000000000000000000000
0000000000000000000000000000100000000110000000000000000000000000
0000000000000000000000000000100000000111000000000000000000000000
0000000000000000000000000000100000001000000000000000000000000000
0000000000000000000000000000100000001001000000000000000000000000
0000000000000000000000000000100000001010000000000000000000000000
0000000000000000000000000000100000001011000000000000000000000000
0000000000000000000000000000100000001100000000000000000000000000
0000000000000000000000000000100000001101000000000000000000000000
0000000000000000000000000000100000001110000000000000000000000000
0000000000000000000000000000100000001111000000000000000000000000
0000000000000000000000000000100100000000000000000000000000000000
0000000000000000000000000000100100000001000000000000000000000000
0000000000000000000000000000100100000010000000000000000000000000
0000000000000000000000000000100100000011000000000000000000000000
0000000000000000000000000000100100000100000000000000000000000000
0000000000000000000000000000100100000101000000000000000000000000
0000000000000000000000000000100100000110000000000000000000000000
0000000000000000000000000000100100000111000000000000000000000000
0000000000000000000000000000100100001000000000000000000000000000
0000000000000000000000000000100100001001000000000000000000000000
0000000000000000000000000000100100001010000000000000000000000000
0000000000000000000000000000100100001011000000000000000000000000
0000000000000000000000000000100100001100000000000000000000000000
0000000000000000000000000000100100001101000000000000000000000000
0000000000000000000000000000100100001110000000000000000000000000
0000000000000000000000000000100100001111000000000000000000000000
0000000000000000000000000000101000000000000000000000000000000000
0000000000000000000000000000101000000001000000000000000000000000
0000000000000000000000000000101000000010000000000000000000000000
0000000000000000000000000000101000000011000000000000000000000000
0000000000000000000000000000101000000100000000000000000000000000
0000000000000000000000000000101000000101000000000000000000000000
0000000000000000000000000000101000000110000000000000000000000000
0000000000000000000000000000101000000111000000000000000000000000
0000000000000000000000000000101000001000000000000000000000000000
0000000000000000000000000000101000001001000000000000000000000000
0000000000000000000000000000101000001010000000000000000000000000
0000000000000000000000000000101000001011000000000000000000000000
0000000000000000000000000000101000001100000000000000000000000000
0000000000000000000000000000101000001101000000000000000000000000
0000000000000000000000000000101000001110000000000000000000000000
0000000000000000000000000000101000001111000000000000000000000000
0000000000000000000000000000101100000000000000000000000000000000
0000000000000000000000000000101100000001000000000000000000000000
0000000000000000000000000000101100000010000000000000000000000000
0000000000000000000000000000101100000011000000000000000000000000
0000000000000000000000000000101100000100000000000000000000000000
0000000000000000000000000000101100000101000000000000000000000000
0000000000000000000000000000101100000110000000000000000000000000
0000000000000000000000000000101100000111000000000000000000000000
0000000000000000000000000000101100001000000000000000000000000000
0000000000000000000000000000101100001001000000000000000000000000
0000000000000000000000000000101100001010000000000000000000000000
0000000000000000000000000000101100001011000000000000000000000000
0000000000000000000000000000101100001100000000000000000000000000
0000000000000000000000000000101100001101000000000000000000000000
0000000000000000000000000000101100001110000000000000000000000000
0000000000000000000000000000101100001111000000000000000000000000
0000000000000000000000000000110000000000000000000000000000000000
0000000000000000000000000000110000000001000000000000000000000000
0000000000000000000000000000110000000010000000000000000000000000
0000000000000000000000000000110000000011000000000000000000000000
0000000000000000000000000000110000000100000000000000000000000000
0000000000000000000000000000110000000101000000000000000000000000
0000000000000000000000000000110000000110000000000000000000000000
0000000000000000000000000000110000000111000000000000000000000000
0000000000000000000000000000110000001000000000000000000000000000
0000000000000000000000000000110000001001000000000000000000000000
0000000000000000000000000000110000001010000000000000000000000000
0000000000000000000000000000110000001011000000000000000000000000
0000000000000000000000000000110000001100000000000000000000000000
0000000000000000000000000000110000001101000000000000000000000000
0000000000000000000000000000110000001110000000000000000000000000
0000000000000000000000000000110000001111000000000000000000000000
0000000000000000000000000000110100000000000000000000000000000000
0000000000000000000000000000110100000001000000000000000000000000
0000000000000000000000000000110100000010000000000000000000000000
0000000000000000000000000000110100000011000000000000000000000000
0000000000000000000000000000110100000100000000000000000000000000
0000000000000000000000000000110100000101000000000000000000000000
0000000000000000000000000000110100000110000000000000000000000000
0000000000000000000000000000110100000111000000000000000000000000
0000000000000000000000000000110100001000000000000000000000000000
0000000000000000000000000000110100001001000000000000000000000000
0000000000000000000000000000110100001010000000000000000000000000
0000000000000000000000000000110100001011000000000000000000000000
0000000000000000000000000000110100001100000000000000000000000000
0000000000000000000000000000110100001101000000000000000000000000
0000000000000000000000000000110100001110000000000000000000000000
0000000000000000000000000000110100001111000000000000000000000000
0000000000000000000000000000111000000000000000000000000000000000
0000000000000000000000000000111000000001000000000000000000000000
0000000000000000000000000000111000000010000000000000000000000000
0000000000000000000000000000111000000011000000000000000000000000
0000000000000000000000000000111000000100000000000000000000000000
0000000000000000000000000000111000000101000000000000000000000000
0000000000000000000000000000111000000110000000000000000000000000
0000000000000000000000000000111000000111000000000000000000000000
0000000000000000000000000000111000001000000000000000000000000000
0000000000000000000000000000111000001001000000000000000000000000
0000000000000000000000000000111000001010000000000000000000000000
0000000000000000000000000000111000001011000000000000000000000000
0000000000000000000000000000111000001100000000000000000000000000
0000000000000000000000000000111000001101000000000000000000000000
0000000000000000000000000000111000001110000000000000000000000000
0000000000000000000000000000111000001111000000000000000000000000
0000000000000000000000000000111100000000000000000000000000000000
0000000000000000000000000000111100000001000000000000000000000000
0000000000000000000000000000111100000010000000000000000000000000
0000000000000000000000000000111100000011000000000000000000000000
0000000000000000000000000000111100000100000000000000000000000000
0000000000000000000000000000111100000101000000000000000000000000
0000000000000000000000000000111100000110000000000000000000000000
0000000000000000000000000000111100000111000000000000000000000000
0000000000000000000000000000111100001000000000000000000000000000
0000000000000000000000000000111100001001000000000000000000000000
0000000000000000000000000000111100001010000000000000000000000000
0000000000000000000000000000111100001011000000000000000000000000
0000000000000000000000000000111100001100000000000000000000000000
0000000000000000000000000000111100001101000000000000000000000000
0000000000000000000000000000111100001110000000000000000000000000
0000000000000000000000000000111100001111000000000000000000000000
# carry-rippler - finite-state-machine for subset-traversal
I knew, that julia would make it possible to decode the bit-indices in an extended one-liner, also…
# version 2, yielding vectors of actual integer-indices
# limited to indices 1..64, but can be extended, ofc.
i=0; while( (i = (i-S) & S) != 0 ) iv=[ ((i>>(j-1))&1)*j for j in 1:64 ]; println(iv[iv.>0]); end
# input: Superset = [2, 10, 15, 20, 29, 31, 38, 44, 48, 54, 61]
S = Int64(0b0001000000100000100010000010000001010000000010000100001000000010)
i=0; while( (i = (i-S) & S) != 0 ) iv=[ ((i>>(j-1))&1)*j for j in 1:64 ]; println(iv[iv.>0]); end
[2]
[10]
[2, 10]
[15]
[2, 15]
[10, 15]
[2, 10, 15]
[20]
[2, 20]
[10, 20]
⋮
[15, 20, 29, 31, 38, 44, 48, 54, 61]
[2, 15, 20, 29, 31, 38, 44, 48, 54, 61]
[10, 15, 20, 29, 31, 38, 44, 48, 54, 61]
[2, 10, 15, 20, 29, 31, 38, 44, 48, 54, 61]
thx for these gems. They actually help a newcomer to julia, like me, who needs to see, just how things can be done, here.
on a lighter note, this…
Moving julia. Not sure where it comes from.
…and an Austrian poet inspired me to write this. I sadly dunno, how to apply anything julian, for it looks more like C.
for i=0:.02:1 j=Int(floor((i-.5)^2*50+1)); k=min(j,2); println((" "^(13-j))*("fr"*["eigh","ui"][k]*"t ")^(j*1)); sleep(j*.1) end
Symmetry!
julia> f <| x = x |> f
<| (generic function with 1 method)
julia> sum <| 1:10 == 1:10 |> sum
true
# version 3, all subsets of a superset S (release-note: one loop is enough!)
i=0; while( (i = (i-S) & S) != 0 ) v=collect(1:64).*digits(i,base=2,pad=64); println(v[v.>0]); end
Strictly speaking, you take \mathcal{O}(n) per iteration. (Though if your initial string fits in 64-bit integer, in a different model it is constant time.)
Why does this matter? You see that your superset code, you have to actually take \mathcal{O}(n2^n) time for iterating through all the subsets. (We can do slightly better at the same time being more complex, with trickery like Gray codes.)
For more information: Knuth 4A (Bit tricks and techniques) and Warren Jr.'s Hacker Delight.
Strictly speaking, you take O(n) per iteration.
…hehe, this is only true for versions #2 & #3, not #1.
Which is why I have only claimed O(1)
per iteration, in version #1.
The other 2 versions are just my playing with julia, to actually getting the indices unpacked, in human-readable format & in a one liner, in julia, to mimick the output of @harven’s code…
…but I haven’t figured out, how to include the trivial subset []
in my output, other than doing something stupid, like this, after initialization of i=0
…
ulia> println([])
Any[]
…but this doesn’t feel “nice”, as it is annotated with an Any
-type, which doesn’t match the other subsets.
…I think your pointer to the lit. is actually exactly accurate. My formulation in #1…
i=0; while (i = (i-S) & S) !=0 processSubset(i); end
…seems to be just one concrete application (limited to n<=64
), of Knuth’s (more general) Algorithm M
, here…
…in his formulation “The program that wants to examine all n-tuples now does its thing” is just what println(bitstring(i))
is doing in my implementation #1.
Note, I’m not coding step M4
, explicitly, but it is implicitly done, by an addition +1 and how hardware handles the carry, for us. Also, one has to expand like this:
i = (i-S) & S <=> ... <=> i = ((i | ~S) + 1) & S
(on the bitlevel!), to see, that there even is a +1
, causing potential carries to happen.
julia> S = 2287346; i = 1723
julia> ((i | ~S) + 1) & S
1728
julia> (i-S) & S
1728
It’s, in any case, an old algorithm, I must have picked up some decades ago, and which I’m actually using in my chess-engine to produce all relevant possible combination of chesspiece-positions, blocking the movement-rays of sliding-pieces (Bishophs, Rooks and Queens) - not in any actual game, but for pre-computing lookup-tables for fast move-generation, later.
Edit: What I’ve not been able to figure out, yet: How to do a do ... while(condition)
- loop in julia, elegantly, as the above algorithm is missing out on calling processSubset(i)
for the initial value i=0
, without adding another explicit call, but I’d prefer to keep stuff as concise as possible (not just in this example, here).
Edit #2: Sorry, didn’t mean to hijack the fun-part of this thread - but this is (also) fun, for me.