Find the "Bittiest" Number
x86 Machine Language, 18 bytes
31 D2 AD F3 0F B8 F8 39 FA 77 03 87 FA 93 E2 F2 93 C3
The above bytes define a function that accepts the address of the array in the
esi register and the number of elements in the array in the
ecx register, and returns the "bittiest" number in the array in the
Note that this is a custom calling convention that accepts arguments in the
esi registers, but it is otherwise much like a C function that takes the length of the array and a pointer to the array as its two arguments. This custom calling convention treats all registers as caller-save, including
The implementation of this function pulls some dirty tricks, which assume that the array has at least 1 element, as provided for in the challenge. It also assumes that the direction flag (
DF) is clear (
0), which is standard in all calling conventions that I'm aware of.
In ungolfed assembly-language mnemonics:
; ecx = length of array ; esi = address of first element in array Find: 31 D2 xor edx, edx ; start with max bit count set to 0 Next: AD lods eax, DWORD PTR [esi] ; load the next value from the array, and ; increment ptr by element size F3 0F B8 F8 popcnt edi, eax ; count # of set bits in value 39 FA cmp edx, edi ; if # of set bits in value is less than 77 03 ja SHORT Skip ; the running maximum, skip next 2 insns 87 FA xchg edx, edi ; save current # of set bits (for comparisons) 93 xchg eax, ebx ; save current array value (for comparisons) Skip: E2 F2 loop SHORT Next ; decrement element count, looping until it is 0 93 xchg eax, ebx ; move running maximum value to eax C3 ret ; return, with result in eax
The key feature of this code is, of course, the x86
popcnt instruction, which counts the number of set bits in an integer. It iterates through the input array, keeping track of both the value of the maximum element and the number of set bits that it contains. It checks each value in the array to see if its number of set bits is higher than any value it has seen before. If so, it updates the tracking values; if not, it skips this step.
popcnt instruction is a large (4-byte) instruction, but there's nothing that can be done to avoid that. However, the very short (1-byte)
lods instruction has been used to load values from the array while simultaneously incrementing the pointer, the short (2-byte)
loop instruction has been used for loop control (automatically decrementing the element counter and looping as long as there are more elements remaining to go through), and the very short (1-byte)
xchg instruction has been used throughout.
xchg had to be used at the end in order to enable use of the
lods instruction, which always loads into the
eax register, but that trade-off is more than worth it.
Try it online!
My first attempt was a 20-byte function. So far, 18 bytes is the best I have been able to come up with. I'm curious to see if anyone else can beat this score!
The only route of improvement that I see would be if a
LOOPA instruction existed. Unfortunately, it doesn't—the only condition codes supported by
NZ. But maybe someone else can stretch their mind further than me!
49 48 47 45 bytes
Saved 2 bytes thanks to @user81655
Try it online!
.sort() the input list with a recursive function that, given
q, clears the least significant bit set in each variable until one of them is equal to 0 (or both of them simultaneously). This allows to order the list from most to least bits set. We then return the first entry, i.e. the "bittiest" one.
a => // a = input list a.sort( // sort a ... g = (p, q) => // ... using the recursive function g: !p | -!q // -> +1 if p = 0 and q ≠ 0, // or -1 if q = 0, || // or 0 if p ≠ 0 and q ≠ 0, in which case ... g( // ... we do a recursive call: p & p - 1, // clear the least significant bit set in p q & q - 1 // clear the least significant bit set in q ) // end of recursive call ) // end of sort(); return the first entry
13 12 8 bytes
Try it online!
µÞ | sort input by %Ø% | modulo by 2^32 (Ø% is a quick for 2^32) B | converted to binary § | sum Ṫ | get the last
Edit: thank you all for the kind response to my first question! I think I've fixed it now, it seems to work for all test cases.