Forum Discussion
Working with Binary numbers BASE(..., 2, 7) and bit operations BITXOR, BITAND
I recently came across an Excel challenge from Chinmay Amte on LinkedIn and I plan to post my solution here because it contains some 'off the beaten track' techniques that might be of some interest.
"Yesterday, Indian state of Bihar was in news due to change in structure of coalition government.
Assume you are an Analyst at Governor's office. He has asked you to evaluate ALL possible combinations of coalition between the political parties to form a government."
Please note, minimum vote of 122 is required to form government.
The correct answer for the number of possible combinations is 61 (done manually)!
= LET(
n, COUNTA(party),
combinations, SEQUENCE(2^n - 1),
totalSeats, MAP(combinations, SeatCountλ(seats)),
possible, FILTER(combinations, totalSeats>121),
coalition, MAP(possible, ListNamesλ(party)),
seats, MAP(possible, SeatCountλ(seats)),
HSTACK(coalition, seats)
)
MID is then used to split the binary number (a string) into separate cells to that matrix multiplication can be used to evaluate the total seats for each coalition.
"SeatCountλ"
= LAMBDA(combination,
LET(
n, COUNTA(seats),
bin, BASE(combination, 2, n),
k, SEQUENCE(1, n),
p, SIGN(MID(bin, k, 1)),
MMULT(p, seats)
)
)
I observed that the coalitions identified include cases that have more parties involved than are strictly necessary to form a government. Therefore I set out to discount any coalition that included a viable governing coalition as a subset. That is where the bit operations came into the equation.
Subsetλ
"Determines whether the first parameter is a subset of the second
where set membership is determined by digits of a binary number"
= LAMBDA(set₁,
LET(
diff, BITXOR(set₁, set₂),
IF(set₁ <> set₂, BITAND(set₁, diff) = 0)
)
)
Despite the fact that the concept involves binary numbers, the arguments to BITXOR and BITAND are actually their decimal equivalents. Exclusive BITXOR returns 0 where the corresponding bits match and 1 for mismatches. The bitwise BITAND examines one of the sets to see whether there is any non-zeros where the sets differ. That is does that coalition include any parties that are not in the second, in which case both combinations must be retained.
It is not often I get to use BITXOR etc. Do others have examples of their use?
Just as a final point which may cause reaction from Excel users that hate 'black boxes', my final worksheet formula was no more than
= PotentialCoalitionsλ(party,seats,122)
which gave rise to
I am happy to accept any feedback. It is, after all, well away from looking like a traditional spreadsheet.
24 Replies
- Balint79Brass Contributor
no words, what i have been through, despite thankful 🙂
=LET( weight;{75\74\43\19\12\5\4}; binary;DEC2BIN(DROP(SEQUENCE(POWER(2;7));-1);7); factor;MID(binary;SEQUENCE(1;7);1)*1; votes;BYROW(weight*factor;LAMBDA(r;SUM(r))); votemin;BYROW(weight*factor;LAMBDA(r;MIN(SUBSTITUTE(r;"0";"99")*1))); detailed;HSTACK(binary;votes;votemin;(votes>121)*((votes-votemin)<122)); summary;FILTER(detailed;CHOOSECOLS(detailed;4)); header;{"involved"\"votesum"\"kingmaker"\"coalitions"}; divider;{"¤"\"¤"\"¤"\"¤"}; VSTACK(header;SORT(summary;2;1);divider;detailed))
- Balint79Brass ContributorPeterBartholomew1
you are (all) amazing for sure. wanted to impress you with a new approach solution but deadlocked myself into complexity. then at least some (hopefully) interesting conclusions for the next day when your manager in Governor's office ask back that "...ok great, but then what?" and you realise that the traveling agent problem came into the game as well. meaning that which party should send negotiators to where and first?
#1
RJD>>BJP
of course the first meeting can quickly close the coalition negotations
#2
RJD>>JDU
BJP>>JDU
decisive two meetings parallel. the top2 party, which is failing to cooperate with JDU, will surely fall out from coalition.
#3 (RJD)
RJD&JDU>>VSIP
now looking for the satellites, RJD&JDU core should agree with the most little party, which should be the "easiest" regarding the compromises made
#4 - #6 (RJD)
RJD&JDU>>AIMIM
RJD&JDU>>CPIML
RJD&JDU>>INC
if none of those talks is successful, then RJD wont be part of a coalition
#3 - #5 (BJP)
BJP&JDU>>AIMIM
BJP&JDU>>CPIML
BJP&JDU>>INC
the same as at #4 - #6 (RJD), with a tiny difference, that BJP will be never in coalition talks with VSIP, without a working constellation. with other words it is unnecessary to send negotiators from BJP to VSIP- PeterBartholomew1Silver Contributor
Not quite a travelling salesman in that there is no obligation to visit all the parties? That said, my calculations were intended to support the kind of analysis that you have provided. I couldn't go further without knowing more about the internal politics of Bihar state.
- Balint79Brass Contributor
correct, however you do not have to know politics for such analysis as even salesmen did not know anything about Bernoulli's principle. regarding the rules it became just more exciting, as salesmen might have the chance to visit a place in the morning hours where they could sell all their stuff and finish for that day. such option would be definitely alluring to them. also any preliminary info about places to avoid (like Old Order Amish) due to less sales chances. hope you noticed that do not want to convince you, it is just about playing with rules via combining unexpected factors, eg is the smiley within the cube or not...?
⌜ ⌝
⌜ ⌝
. (: ⌟⌞ ⌟
- Patrick2788Silver Contributor
I've used BITXOR and BITAND very sparingly and I've played with BITLSHIFT and BITRSHIFT. I understand what the functions do but have not used them enough to the point where I can conceptualize a solution for combinations/permutations. I'll study your solution provided to see where I can find ways to make use of these functions.
My current way of tackling this task is with the help of DEC2BIN. I understand the limitations involved but for 127 possibilities it's more than up to the task (for much more than 127 perhaps Python is the best option.)
'GenerateCombinations =LAMBDA(party,seats,combinations,LET( header, HSTACK(TOROW(party), "Seats"), n, COUNT(seats), seq, SEQUENCE(n), combinations, SUM(COMBIN(n, seq)), BIN_vector, DEC2BIN(SEQUENCE(combinations), n), height, ROWS(BIN_vector), GetSeats, LAMBDA(r, c, LET( bin_val, MID(INDEX(BIN_vector, r), c, 1), seat_total, INDEX(seats, c), bin_val * seat_total ) ), SeatMatrix, MAKEARRAY(height, n, GetSeats), CoalitionSeats, BYROW(SeatMatrix, SUM), CoalitionMatrix, FILTER(HSTACK(SeatMatrix, CoalitionSeats), CoalitionSeats >= required), Results, SORT(CoalitionMatrix, n + 1), VSTACK(header, Results) ))
- PeterBartholomew1Silver Contributor
"but for 127 possibilities it's more than up to the task
(for much more than 127 perhaps Python is the best option)"
I wouldn't give up on the Excel formula language that easily. BASE is good for numbers up to 2^53! Mind you, I had never noticed that DEC2BIN has a 'places' parameter, so I could have used it.
I first saw it when lori_m used it for a Chandoo minimum length formula challenge. My recollection is that it was a case of multiplying by 37 in base 36 to double up the letter encoding a value.
- lori_mIron Contributor
Peter - you have a better memory than me, it was only after ten minutes of searching I found this (Code Golf) formula for checking if a string contains a repeated character:
=COUNT(SEARCH(BASE(({0,1,2,3,4,5}+{0;1;2;3;4;5}*6)*37,36,2),A1))>0
I remember avoiding the dreaded CSE entry and unnecessary range dependencies introduced by ROW, etc. were an integral part of such challenges. Things are much more straightforward these days - Excel formulas being a bone fide language and all - though maybe not quite as fun 🙂
( https://dhexcel1.wordpress.com/2017/10/03/boolean-formula-for-repetitive-characters-in-a-string/ )
- PeterBartholomew1Silver Contributor
Confession.
I have changed the code that checks whether a given proposed coalition contains a smaller viable coalition. Originally I worked with arrays of the form {1,1,0,0,1,0,1} to check the subset condition and that required nested MAPs which were not pretty. Since BITXOR and BITAND work with the decimal representation (i.e. scalars rather than arrays) that part could be simplified.
HasSubsetλ "Tests whether each of an array of sets is a superset of the others" = LET( q, TRANSPOSE(p), s, SIGN(IF(p <> q, BITAND(BITXOR(p, q), q) = 0)), BYROW(s, LAMBDA(x, SUM(x))) > 0 )
Sadly, settling for the first thing that works has its shortcomings.
- lori_mIron Contributor
Looks like a nice approach, I'd like to make time to check this out in more detail. It does makes me think a lambda function for generating combinations, like the one in Python, would make for a useful utility function and worth looking at as a future challenge.
On the subject of more obscure functions, I have seen specialised financial functions such as DOLLARFR and even ODDFYIELD employed in the context of treasury yield computations. Bitwise functions are also fairly niche in my experience but become more useful in lambda development where one is looking to optimise algorithms for example replacing array comparisons with bitwise operations. One application I have found myself reusing on multiple occasions is in generating (pseudo-)random data but removing volatility e.g. for benchmarking or speeding up recalc
=LAMBDA(length, [seed], TAKE( SCAN( IF(ISOMITTED(seed), 123456789, seed), SEQUENCE(length, , , 0) * {13, -17, 5}, LAMBDA(s, i, BITXOR(s, BITAND(BITLSHIFT(s, i), 2 ^ 32 - 1))) ), , -1 ) )(5)
- m_tarlerBronze Contributorooooh pseudo-random number. I totally thing Excel should add [seed] to RAND() and all of its 'sister' functions. That said I created my own pseudo-rand number generator (very primitive but fine for most non-scientific work) and will have to compare it to the option you give here.
I have seen many good options for pseudo-rnd numbers here on the forum when people ask to create 'random' lists for work schedules or baseball call sheets or tournement lists, etc... Having a SEED value based on the date, or week, or whatever will give them that random feel but not change every time they re-open the sheet. thx for sharing.
- SergeiBaklanDiamond Contributor
Combinations is too complex for me, make the bookmark to play one day.
As for the binary logic long ago I used it to check if the character is in English alphabet or in digits
ABC = LAMBDA(chr, IFERROR( BITOR(chr, 48), IFERROR(CHAR(BITXOR(CODE(chr), 32)) = chr, 0) ) )
and only to play with it, sure could be done other way. No more practical cases in my practice.
- PeterBartholomew1Silver Contributor
Even that is more than I had expected! I had definitely regarded BITXOR as lying within an exotic but very obscure corner of Excel. Perhaps not as bad as a Bessel function of the second kind, but close. Mind you, the finance formulas have their oddities; DOLLARFR means very little to me!
Presumably the trick in your formula is to move from lower case characters to upper case and the converse.