Forum Discussion
Working with Binary numbers BASE(..., 2, 7) and bit operations BITXOR, BITAND
Thanks for the reply, I will study it.
Meanwhile, to place the ball back in your court, I have been working up an alternative approach to the generation of all combinations of m objects from n.
I loved the elegance bisection formula and the way sets were combined. What troubled me was the duplication that was appearing. In 'normal' family trees there are 4 second generation ancestors and 8 third generation; in this case the numbers are 3 and 4 respectively with ancestors in common on both branches of the tree. This implies that some calculations are performed multiple times.
What I tried instead was to SCAN one side of Pascal's triangle and use the thunked results to initialise reduction steps on the other diagonal. The dimensions of the scanned region are m x (n-m)
I think I started out converting the function calls to Craig Hatmaker 's 5g functions but I have yest to reach the end of that process! I was happy to put the effort into the main program segments but wondered how far to go down the functional decomposition. I remember Craig's Central Error Reporting for VBA the entire calling tree was documented and would be returnable to assist the developer whilst being suppressed for an end user with no access to the code.
That looks impressive and not a method I think I ever could have foreseen! And I see what you mean about the repetition in the binary tree. The method of m_tarler in the previous link also looks elegant with acceptable performance which I suspect could be further improved with some minor alterations. I will need to set some time aside to look at all this in more detail...
PS. Just to clarify in my last post it looks like a closing parenthesis was omitted from the first formula and, in the screenshot, the cell beneath 'Residual' contains a spilled array formula: =MinSubset(seats, 122)
- PeterBartholomew1Jun 17, 2024Silver Contributor
I wish I knew for how long these workarounds are to be needed. I suspect the vast majority of spreadsheet users will never make the jump to the Excel formula as a functional programming language and the nested array problem only makes it more intimidating!
Towers of Hanoi. I am not sure which discussion it was attached to but it was posted by Patrick (I have a copy). I do not know why it has disappeared, though. The algorithm appears to build a table of moves that lead to the solution but without ever calculating the current state of the problem.
BTW I am planning to attend EuSpRIG Annual Conference | European Spreadsheet Risk Interest Group.
The programme looks quite varied this year.
- lori_mMay 29, 2024Iron Contributor
Ok, so after several weeks of head banging, i feel like there may finally be some progress!
First, as far as i'm aware the list of scalable alternatives to the basic REDUCE/VSTACK method for stacking arrays now includes: nested reduce, recursive bisection, thunk arrays and lambda accumulators. Several examples are given in earlier comments; a relatively efficient implementation utilising lambda accumulators could be
BYROWλ =LAMBDA(array, function, LET( n, ROWS(array), k, CEILING.MATH(LOG(n,2)), REDUCE( LAMBDA(r,function(CHOOSEROWS(array,r))), SEQUENCE(k,,0), LAMBDA(a,i,LAMBDA(j,IF(j+2^i<=n,VSTACK(a(j),a(j+2^i)),a(j)))) )(1) ) )
Second, for enumerating combinations, tests suggest lookups can be faster than stacking when returning longer result sets and that 2D-arrays may be needed to overcome decimal precision limitations such as:
=LAMBDA(n,k, REDUCE(SEQUENCE(n-k+1),SEQUENCE(k-1,,2),LAMBDA(a,j, LET(r,ROUND(COMBIN(SEQUENCE(n-k+1,,j),j),), i,SEQUENCE(@TAKE(r,-1,1)), HSTACK( CHOOSEROWS(a,i-XLOOKUP(i,r,VSTACK(0,DROP(r,-1)),,1)), XMATCH(i,r,1)+j-1 ) ) )))(20,10)
P.S. was there a Towers of Hanoi lambda posted here previously? Maybe I was hallucinating but I had been hoping to check it out when it seemed to vanish!
- lori_mMay 01, 2024Iron Contributor
That thunk method looks pretty neat - I was impressed by the speed too. In previous attempts working with thunks I had experienced performance issues that were difficult to circumvent. Passing the thunk array as an array parameter to SCAN is clever and appears much more efficient than passing as a lambda parameter - within MAKEARRAY for example.
My first attempt to improve efficiency was to apply memoization which is a standard technique to avoid recomputing values within the recursion. I started looking at converting some online code examples to lambdas by building a table of thunks before realising that this was going to be similar to your method but probably less fast!
A follow-up thought was to generate all decimal combinations in a single row of Pascal's triangle iteratively,
=SORT(REDUCE(0,SEQUENCE(n),LAMBDA(a,_,VSTACK(a*{1,2},a*{1,2}+1))),{1,2})
With n = 12 for example this returns 2^12=4096 rows, the first column is the number of combinations k and the second is the decimal representation of the combination. To return just the COMBIN(n,k) combinations we only need keep combinations less than k,
=LAMBDA(n, k, LET( combs, REDUCE( 0, SEQUENCE(n), LAMBDA(a, i, SORT( VSTACK( DROP(a, IF(i > n - k, INT(COMBIN(i - 1, n - k)), 0)) * {1, 2}, DROP(a, IF(i > k, -INT(COMBIN(i - 1, k)), 0)) * {1, 2} + 1 ), {1, 2} ) ) ), BASE(TAKE(combs, , -1), 2, n) ) )
I expected this might be faster than the thunk approach but in practice it fell short due to the repeated SORT operations so likely needs further refinements. I was also surprised that COMBIN returns non-integers in some cases (e.g. try removing 'INT' with n=12 and k=6)