Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Goal

Write a function or program sort an array of integers 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.

share|improve this question
2  
825 only has 6 bits set. –  marinus Feb 19 at 0:00
2  
You didn't explicitly mention, but does it need to be in descending order? –  Nick T Feb 19 at 4:12
3  
You're right, I missed that. Everyone else has gone with descending, so we'll stick with that. –  Hand-E-Food Feb 19 at 7:19
 
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. –  Nate Kerkhofs Feb 19 at 9:04
 
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. –  Hand-E-Food Feb 19 at 22:02
show 5 more comments

47 Answers

GolfScript, 14 chars

~{2base 0-,}$`

Example input (sorted in numerical order):

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

Example output (sorted by bit count) for the input above:

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

Note that the program above sorts the input in ascending order by bit count. If you insist on descending order, that'll cost one extra char:

~{2base 0-,~}$`

Explanation:

  • ~ evals the input. Since you didn't specify the input format, I took the liberty of assuming that the input is provided as a GolfScript array literal (i.e. a series of whitespace-separated numbers wrapped in [ ]).

  • { }$ applies the code inside the braces to each element of the array, and sorts them according to the resulting sort keys.

    • Inside the braces, 2base uses the built-in base conversion operator to turn the number into an array of bits (e.g. 19[1 0 0 1 1]). The 0- then removes all the zero bits from the array (the space before it is needed to keep base0 from being parsed as a single token) and the , counts the length of the remaining array.

    • (In the descending order version, the ~ then bitwise negates the count, effectively applying the map x ↦ −(x + 1) and thus inverting the sort order.)

  • Finally, the ` un-evals the sorted array, converting it back into the input format for output.

share|improve this answer
add comment

C++ and QT

template<typename T>

//Compars the number of ones in the binary representation of some numbers 
bool onesCountSort()(Const T* a, const T* b) const
{
   int aCount = getOnesCount(&a);
   int bCount = getOnesCount(&b);
   return aCount < bCount;
}

//Returns the number of ones in a number
int getOnesCount(T value) const
{
    int rVal = 0;
    while(value > 0)
    {
       rVal++;
       value = value >> 1;
    } 
    return rVal;
}    

int main(int argc, char *argv[])
{
   QList<int> listTest;
   listTest << 16375;
   listTest << 15342; 
   listTest << 32425; 
   listTest << 11746; 
   listTest << 28436;
   //...

   qSort(list.begin(); list.end(), onesCountSort<int>());//Sort by binary ones count
   qSort(list.end(); list.begin(), onesCountSort<int>());//Reverse the sort
}

Edit:

template<typename T>

//Compars the number of ones in the binary representation of some numbers 
bool onesCountSort()(Const T* a, const T* b) const
{
   return getOnesCount(a) < getOnesCount(b);
}

int getOnesCount(const T* value, int count = 0) const
{
    return &value ? count : getOnesCount(value >> 1, count + 1);
}        
share|improve this answer
add comment

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));
share|improve this answer
 
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. –  ProgramFOX Feb 19 at 17:34
add comment

C, 95 chars

Call s(array, size) to sort an array.
The framework is based on AShelly's answer, with a different bit count function.
Only works on 32bit platforms.

c(unsigned a){return a?a%2+c(a/2):0;}
f(int*a,int*b){return c(*b)-c(*a);}
s(a,n){qsort(a,n,4,f);}

The bit count function treats the numbers as unsigned, so division will discard the low bit.

share|improve this answer
add comment

**

C++(Visual Studio 2013), 112

**

#define n int
#define s __popcnt
n* d(n i[], n l){sort(i, i+l, [](n a, n b){return  s(a) > s(b); });return i;}

Unobfuscated:

#define n int
#define s __popcnt
n* d(n i[], n l){
    std::sort(i, i+l, [](n a, n b){return  s(a) > s(b); });
    return i;
}

haven't touched C++ for a while. While not the shortest, it PROBABLY is the fastest, by far, though it depends highly if the __popcnt is implemented as single CPU instruction, or set.

I might fire up mathbrain later and see if it's possible to compare two numbers by bits and see which one has more bits set(without any string conversions or bit counting). I think there is some kind of bit-hack that can be used, but it's probably longer.

share|improve this answer
add comment

K, 14

{x@>+/'0b\:'x}

.

k){x@>+/'0b\:'x} 28943 16375 15342
16375 15342 28943
share|improve this answer
add comment

php 5.3, 117 109

Thank to @mniip to point out some more char save. So New One are

usort($a,function($u,$v){return $u==$v?0:(substr_count(decbin($u),'1')<substr_count(decbin($v),'1')?1:-1);});

Older One

usort($a,function($u,$v){if($u==$v)return 0;return substr_count(decbin($u),'1')<substr_count(decbin($v),'1')?1:-1;});
share|improve this answer
 
I'm pretty sure you can save a few chars if you combine your return statements into one using ternary operator –  mniip Feb 20 at 10:42
add comment

C : 112

C(a){int c=a!=0;while(a&=a-1)c++;return c;}
B(int*a,int*b){return C(*b)-C(*a);}
S(int*a,int n){qsort(a,n,4,B);}

works on gcc with Target: x86_64-linux-gnu

usage: S(array, size);

share|improve this answer
 
similar to @albeert's answer, which I only saw after I completed this... –  AShelly Feb 20 at 4:15
 
S(n,int*a) doesn't compile. Even when fixed, doesn't work on by 64bit Linux with gcc. Omitting return from C is very fragile. –  ugoren Feb 20 at 9:38
 
Ah, you're right. I missed the compiler error among the warnings and got the same output as the previous run, so I assumed it was good. I went back to my last working version: +12 char. –  AShelly Feb 20 at 12:05
add comment

Javascript (ECMAScript 6) - 41 Characters

Takes an array a as input:

a.sort(ພ=(ຟ,ຝ)=>ຟ*ຝ?ພ(ຟ&ຟ-1,ຝ&ຝ-1):(ຝ-ຟ))

Testing (with less obfuscated code):

JSFIDDLE

a=[19944, 11746, 15342, 21826, 825, 28943, 32425, 16375, 28436, 3944, 15752];
a.sort(_=(b,c)=>b*c?_(b&b-1,c&c-1):(c-b))
console.log(a.toString());

Gives this output:

16375,15342,32425,19944,11746,28943,28436,3944,15752,21826,825
share|improve this answer
add comment

C#, 191 183 172 thanks to Rik

 using System.Linq;class P{static void Main(string[]a){System.Console.WriteLine(string.Join(" ",a.Select(int.Parse).OrderBy(v=>{int c=0;for(;v>0;c++,v&=v-1);return-c;})));}}

Formatted:

using System.Linq;
class P
{
    static void Main(string[] a)
    {
        System.Console.WriteLine(string.Join(" ", a.Select(int.Parse)
            .OrderBy(v => { 
                int c = 0; 
                for (; v > 0; c++, v &= v - 1);
                return -c; 
            })
        ));
    }
}

When run as foo.exe 32425 28943 28436 21826 19944 16375 15752 15342 11746 3944 825 the output is:

16375 15342 32425 28943 28436 19944 11746 15752 3944 21826 825

Including the bitcount:

16375   13
15342   11
32425   10
28943   8
28436   8
19944   8
11746   8
15752   7
3944    7
21826   6
825     5

As function only: 100 89 chars

...Which some seem to regard as correct too:

int[] v(int[]a){return a.OrderBy(v=>{int c=0;for(;v>0;c++,v&=v-1);return-c;}).ToArray();}

To use, call v() with an array of ints to be sorted by binary 1's count.

share|improve this answer
 
instead of OrderByDescending you can use OrderBy and return -c in your lambda and save 9 chars. –  Rik Feb 19 at 14:59
 
D'oh! Thanks! Why didn't I think of that?! :D Actually, it saves 10 since I don't need a space between return and -c :D –  RobIII Feb 19 at 15:08
add comment

C# - 98

C# can't really compete in "the smallest" category. Still fun, though :)

x.Select(i=>new{v=i,c=Convert.ToString(i,2).Count(c=>c=='1')}).OrderByDescending(a=>a.c);

Used:

var y = new [] {28943, 825, 11746, 16375, 32425, 19944, 21826, 15752, 15342, 3944, 28436}.Select(i=>new{v=i,c=Convert.ToString(i,2).Count(c=>c=='1')}).OrderByDescending(a=>a.c);
Console.WriteLine(y.Select(a => a.v.ToString()).Aggregate((s1,s2)=>s1+","+s2));

Result:

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

EDIT: .NetFiddle - http://dotnetfiddle.net/ahMMbq

share|improve this answer
add comment

C# 95

int[]o(int[]d){return d.OrderByDescending(v =>Convert.ToString(v,2).Sum(c =>c-'0')).ToArray();}
share|improve this answer
add comment

Haskell - 107100 (including sample list and main call) else 100-22=78

import Data.List
b 0=0
b n=mod n 2+b(div n 2)
c q=map snd$ sort$ zip(map b q)q
main=print$ c [1..100]

Result:

[1,2,4,8,16,32,64,3,5,6,9,10,12,17,18,20,24,33,34,36,40,48,65,66,68,72,80,96,7,11,13,14,19,21,22,25,26,28,35,37,38,41,42,44,49,50,52,56,67,69,70,73,74,76,81,82,84,88,97,98,100,15,23,27,29,30,39,43,45,46,51,53,54,57,58,60,71,75,77,78,83,85,86,89,90,92,99,31,47,55,59,61,62,79,87,91,93,94,63,95]
share|improve this answer
add comment

PHP - 89 bytes

Here is the best I have been able to do so far.

function f($a){usort($a,function($a,$b){$c=gmp_popcount;return$c($a)<$c($b);});return$a;}

If I am allowed to sort the array in-place (which is idiomatic for PHP), then it is only 81:

function f(&$a){usort($a,function($a,$b){$c=gmp_popcount;return$c($a)<$c($b);});}
share|improve this answer
add comment

Perl, 56 bytes

sub x{$_=sprintf'%b',@_;s/1//g}print sort{x($b)<=>x$a}<>

Input is expected in STDIN, one integer per line. Output is in descending order.

sprintf '%b' converts the number into binary representation. s/1// replaces the 1, the return value is the number of replacements. Thus function x returns the number of 1 in the binary representation of the number. The sorting function sorts the number according to their binary 1's count. By exchanging $a and $b the sorting order is reversed to ascending.

share|improve this answer
add comment

Longwinded C#:

using System;

namespace P
{
    class P
    {
        static int T(int v) { int i = 0; while (v != 0) { i += (v & 1); v >>= 1; } return i; }
        static int[] S(int[] a)
        { Array.Sort<int>(a, (x, y) => { return (T(x) > T(y)) ? -1 : (T(x) < T(y)) ? 0 : 1; }); return a; }
        static void Main(string[] args)
        {
            foreach (var i in S(new int[]{ 28943, 825, 11746, 16375, 32425, 19944, 21826, 15752, 15342, 3944, 28436 }))
                Console.WriteLine("{0}\t{1}\t{2}", i, Convert.ToString(i, 2), T(i));
            Console.ReadKey();
        }
    }
}
share|improve this answer
add comment

Python-40 bytes

l.sorted(key=lambda x:bin(x).count('1'))

second to K!! Thwarted by K once again.......

share|improve this answer
 
If l is a Python list, it has no sorted method. Perhaps you meant sort? Otherwise, your answer is practically a duplicate of another. Your sort delivers its results in ascending order, whereas descending was specified. Finally, you claim that your answer is second only to K, which is false. Too many problems to ignore. -1. –  Steven Rumbalski Feb 26 at 4:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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