39
\$\begingroup\$

Goal

Write a function or program sort an array of integers in descending order by the number of 1's present in their binary representation. No secondary sort condition is necessary.

Example sorted list

(using 16-bit integers)

  Dec                Bin        1's
16375   0011111111110111        13
15342   0011101111101110        11
32425   0111111010101001        10
11746   0010110111100010         8
28436   0000110111110100         8
19944   0100110111101000         8
28943   0000011100011111         8
 3944   0000011111101000         7
15752   0011110110001000         7
  825   0000000011111001         6
21826   0101010101000010         6

Input

An array of 32-bit integers.

Output

An array of the same integers sorted as described.

Scoring

This is code golf for the least number of bytes to be selected in one week's time.

\$\endgroup\$
11
  • 3
    \$\begingroup\$ You didn't explicitly mention, but does it need to be in descending order? \$\endgroup\$
    – Nick T
    Feb 19, 2014 at 4:12
  • 4
    \$\begingroup\$ You're right, I missed that. Everyone else has gone with descending, so we'll stick with that. \$\endgroup\$ Feb 19, 2014 at 7:19
  • \$\begingroup\$ I think the final number (21826) has been converted wrong. according to my Windows calculator, it's 0101 0101 0100 0010, not 0010 1010 1100 0010. \$\endgroup\$
    – Nzall
    Feb 19, 2014 at 9:04
  • \$\begingroup\$ Thanks for those corrections. That's weird about 21826 because I used Excel to convert the numbers to binary. I wonder about the rest now. \$\endgroup\$ Feb 19, 2014 at 22:02
  • \$\begingroup\$ Solution using assembly and popcount instruction? \$\endgroup\$
    – eiennohito
    Feb 20, 2014 at 5:57

77 Answers 77

28
\$\begingroup\$

J (11)

