I am trying to write a function that given a list of non negative integers, arranges them such that they form the largest possible number.
For example, given
Here is an ugly solution that does work without passing a cmp
comparison function to the sorted
. Basically, the key function takes each number and calculates a rational number that has that number as the repeating decimals; that is
0 => 0
100 => 100/999 == 0.100100100...
10 => 10/99 == 0.1010101010...
1 => 1/9 == 0.1111111111...
11 => 11/99 == 0.1111111111...
12 => 12/99 == 0.1212121212...
9 => 9/9 == 1
99 => 99/99 == 1
999 => 999/999 == 1
The 0 is sorted the smallest with sort key 0, and 1 followed by most zeroes would have key closest to 0.1
, and thus sorted second smallest. Numbers that consist of digit 9 all have sort key equal to 1
; it does not really matter if you sort 9
before or after 99
.
Sorting using these values as the key will necessarily give the correct output, unless you use numbers that are too big for float precision. (probably much sooner than 2 ** 53
)
Thus we get the following program:
# for Python 2, not needed in Python 3
from __future__ import division
a = [50, 5, 51, 59, 2, 1, 9, 98]
def fractionalize(i):
divisor = 9
while divisor < i:
divisor = 10 * divisor + 9
return i / divisor
print(sorted(a, key=fractionalize, reverse=True))
Which produces
[9, 98, 59, 5, 51, 50, 2, 1]
As we're essentially calculating i / (10 ** ceil(log10(i + 1)) - 1)
here, one can also write the following oneliner:
from math import ceil, log10
print(sorted(a, key=lambda i: i and i/(10**ceil(log10(i+1))-1), reverse=True))
The i and
part guards for division by zero error, in case 0
is among the numbers.