(\:+/"1@#:)

This is a function that takes a list:

     (\:+/"1@#:) 15342 28943 16375 3944 11746 825 32425 28436 21826 15752 19944
16375 15342 32425 28943 11746 28436 19944 3944 15752 825 21826

If you want to give it a name, it costs one extra character:

     f=:\:+/"1@#:
     f 15342 28943 16375 3944 11746 825 32425 28436 21826 15752 19944
16375 15342 32425 28943 11746 28436 19944 3944 15752 825 21826

Explanation:

  • \:: downwards sort on
  • +/: sum of
  • "1: each row of
  • #:: binary representation
\$\endgroup\$
3
  • 5
    \$\begingroup\$ @ak82 it's the ASCII version of APL \$\endgroup\$ Feb 19, 2014 at 14:59
  • 3
    \$\begingroup\$ @JanDvorak of sorts; there have been quite a few changes: jsoftware.com/papers/j4apl.htm (see Language section). \$\endgroup\$
    – mudri
    Feb 24, 2014 at 20:22
  • 3
    \$\begingroup\$ There's also \:1#.#: which saves a few bytes. \$\endgroup\$
    – miles
    Nov 4, 2016 at 12:35
17
\$\begingroup\$

JavaScript, 39

Update: Now shorter than Ruby.

x.sort(q=(x,y)=>!x|-!y||q(x&x-1,y&y-1))

40

x.sort(q=(x,y)=>x&&y?q(x&x-1,y&y-1):x-y)

Explanation:

q is a recursive function. If x or y are 0, it returns x-y (a negative number if x is zero or a positive number if y is zero). Otherwise it removes the lowest bit (x&x-1) from x and y and repeats.

Previous version (42)

x.sort(q=(x,y)=>x^y&&!x-!y+q(x&x-1,y&y-1))
\$\endgroup\$
4
  • \$\begingroup\$ This is really clever! I'm still trying to wrap my mind around it. \$\endgroup\$
    – mowwwalker
    Feb 20, 2014 at 21:35
  • \$\begingroup\$ Shouldn't ~y work instead of -!y? \$\endgroup\$
    – Toothbrush
    Feb 21, 2014 at 15:42
  • \$\begingroup\$ @toothbrush The ending condition is that x or y are 0, in which case the expression !x|-!y becomes non-zero. ~ doesn't really fit in since it's non-zero for many inputs (including zero) \$\endgroup\$
    – copy
    Feb 21, 2014 at 16:13
  • 1
    \$\begingroup\$ Can anyone help me in case a secondary sorting is required, please? \$\endgroup\$
    – Manu
    Apr 21, 2018 at 15:09
16
\$\begingroup\$

Ruby 41

f=->a{a.sort_by{|n|-n.to_s(2).count(?1)}}

Test:

a = [28943, 825, 11746, 16375, 32425, 19944, 21826, 15752, 15342, 3944, 28436];
f[a]
=> [16375, 15342, 32425, 11746, 28436, 28943, 19944, 15752, 3944, 21826, 825]
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Simple. Understandable. Short. Kudos for this solution. \$\endgroup\$ Feb 19, 2014 at 9:14
8
\$\begingroup\$

Python 3 (44):

def f(l):l.sort(lambda n:-bin(n).count('1'))
\$\endgroup\$
8
\$\begingroup\$

Common Lisp, 35

logcount returns the number of ‘on’-bits in a number. For a list l, we have:

(sort l '> :key 'logcount)
CL-USER> (sort (list 16375 15342 32425 11746 28436 19944 28943 3944 15752 825 21826) '> :key 'logcount)
;=> (16375 15342 32425 11746 28436 19944 28943 3944 15752 825 21826)

As a standalone function, and what I'll base the byte count on:

(lambda(l)(sort l'> :key'logcount))
\$\endgroup\$
7
\$\begingroup\$

Python 3, 90 77 72 67 characters.

Our solution takes an input from the command-line, and prints the number in descending order (67 chars), or ascending (66).

Descending order

print(sorted(input().split(),key=lambda x:-bin(int(x)).count("1"))) # 67

Thanks to @daniero, for the suggestion of using a minus in the 1's count to reverse it, instead of using a slice to reverse the array at the end! This effectively saved 5 characters.

Just for the sake of posting it, the ascending order version (which was the first we made) would take one character less.

Ascending order:

print(sorted(input().split(),key=lambda x:bin(int(x)).count("1"))) # 66

Thanks to @Bakuriu for the key=lambda x… suggestion. ;D

\$\endgroup\$
10
  • \$\begingroup\$ So 0 will always be a part of your output then; That's not correct. \$\endgroup\$
    – daniero
    Feb 19, 2014 at 2:01
  • \$\begingroup\$ I don't see anything in the question that prohibits me from inserting a value. \$\endgroup\$
    – Jetlef
    Feb 19, 2014 at 2:04
  • \$\begingroup\$ I do: "An array of the same integers sorted as described." ;) Besides, why not just use raw_input() and drop some characters? \$\endgroup\$
    – daniero
    Feb 19, 2014 at 2:17
  • 1
    \$\begingroup\$ @daniero fixed it. Switching to Python 3 (a Python 2 answer was already present, gotta be creative!) allows me to use input(), saving two characters (two are to be added because of the brackets required by print()). \$\endgroup\$
    – Jetlef
    Feb 19, 2014 at 2:30
  • \$\begingroup\$ You can drop the [] inside sorted. Also the output of this program is the number of 1s in the numbers in input sorted, but you should output the number you received in input, sorted using the number of 1s. Something like: print(sorted(input().split(), key=lambda x:bin(int(x)).count('1'))) would be correct. \$\endgroup\$
    – Bakuriu
    Feb 19, 2014 at 9:33
7
\$\begingroup\$

JavaScript [76 bytes]

a.sort(function(x,y){r='..toString(2).split(1).length';return eval(y+r+-x+r)})

where a is an input array of numbers.

Test:

[28943,825,11746,16375,32425,19944,21826,15752,15342,3944,28436].sort(function(x, y) {
    r = '..toString(2).split(1).length';
    return eval(y + r + -x + r);
});

[16375, 15342, 32425, 19944, 11746, 28943, 28436, 15752, 3944, 21826, 825]
\$\endgroup\$
8
  • \$\begingroup\$ Could you please tell how the .. works? My understanding is that if x = 5 then eval(x + r) becomes eval(5..toString(2).match(/1/g).length) which is, I suppose, invalid. Thanks. \$\endgroup\$ Feb 19, 2014 at 12:03
  • 1
    \$\begingroup\$ @GaurangTandon It is not. As you know, in JS everything except literals is an object. And numbers. So theoretically (and practically) you may get properties or call methods of any non-literal via dot notation, as you do 'string'.length or [1,2,3].pop(). In case of numbers you may do the same but you should keep in mind that after a single dot the parser will look for a fractional part of the number expecting a float value (as in 123.45). If you use an integer you should "tell" the parser that a fractional part is empty, setting an extra dot before addressing a property: 123..method(). \$\endgroup\$
    – VisioN
    Feb 19, 2014 at 12:17
  • 1
    \$\begingroup\$ You can save two bytes by stripping the zeros and treating the rest as a decimal number. Replace match(/1/g).length with replace(/0/g,""). \$\endgroup\$
    – DocMax
    Feb 19, 2014 at 20:16
  • \$\begingroup\$ @VisioN Thanks! Learnt a new thing. \$\endgroup\$ Feb 20, 2014 at 10:07
  • 1
    \$\begingroup\$ a.sort(function(x,y){r='..toString(2).match(/1/g).length';return eval(y+r+-x+r)}) \$\endgroup\$
    – l4m2
    May 16, 2018 at 11:02
6
\$\begingroup\$

Mathematica 30

SortBy[#,-DigitCount[#,2,1]&]&

Usage:

SortBy[#,-DigitCount[#,2,1]&]&@
                           {19944,11746,15342,21826,825,28943,32425,16375,28436,3944,15752}

{16375, 15342, 32425, 11746, 19944, 28436, 28943, 3944, 15752, 825, 21826}

\$\endgroup\$
6
\$\begingroup\$

k [15 Chars]

{x@|<+/'0b\:'x}

Example 1

{x@|<+/'0b\:'x}19944, 11746, 15342, 21826, 825, 28943, 32425, 16375, 28436, 3944, 15752

16375 15342 32425 28436 28943 11746 19944 15752 3944 825 21826

Example 2 (all numbers are 2^n -1)

{x@|<{+/0b\:x}'x}3 7 15 31 63 127

127 63 31 15 7 3
\$\endgroup\$
5
\$\begingroup\$

Mathematica 39

IntegerDigits[#,2] converts a base 10 number to list of 1's and 0's.

Tr sums the digits.

f@n_:=SortBy[n,-Tr@IntegerDigits[#,2]&]

Test Case

f[{19944, 11746, 15342, 21826, 825, 28943, 32425, 16375, 28436, 3944, 15752}]

{16375, 15342, 32425, 11746, 19944, 28436, 28943, 3944, 15752, 825, 21826}

\$\endgroup\$
1
  • \$\begingroup\$ I've grown fond of that (ab?)use of Tr[] in golfing code. \$\endgroup\$ Feb 19, 2014 at 2:06
5
\$\begingroup\$

Java 8 - 87/113 81/111 60/80 60/74/48 characters

This is not a complete java program, it is just a function (a method, to be exact).

It assumes that java.util.List and java.lang.Long.bitCount are imported, and has 60 characters:

void s(List<Long>a){a.sort((x,y)->bitCount(x)-bitCount(y));}

If no pre-imported stuff are allowed, here it is with 74 characters:

void s(java.util.List<Long>a){a.sort((x,y)->x.bitCount(x)-x.bitCount(y));}

Add more 7 characters if it would be required that it should be static.

[4 years later] Or if you prefer, it could be a lambda (thanks @KevinCruijssen for the suggestion), with 48 bytes:

a->{a.sort((x,y)->x.bitCount(x)-x.bitCount(y));}
\$\endgroup\$
13
  • \$\begingroup\$ Any reason why you can't do Integer.bitCount(x)<Integer.bitCount(y)?-1:1;? Do you need the -1,0,1 behavior? \$\endgroup\$
    – Justin
    Feb 19, 2014 at 5:02
  • \$\begingroup\$ Also, is it possible to replace the <Integer> with space? \$\endgroup\$
    – Justin
    Feb 19, 2014 at 6:38
  • \$\begingroup\$ You can also use Long, that save some space :) \$\endgroup\$ Feb 19, 2014 at 7:27
  • \$\begingroup\$ Also a.sort((x,y)->Long.bitCount(x)-Long.bitCount(y)); \$\endgroup\$ Feb 19, 2014 at 7:31
  • 1
    \$\begingroup\$ @KevinCruijssen Thanks. I'm so used that using a variable instance to call a static method is a bad practice that I ever forgot that the compiler accepts that. \$\endgroup\$ Feb 7, 2018 at 16:38
4
\$\begingroup\$

Python 2.x - 65 characters (bytes)

print sorted(input(),key=lambda x:-sum(int(d)for d in bin(x)[2:]))

That's actually 66 characters, 65 if we make it a function (then you need something to call it which is lamer to present).

f=lambda a:sorted(a,key=lambda x:-sum(int(d)for d in bin(x)[2:]))

Demo in Bash/CMD:

echo [16, 10, 7, 255, 65536, 5] | python -c "print sorted(input(),key=lambda x:-sum(int(d)for d in bin(x)[2:]))"
\$\endgroup\$
2
  • \$\begingroup\$ you can change sum(int(d)for d in bin(x)[2:]) to sum(map(int,bin(x)[2:])) \$\endgroup\$
    – Elisha
    Feb 19, 2014 at 9:46
  • 1
    \$\begingroup\$ or even: print sorted(input(),key=lambda x:-bin(x).count('1')) \$\endgroup\$
    – Elisha
    Feb 19, 2014 at 9:50
4
\$\begingroup\$

Matlab, 34

Input in 'a'

[~,i]=sort(-sum(dec2bin(a)'));a(i)

Works for nonnegative numbers.

\$\endgroup\$
4
\$\begingroup\$

C - 85 bytes (108 106 bytes)

Portable version on GCC/Clang/wherever __builtin_popcount is available (106 bytes):

#define p-__builtin_popcount(
c(int*a,int*b){return p*b)-p*a);}
void s(int*n,int l){qsort(n,l,sizeof l,c);}

Ultra-condensed, non-portable, barely functional MSVC-only version (85 bytes):

#define p __popcnt
c(int*a,int*b){return p(*b)-p(*a);}
s(int*n,int l){qsort(n,l,4,c);}         /* or 8 as needed */

  • First newline included in byte count because of the #define, the others are not necessary.

  • Function to call is s(array, length) according to specifications.

  • Can hardcode the sizeof in the portable version to save another 7 characters, like a few other C answers did. I'm not sure which one is worth the most in terms of length-usability ratio, you decide.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ sizeof l saves a byte. The horribly ugly #define p-__builtin_popcount( can help save another one. \$\endgroup\$
    – ugoren
    Feb 20, 2014 at 12:28
  • \$\begingroup\$ @ugoren Thanks for the tips! The preprocessor one is such a hack, I had no idea such a thing was possible. Sadly it does not work on MSVC, but every byte counts! \$\endgroup\$
    – Thomas
    Feb 21, 2014 at 3:42
  • \$\begingroup\$ 58 bytes \$\endgroup\$
    – ceilingcat
    Dec 8, 2023 at 11:20
4
\$\begingroup\$

PowerShell v3, 61 58 53

$args|sort{while($_){if($_-band1){1};$_=$_-shr1}}-des

The ScriptBlock for the Sort-Object cmdlet returns an array of 1's for each 1 in the binary representation of the number. Sort-Object sorts the list based on the length of the array returned for each number.

To execute:

script.ps1 15342 28943 16375 3944 11746 825 32425 28436 21826 15752 19944
\$\endgroup\$
5
  • \$\begingroup\$ it's work. How it work? How the magic '.' comes to 'based on the length of the array'? \$\endgroup\$
    – mazzy
    Nov 2, 2018 at 9:01
  • \$\begingroup\$ The '.' executes the scriptblock that comes after it. The sort command sorts based on the output of the outer scriptblock. I realize now that the inner scriptblock is not needed. see edit \$\endgroup\$
    – Rynant
    Nov 2, 2018 at 16:11
  • \$\begingroup\$ $f={ is redundant, while -> for, -band1-> %2, -des->-d and other golf tricks. It's clear. Can you explain how to work $args|sort{@(1,1,...,1)}? It's work! How the sort compares arrays without explicit .Count? where to read about it? Thanks! \$\endgroup\$
    – mazzy
    Nov 2, 2018 at 17:47
  • 1
    \$\begingroup\$ @mazzy, you're right, I removed the redundant bits now. It's the default sorting of the Sort-Object cmdlet. See: help Sort-Object -Parameter property I don't know where the default sorting property for types is defined, but for arrays it is Count or Length. \$\endgroup\$
    – Rynant
    Nov 2, 2018 at 18:23
  • \$\begingroup\$ Good guess. But $args|sort{while($_){if($_-band1){$_};$_=$_-shr1}}-des gives a wrong result. Therefore, it is not Count. It's very interesting. Thanks again. \$\endgroup\$
    – mazzy
    Nov 2, 2018 at 18:44
3
\$\begingroup\$

ECMAScript 6, 61

Assumes z is the input

z.sort((a,b)=>{c=d=e=0;while(++c<32)d+=a>>c&1,e+=b>>c&1},e-d)

Test data

[28943,825,11746,16375,32425,19944,21826,15752,15342,3944,28436].sort(
    (a,b)=>{
        c=d=e=0;
        while(++c<32)
            d+=a>>c&1,e+=b>>c&1
    },e-d
)

[16375, 15342, 32425, 11746, 19944, 28436, 28943, 15752, 3944, 21826, 825]

Thanks, toothbrush for the shorter solution.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I've just tried your solution, but it didn't work. It doesn't sort the numbers. \$\endgroup\$
    – Toothbrush
    Feb 19, 2014 at 16:33
  • \$\begingroup\$ @toothbrush woops. Thanks for catching that, should work now. \$\endgroup\$
    – Danny
    Feb 19, 2014 at 16:40
  • \$\begingroup\$ Great work! I like it. \$\endgroup\$
    – Toothbrush
    Feb 19, 2014 at 16:48
  • 1
    \$\begingroup\$ Only 61 bytes: z.sort((a,b)=>{c=d=e=0;while(++c<32)d+=a>>c&1,e+=b>>c&1},e-d) (and thanks for the up-vote). \$\endgroup\$
    – Toothbrush
    Feb 19, 2014 at 17:08
  • 1
    \$\begingroup\$ My solution is now the same size as yours! \$\endgroup\$
    – Toothbrush
    Feb 21, 2014 at 17:37
3
\$\begingroup\$

R, 132 96 94 88 84 75 73 53 51 bytes

-20 thanks to J.Doe's implementation -2 more thanks to Giuseppe

function(x)x[order(colSums(sapply(x,intToBits)<1))]

My original post:

pryr::f(rev(x[order(sapply(x,function(y)sum(as.double(intToBits(y)))))]))

Try it online!

I tried several different methods before I got down to this result.

Matrix Method: Created a two column matrix, one column with the input vector, one of the sum of the binary representation, then I sorted on the sum of binary.

function(x){m=matrix(c(x,colSums(sapply(x,function(y){as.integer(intToBits(y))}))),nc=2,nr=length(x));m[order(m[,2],decreasing=T),]}

Non-Matrix: Realized I could toss out the matrix function and instead create a vector of binary values, sum them, order them, then use the ordered values to reorder the input vector.

function(x){m=colSums(sapply(x,function(y){as.integer(intToBits(y))}));x[order(m,decreasing=T)]}

Minor Changes

function(x){m=colSums(sapply(x,function(y)as.double(intToBits(y))));x[order(m,decreasing=T)]}

More Minor Changes Converting entire thing to one line of code instead of two separated by a semicolon.

function(x)x[order(colSums(sapply(x,function(y)as.double(intToBits(y)))),decreasing=T)]

Sum Method Instead of adding the columns with colSums of the binary matrix created by sapply, I added the elements in the column before sapply "finished."

function(x)x[order(sapply(x,function(y)sum(as.double(intToBits(y)))),decreasing=T)]

Decreasing to Rev I really wanted to shorten decreasing, but R squawks at me if I try to shorten decreasing in the order function, which was necessary to get the order desired as order defaults to increasing, then I remembered the rev function to reverse a vector. EUREKA!!! The last change in the final solution was function to pryr::f to save 2 more bytes

function(x)rev(x[order(sapply(x,function(y)sum(as.double(intToBits(y)))))])
\$\endgroup\$
2
  • 1
    \$\begingroup\$ 53 bytes \$\endgroup\$
    – J.Doe
    Aug 31, 2018 at 18:39
  • 1
    \$\begingroup\$ 51 bytes improving on @J.Doe 's excellent golf! \$\endgroup\$
    – Giuseppe
    Aug 31, 2018 at 19:48
2
\$\begingroup\$

Haskell, 123C

import Data.List
import Data.Ord
b 0=[]
b n=mod n 2:b(div n 2)
c n=(n,(sum.b)n)
q x=map fst$sortBy(comparing snd)(map c x)

This is the first way I thought of solving this, but I bet there's a better way to do it. Also, if anyone knows of a way of golfing Haskell imports, I would be very interested to hear it.

Example

*Main> q [4,2,15,5,3]
[4,2,5,3,15]
*Main> q [7,0,2]
[0,2,7]

Ungolfed version (with explanations)

import Data.List
import Data.Ord

-- Converts an integer into a list of its bits
binary 0 = []
binary n = mod n 2 : binary (div n 2)

-- Creates a tuple where the first element is the number and the second element
-- is the sum of its bits.
createTuple n = (n, (sum.binary) n)

-- 1) Turns the list x into tuples
-- 2) Sorts the list of tuples by its second element (bit sum)
-- 3) Pulls the original number out of each tuple
question x = map fst $ sortBy (comparing snd) (map createTuple x)
\$\endgroup\$
4
  • \$\begingroup\$ would it be helpful to use the infix notation for mod, n`mod`2? It has the same precedence as multiplication and division. \$\endgroup\$ Feb 19, 2014 at 15:08
  • \$\begingroup\$ That wouldn't be too helpful for golfing reasons as far as I can see. I'd lose two spaces, but gain two backticks, right? \$\endgroup\$
    – danmcardle
    Feb 19, 2014 at 16:49
  • \$\begingroup\$ import Data.List;import Data.Ord;import Data.Bits;q=sortBy(comparing popCount) - 80C - or using your approach, import Data.List;import Data.Ord;b 0=0;b n=(mod n 2)+b(div n 2);q=sortBy(comparing b) - 86C \$\endgroup\$
    – bazzargh
    Feb 20, 2014 at 4:56
  • \$\begingroup\$ I tried avoiding imports entirely, best I could manage was 87C by golfing quicksort: b 0=0;b n=mod n 2+b(div n 2);q[]=[];q(a:c)=f((b a>).b)c++a:f((b a<=).b)c;f=(q.).filter \$\endgroup\$
    – bazzargh
    Feb 20, 2014 at 12:16
2
\$\begingroup\$

CoffeeScript (94)

Readable code (212):

sort_by_ones_count = (numbers) ->
  numbers.sort (a, b) ->
    a1 = a.toString(2).match(/1/g).length
    b1 = b.toString(2).match(/1/g).length
    if a1 == b1
      0
    else if a1 > b1
      1
    else
      -1

console.log sort_by_ones_count [825, 3944, 11746, 15342, 15752, 16375, 19944, 21826, 28436, 28943, 32425]

Optimized (213):

count_ones = (number) -> number.toString(2).match(/1/g).length
sort_by_ones_count = (numbers) -> numbers.sort (a, b) ->
  a1 = count_ones(a)
  b1 = count_ones(b)
  if a1 == b1 then 0 else if a1 > b1 then 1 else -1

Obfuscating (147):

c = (n) -> n.toString(2).match(/1/g).length
s = (n) -> n.sort (a, b) ->
  a1 = c(a)
  b1 = c(b)
  if a1 == b1 then 0 else if a1 > b1 then 1 else -1

Ternary operators are excessively long (129):

c = (n) -> n.toString(2).match(/1/g).length
s = (n) -> n.sort (a, b) ->
  a1 = c(a)
  b1 = c(b)
  (0+(a1!=b1))*(-1)**(0+(a1>=b1))

Too long yet, stop casting (121):

c = (n) -> n.toString(2).match(/1/g).length
s = (n) -> n.sort (a, b) ->
  a1 = c(a)
  b1 = c(b)
  (-1)**(a1>=b1)*(a1!=b1)

Final (94):

c=(n)->n.toString(2).match(/1/g).length
s=(n)->n.sort((a, b)->(-1)**(c(a)>=c(b))*(c(a)!=c(b)))
\$\endgroup\$
2
\$\begingroup\$

Smalltalk (Smalltalk/X), 36 (or maybe 24)

input in a; destructively sorts in a:

a sort:[:a :b|a bitCount>b bitCount]

functional version: returns a new sorted array:

a sorted:[:a :b|a bitCount>b bitCount]

there is even a shorter variant (passing the name or the function as argument) in 24 chars. But (sigh) it will sort highest last. As I understood, this was not asked for, so I don't take that as golf score:

a sortBySelector:#bitCount
\$\endgroup\$
2
\$\begingroup\$

PHP 5.4+ 131

I don't even know why I bother with PHP, in this case:

<?unset($argv[0]);usort($argv,function($a,$b){return strcmp(strtr(decbin($b),[0=>'']),strtr(decbin($a),[0=>'']));});print_r($argv);

Usage:

> php -f sortbybinaryones.php 15342 28943 16375 3944 11746 825 32425 28436 21826 15752 19944
Array
(
    [0] => 16375
    [1] => 15342
    [2] => 32425
    [3] => 28436
    [4] => 19944
    [5] => 11746
    [6] => 28943
    [7] => 3944
    [8] => 15752
    [9] => 825
    [10] => 21826
)
\$\endgroup\$
1
  • \$\begingroup\$ well, someone has to bother with PHP \$\endgroup\$
    – Einacio
    Feb 19, 2014 at 15:13
2
\$\begingroup\$

Scala, 58

def c(l:List[Int])=l.sortBy(-_.toBinaryString.count(_>48))
\$\endgroup\$
2
\$\begingroup\$

DFSORT (IBM Mainframe sorting product) 288 (each source line is 72 characters, must have space in position one)

 INREC IFTHEN=(WHEN=INIT,BUILD=(1,2,1,2,TRAN=BIT)), 
       IFTHEN=(WHEN=INIT,FINDREP=(STARTPOS=3,INOUT=(C'0',C'')))
 SORT FIELDS=(3,16,CH,D) 
 OUTREC BUILD=(1,2)

Just for fun, and no mathematics.

Takes a file (could be executed from a program which used an "array") with the integers. Before sorting, it translates the integers to bits (in a 16-character field). Then changes the 0s in the bits to nothing. SORT Descending on the result of the changed bits. Creates the sorted file with just the integers.

\$\endgroup\$
2
\$\begingroup\$

C

void main()
{
 int a[]={7,6,15,16};
 int b,i,n=0;
 for(i=0;i<4;i++)
 {  for(b=0,n=0;b<=sizeof(int);b++)
      (a[i]&(1<<b))?n++:n;   
    a[i]=n;
 }
 for (i = 1; i < 4; i++) 
  {   int tmp = a[i];
      for (n = i; n >= 1 && tmp < a[n-1]; n--)
         a[n] = a[n-1];
      a[n] = tmp;
  }    
}
\$\endgroup\$
1
  • 4
    \$\begingroup\$ Since this is a code golf competition, you should try to shorten your code. \$\endgroup\$
    – Timtech
    Feb 19, 2014 at 15:36
2
\$\begingroup\$

C#, 88 89

int[] b(int[] a){return a.OrderBy(i=>-Convert.ToString(i,2).Count(c=>c=='1')).ToArray();}

Edit: descending order adds a character.

\$\endgroup\$
2
\$\begingroup\$

Javascript 84

Inspired by other javascript answers, but without eval and regex.

var r=(x)=>(+x).toString(2).split('').reduce((p,c)=>p+ +c)
[28943,825,11746,16375,32425,19944,21826,15752,15342,3944,28436].sort((x,y)=>r(x)-r(y));
\$\endgroup\$
1
  • \$\begingroup\$ The question is code golf, please try to 'golf' your code: remove unnecessary whitespace and try to make your code as small as possible. Also, include a character count in your answer. \$\endgroup\$
    – ProgramFOX
    Feb 19, 2014 at 17:34
2
\$\begingroup\$

Javascript (82)

a.sort(function(b,c){q=0;while(b|c){b%2?c%2?0:q++:c%2?q--:0;b>>=1;c>>=1}return q})
\$\endgroup\$
2
\$\begingroup\$

Postscript, 126

Because list of values by which we sort is known beforehand and very limited (32), this task can be easily done even if there's no built-in for sorting, by picking matching values for 1..32. (Is it O(32n)? Probably).

Procedure expects array on stack and returns 'sorted' array.

/sort_by_bit_count {
    [ exch
    32 -1 1 {
        1 index
        {
            dup 2 32 string cvrs
            0 exch
            {48 sub add} forall
            2 index eq 
            {3 1 roll} {pop} ifelse
        } forall
        pop
    } for
    pop ]
} def

Or, ritually stripped of white space and readability:

/s{[exch 32 -1 1{1 index{dup 2 32 string cvrs 0 exch{48 sub add}forall 2 index eq{3 1 roll}{pop}ifelse}forall pop}for pop]}def

Then, if saved to bits.ps it can be used like this:

gs -q -dBATCH bits.ps -c '[(%stdin)(r)file 1000 string readline pop cvx exec] s =='
825 3944 11746 15342 15752 16375 19944 21826 28436 28943 32425
[16375 15342 32425 11746 19944 28436 28943 3944 15752 825 21826]

I think it effectively is the same as this Perl (there's yet no Perl here, too):

sub f{map{$i=$_;grep{$i==(()=(sprintf'%b',$_)=~/1/g)}@_}reverse 1..32}

Though that, unlike Postscript, can be easily golfed:

sub f{sort{j($b)-j($a)}@_}sub j{$_=sprintf'%b',@_;()=/1/g}
\$\endgroup\$
1
  • \$\begingroup\$ Postscript! My first love, my favorite language of all time! It is nice to see another believer in the One True Programming Language. \$\endgroup\$ Feb 25, 2014 at 2:40
2
\$\begingroup\$

C - 124 111

Implemented as a method and using the standard library for the sorting. A pointer to the array and the size should be passed as parameters. This will only work on systems with 32-bit pointers. On 64-bit systems, some characters have to be spent specifying pointer definitions.

Indentation for readability

c(int*a,int*b){
    int d,e,i;
    for(d=e=i=0;i-32;){
        d+=*a>>i&1;e+=*b>>i++&1;
    }
    return d>e?-1:d<e;
}
o(r,s){qsort(r,s,4,c);}

Sample call:

main() {
    static int a[] ={1, 2, 3, 4, 5, 6, 7, 8, 9};
    o(a, 9);
}
\$\endgroup\$
2
\$\begingroup\$

Java 8: 144

static void main(String[]a){System.out.print(Stream.of(a).mapToInt(Integer::decode).sorted(Comparable.comparing(Integer::bitCount)).toArray());}

In expanded form:

static void main(String[] args){
    System.out.print(
        Stream.of(args).mapToInt(Integer::decode)
              .sorted(Comparable.comparing(Integer::bitCount))
              .toArray()
        );
}

As you can see, this works by converting the args to a Stream<String>, then converting to a Stream<Integer> with the Integer::decode function reference (shorter than parseInt or valueOf), and then sorting by Integer::bitCount, then putting it in an array, and printing it out.

Streams make everything easier.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.