Inspired by this Stack Overflow question: Sorting a list: numbers in ascending, letters in descending. Your task is to solve the following problem and, as this is , you should do so in as few as bytes as possible.

You should take a list of objects as input containing letters (any reasonable form: string, char, etc) and numbers. You should then sort the numbers into ascending order and the letters into descending order. However, you should keep letters in letter positions and numbers in number positions. For example, if the list is:

[L, D, L, L, D, L]

The output list should be in the form of:

[L, D, L, L, D, L]


Input: ['a', 2, 'b', 1, 'c', 3]

  • Sort the numbers into ascending order: [1, 2, 3]
  • Sort the letters into descending order: ['c', 'b', 'a']
  • Join them back but keep the order the same: ['c', 1', 'b', 2, 'a', 3]


  • The list will only contain letters and digits.
  • The list may be empty.
  • The list may only contain letters or only digits.
  • If your language does not support mixed type arrays you may use digit characters instead of numbers. Note that if your language does support this you must use mixed types.
  • Letters will only be [a-z] or [A-Z], you may choose which one.
  • Letters are sorted as a being lowest, z being highest i.e. a = 1, z = 26.
  • Standard loopholes are forbidden.
  • I/O may be by any standard means including as a string.

Test cases

[5, 'a', 'x', 3, 6, 'b'] -> [3, 'x', 'b', 5, 6, 'a']

[ 3, 2, 1] -> [ 1, 2, 3 ]

[ 'a', 'b', 'c' ] -> [ 'c', 'b', 'a' ]

[] -> []

[ 2, 3, 2, 1 ] -> [1, 2, 2, 3]

As this is the shortest answer in bytes wins!

  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$ Sep 3, 2017 at 13:51

30 Answers 30


Python 2, 53 52 51 bytes

-2 bytes thanks to g.rocket
-1 byte thanks to Jonathan Frech
-1 byte thanks to RootTwo

def F(x):n=sorted(x);print[n.pop(-(e>x))for e in x]

Try it online!

The sorted list will have the numbers first and then the chars like [3, 5, 6, 'a', 'b', 'x'], then use e>x to filter what is number and what is char, in python any number is less than a list (input) and a list is less than a string.

  • \$\begingroup\$ This version fails with IndexError: pop index out of range. The former solution did work. \$\endgroup\$
    – Mr. Xcoder
    Aug 9, 2017 at 11:28
  • \$\begingroup\$ This works though, with 55 bytes too. 1-(e<'`') should be (e<'`')-1. You just placed them in the wrong order. BTW, you ninja'd me :/ I had this \$\endgroup\$
    – Mr. Xcoder
    Aug 9, 2017 at 11:30
  • 2
    \$\begingroup\$ Save two with e>x \$\endgroup\$ Aug 10, 2017 at 1:16
  • 1
    \$\begingroup\$ Think you can save another one with n.pop(-(e>x)) \$\endgroup\$
    – RootTwo
    Aug 10, 2017 at 6:09
  • 1
    \$\begingroup\$ @RootTwo That does the opposite of the intended behavior. \$\endgroup\$
    – LyricLy
    Aug 10, 2017 at 7:09

APL (Dyalog), 27 26 bytes

Expects characters to be uppercase


Try it online!

This is just two applications of the form f@g, apply the function f on the items indicated by g.

For the first application we use:
f: ⍒⊃¨⊂ the descending grades () each pick (⊃¨) from the entire argument ().
g: (e←∊∘⎕A) members () of () the Alphabet (⎕A), and store () this function as e.

For the second application we use:
f: ⍋⊃¨⊂ the ascending grades () each pick (⊃¨) from the entire argument ().
g: (~e) not (~) members of the alphabet (e; the function we stored before)

  • \$\begingroup\$ I think this needs to cover for all integers, so replace the second filter with 83=⎕DR¨⍵ \$\endgroup\$
    – Uriel
    Aug 9, 2017 at 11:14
  • \$\begingroup\$ @Uriel Doesn't actually seem to be a requirement, but did save a byte. Also, ⎕DR is not universally 83 for numbers, only for small integers. \$\endgroup\$
    – Adám
    Aug 9, 2017 at 11:47
  • \$\begingroup\$ is it always 3=10|⎕DR for integers? \$\endgroup\$
    – Uriel
    Aug 9, 2017 at 12:13
  • \$\begingroup\$ @Uriel Yes: 0=UnicodeChar, 1=Boolean, 2=ClassicChar, 3=int, 5=float, 6=pointer, 7=decimal, 9=complex. ⌊0.1×⎕DR gives you the number of bits used to represent each scalar, except for pointers, which depend on the architecture but always are 326. Thus, all numbers are 2|⎕DR. \$\endgroup\$
    – Adám
    Aug 9, 2017 at 12:18

Retina, 10 bytes


Try it online!

The O stage in Retina can directly perform the kind of selective sorting required by this challenge.

Here the first line sorts digits while the second line sorts non-digits in reverse.


JavaScript (ES6), 71 51 47 bytes

Saved 20 bytes by just using sort(), as suggested by @JustinMariner
Saved 4 more bytes thanks to @CraigAyre

Using a similar approach as Rod's Python answer:


Test cases

let f =


console.log(JSON.stringify(f(['a', 2, 'b', 1, 'c', 3]))) // -> ['c', 1', 'b', 2, 'a', 3]
console.log(JSON.stringify(f([5, 'a', 'x', 3, 6, 'b']))) // -> [3, 'x', 'b', 5, 6, 'a']
console.log(JSON.stringify(f([3, 2, 1]))) // -> [ 1, 2, 3 ]
console.log(JSON.stringify(f(['a', 'b', 'c']))) // -> [ 'c', 'b', 'a' ]
console.log(JSON.stringify(f([]))) // -> []
console.log(JSON.stringify(f([2, 3, 2, 1]))) // -> [1, 2, 2, 3]

  • \$\begingroup\$ Am I missing something or couldn't you remove the whole sort function and just use sort() on its own? It seems to sort in the same way without a function (in Chrome/FF/Edge). \$\endgroup\$ Aug 9, 2017 at 19:05
  • \$\begingroup\$ @JustinMariner At first, I thought the numeric values could be numbers -- in which case a simple sort() would fail. But since we're limited to digits, you are correct: that does work. Thanks! \$\endgroup\$
    – Arnauld
    Aug 9, 2017 at 19:12
  • 1
    \$\begingroup\$ Nice solution, could you shift/pop on a.sort() each loop instead of assigning to x?: .map(n=>a.sort()[1/n?'shift':'pop']()) \$\endgroup\$
    – Craig Ayre
    Aug 9, 2017 at 19:50
  • \$\begingroup\$ @CraigAyre Good catch! \$\endgroup\$
    – Arnauld
    Aug 9, 2017 at 20:00
  • \$\begingroup\$ I'm pretty sure +n can be used instead of 1/n \$\endgroup\$ Aug 10, 2017 at 22:56

R, 83 76 bytes

-7 bytes thanks to Miff


This is the same as the below, but it allows for mixed-type input as a list rather than an atomic vector (which would typecast everything as characters with mixed types).

Try it online!

R, 68 61 bytes

-7 bytes thanks to Miff


Anonymous function. All digits are cast to characters in this case. n[-d] is the array without the digits. Returns NULL (empty list) on empty input.

Try it online!

  • \$\begingroup\$ You can shave off a few characters with d=n%in%0:9 \$\endgroup\$
    – Miff
    Aug 9, 2017 at 14:49

Japt, 18 15 bytes

Thanks @Shaggy for -3 bytes and for help fixing for arrays with 0s.

c ñc
®¤?Vv :Vo

First line is intentionally left blank.

Try it online! using -Q to view the formatted array.


First line is blank to avoid overwriting the input array.
[5, 'a', 'x', 3, 6, 'b']

c ñc

Make a copy by flattening (c) the input array, then sort (ñ) with strings represented by their char code (c). This is stored in V.
[3, 5, 6, 'a', 'b', 'x']


Then map the input array by the function...

¤?Vv :Vo

Turn numbers into binary strings (truthy) or strings into "" (falsy) (¤). If truthy, remove from the start of V (v), otherwise remove from the end (o).

  • \$\begingroup\$ 15 bytes \$\endgroup\$
    – Shaggy
    Aug 9, 2017 at 12:27
  • \$\begingroup\$ @Shaggy Nice, that's really clever. Thanks! \$\endgroup\$ Aug 9, 2017 at 12:32
  • \$\begingroup\$ You forgot to switch Vo and Vv around. I'm convinced there has to be a shorter way, without the ternary. \$\endgroup\$
    – Shaggy
    Aug 9, 2017 at 12:37
  • \$\begingroup\$ @Shaggy Oh, whoops. And yeah, just if o could remove from the beginning with negative values or something... \$\endgroup\$ Aug 9, 2017 at 12:40

JavaScript, 164 162 158 142 bytes

edit 1: 2 bytes less after removing a redundant assignment of v.

edit 2: 4 bytes less thanks to TheLethalCoder.

edit 3: 16 bytes less thanks to brilliant hints from Justin Mariner


It's my very first time in code-golf, so it can surely be improved... But still, worth a try.

The program performs a variant of selection sort, which only takes into account the values of the same type as the current one (swapping only a number and a number, or a letter and a letter)

Readable form:

            n(e=x[j])==n(w) && e<v==n(w) && (m=j,v=e)
  • \$\begingroup\$ for(j=i+1;j<l;j++) -> for(j=i++;++j<l;) and remove the increment in the outer loop. \$\endgroup\$ Aug 9, 2017 at 13:21
  • \$\begingroup\$ Welcome PPCG too! \$\endgroup\$ Aug 9, 2017 at 13:22
  • \$\begingroup\$ @TheLethalCoder if we increment the counters so early, we'll also need to change the lines where i and j are used... But the idea is really smart, I'll think how to make use of it anyway. \$\endgroup\$
    – mackoo13
    Aug 9, 2017 at 13:44
  • \$\begingroup\$ You can increment j as I suggested, I didn't see you use i further down just change x[i]=x[m] too x[i++]=x[m] \$\endgroup\$ Aug 9, 2017 at 13:49
  • \$\begingroup\$ Ah, sure... Why didn't I think of x[i++]=x[m]... Thanks! \$\endgroup\$
    – mackoo13
    Aug 9, 2017 at 13:56

Jelly, 9 bytes


Try it online!

Takes input as a flat array (Jelly typically treats strings as char arrays, so [5, 'a', 'x', 3, 6, 'b'] -> [5, ['a'], ['x'], 3, 6, ['b']]. The Footer flattens this array for you).

Similar to PurkkaKoodari's Jelly answer

How it works

OÞḢṪOƑ}?Ɱ - Main link. Takes an array A on the left
 Þ        - Sort by:
O         -   Ordinal
            This shuffles the strings to the end,
             sorting both the strings and the numbers
        Ɱ - Over each element E in A:
       ?  -   If statement:
    OƑ}   -     Condition: E is a number?
  Ḣ       -     Then: Pop and yield the first element of A sorted
   Ṫ      -     Else: Pop and yield the last element of A sorted

Jelly, 14 bytes


Try it online!

Basically a port of Rod's Python solution.


C++17 (gcc), 219 bytes

#include <variant>
#include <set>
using V=std::variant<char,int>;void f(V*a,V*b){std::set<V>S[2];for(V*c=a;c<b;++c)S[c->index()].insert(*c);auto
C=S->rbegin();auto N=S[1].begin();for(;a<b;++a)*a=(a->index()?*N++:*C++);}

Try it online!

Hardly competitive. But I must support mixed-type arrays? FINE.

Accepts an array of variants in range style, and modifies it in place. Copies the input into two sorted sets, and then back into the input/output array.

  • \$\begingroup\$ This is interesting. I wouldn't interpret "supporting mixed-type arrays" in this way. Otherwise, I'd have to use an array of void * in C ;) But, yes, interesting to see a solution jumping through such a hoop. \$\endgroup\$ Aug 10, 2017 at 13:08
  • \$\begingroup\$ You can save two bytes by removing the spaces in the #includes \$\endgroup\$ Aug 10, 2017 at 22:57

Japt, 9 bytes

I knew there had to be a (golfy) way to do this without any sort of conditional :)

Outputs an array of singleton arrays. Replace £ with c@ to output a flat array.


Try it

£=ñs)jÓXÎ     :Implicit input of array U
£             :Map each X (or flat map with c@)
 =            :  Reassign to U
  ñ           :    Sort by
   s          :      Converting to string if an integer, slicing if a string (which does nothing to the string if given no arguments)
    )         :  End reassignment
     j        :  Remove (mutating the original) and return the element at modular 0-based index
      Ó       :    Bitwise NOT of the negation of (i.e, decrement)
       XÎ     :    Sign of difference of X with -1 if an integer, last character if a string (resulting in 0 if an integer or -1 if a string)

Mathematica, 203 bytes


Try it online!


Pyth, 12 11 bytes


Try it online! or Try the Test Suite.


KSQm.(Kt<d\@  - Full program with implicit input.

KSQ           - Assign a variable K to the lexicographically sorted input.
   m          - Map over the input (with a variable d).
    .(K       - Pop the sorted list at this location:
       >\@    - If d is lexicographically lower than '@', at 0 (the first element). Else, at -1 (the last element).
  • \$\begingroup\$ Wait, you don't need to order the entire array, just split in two homogeneous arrays which each should be easily sortable. APL cannot sort mixed arrays either (yet), but I sort each type separately. \$\endgroup\$
    – Adám
    Aug 9, 2017 at 12:00
  • \$\begingroup\$ @Adám What do you mean by just split in two homogeneous arrays which each should be easily sortable? \$\endgroup\$
    – Mr. Xcoder
    Aug 9, 2017 at 12:00
  • \$\begingroup\$ As described in the OP's "Workthrough": 1. Make note of which elements are numeric and which are character. 2. Extract all numbers into a separate array and sort that. Do the same for the characters. 3. Put the sorted number back into the number slots. DO the same for the characters. \$\endgroup\$
    – Adám
    Aug 9, 2017 at 12:03
  • \$\begingroup\$ @Adám If the OP considers this invalid, I will do exactly what you said (This would result in a much, much longer approach) \$\endgroup\$
    – Mr. Xcoder
    Aug 9, 2017 at 12:04

Python, 145 139 130 bytes

6 bytes saved thanks to @officialaimm

9 bytes saved thanks to @Chris_Rands

g=lambda s,a:sorted(x for x in s if(type(x)==str)==a)
def f(s):l,n=g(s,1),g(s,0)[::-1];return[[n,l][type(x)==str].pop()for x in s]

Try it online!

  • \$\begingroup\$ 139 bytes \$\endgroup\$ Aug 9, 2017 at 11:46
  • \$\begingroup\$ type(x)==str would save some bytes over using isinstance(...) i think \$\endgroup\$ Aug 9, 2017 at 13:25
  • \$\begingroup\$ @Chris_Rands thanks! \$\endgroup\$
    – Uriel
    Aug 9, 2017 at 13:38

05AB1E, 17 bytes


Try it online!

SaJ               # Push 1 if letter 0 else, for all letters in string.
   ¹á{R           # Reverse sort letters from input.
       ¹þ{        # Regular sort digits from input.
          «       # Concatenate those two things.
           v      # For each letter in the sorted string...
            ya    # 0 if digit, 1 if letter.
              y.; # Replace first instance of 0/1 with digit/letter.

Using the sort-by closure actually was worse: Σ©Ç®ai0<*}}¹SaJsvyay.;


Haskell, 108 bytes

There may be shorter ways, but I just had to try it with the Lens library.

import Control.Lens
import Data.List
f x=x&i(<)id&i(>)reverse

I could define f to just be the composition of the two i invocations, but I'd still have to apply x to it to avoid a type error from the monomorphism restriction. Note that the type of f is Traversable t => t Char -> t Char so it can be used with Strings which are lists of Chars as well as with arrays of Chars.

Here are the test cases:

*Main> map f ["5ax36b","321","abc","","2321"]

Python 3, 77 bytes

This answer is based on the comment that says you can use '1', '2', etc if chars and digits are not comparable in the language. 'a' and 1 are not comparable in Python 3.

def f(s):x=sorted(s,key=lambda c:ord(c)-95);return[x.pop(-(c>'.'))for c in s]

q/kdb+, 54 53 bytes


{x[w,q]:asc[x w:(&)d],desc x q:(&)(~)d:-7=type@/:x;x}


q){x[w,q]:asc[x w:(&)d],desc x q:(&)(~)d:-7=type@/:x;x}(5;"a";"x";3;6;"b") / mixed list
q){x[w,q]:asc[x w:(&)d],desc x q:(&)(~)d:-7=type@/:x;x}3 2 1   / simple list
1 2 3
q){x[w,q]:asc[x w:(&)d],desc x q:(&)(~)d:-7=type@/:x;x}"abc"   / simple list
q){x[w,q]:asc[x w:(&)d],desc x q:(&)(~)d:-7=type@/:x;x}2 3 2 1 / simple list
1 2 2 3


Find the chars in the list, sort descending, find the longs in the list, sort them ascending, join to get a list of, e.g. ("x";"b";"a";3;5;6), then assign the sorted values back to their original positions in the list, e.g. at 0 3 4 1 2 5.

Golfing is just switching out q keywords (each, where and not) for their k equivalent (which requires them to be wrapped in brackets).

{x[w,q]:asc[x w:where d],desc x q:where not d:-7=type each x;x} / ungolfed
{                                                           ; } / lambda function with 2 statements
                                                 type each x    / return types of elements in mixed list
                                              -7=               / true where item is a long
                                            d:                  / save this bool array in d
                                        not                     / invert
                                  where                         / indices where true (we have chars)
                                q:                              / save these indices in q
                              x                                 / values of x at these indices
                         desc                                   / sort them descending
                        ,                                       / join/contatenate
                where d                                         / indices where we have digits
              w:                                                / save this in w
            x                                                   / values of x at these indices
        asc[           ]                                        / sort them ascending
 x[w,q]:                                                        / assign this list to x at indices w,q
                                                             x  / return x


  • -1 byte as don't need square brackets around desc

C (gcc), 125 113 110 bytes


Try it online!



    // slightly modified stupid bubblesort, this line in fact
    // does nested looping with a single for statement
    // (undefined behavior here, there's no sequence point between accesses to c,
    // so this could go wrong. Works with the gcc version on tio.)

        // determine whether the current b is a letter:

        // for doing anything, b and c must be the same "type":

            // when c > b for letter or c <= b for digit
            || *c>*b^!i

            // then swap
            && (i=*c,*c=*b,*b=i);


Letters are expected in uppercase.


PHP, 66 bytes:


takes input from command line arguments, prints a string. Run with -nr or try it online.

Yields a warning in PHP 7.1; replace a& with ""< to fix.


Mathematica, 107 bytes


C# (.NET Core), 171 bytes

a=>{var b=a.Where(x=>x is int).ToList();b.Sort();int i=0,j=0;return a.Select(x=>b.Contains(x)?b[i++]:a.Except(b).OrderByDescending(y=>y).ToList()[j++]);}

Byte count also includes:

using System.Linq;

Try it online!


a =>
    var b = a.Where(x => x is int).ToList(); // Filter to only ints and transform to list
    b.Sort();                                // Sort the list
    int i = 0, j = 0;                        // Create index counters
    return a.Select(x =>                     // Replace each input element with
                    b.Contains(x) ?          // If it is in list b:
                    b[i++] :                 // Get the next element from b
                    a.Except(b)              // Otherwise take input and filter out those in b
                     .OrderByDescending(x=>x)// Order them z to a
                     .ToList()[j++]);        // Get the next element

Perl 5, 107 + 1 (-n) = 108 bytes

y/][//d;@a=split/, /;@l=sort grep/\D/,@a;@d=sort grep/\d/,@a;@r=map{/\d/?pop@d:shift@l}@a;$"=", ";say"[@r]"

Try it online!


Ruby, 265 bytes

x.sort_by(&:to_s).select{|a| a.is_a?(String)}.zip(x.map.with_index {|a, i| a.is_a?(String) ? i : nil}.compact).each{|a,i| x[i] = a}
x.sort_by(&:to_s).select{|a| a.is_a?(Integer)}.zip(x.map.with_index {|a, i| a.is_a?(Integer) ? i : nil}.compact).each{|a,i| x[i] = a}

Try it online!

First timer here, My solution is definetly not the best one. But since this is my first answer, I thought in posting just for the fun of it.

Looking foward to see better Ruby answers, to see what is the best approach. I hope I improve in future answers =)


x = ["c", 1, "a", 3, "b", 2]

b = x.map.with_index {|a, i| a.is_a?(Integer) ? i : nil}.compact
s = x.map.with_index {|a, i| a.is_a?(String) ? i : nil}.compact

o = x.sort_by(&:to_s).select{|a| a.is_a?(Integer)}
d = x.sort_by(&:to_s).select{|a| a.is_a?(String)}

d.zip s
d.zip(s).each {|a, i| x[i] = a}

o.zip b
o.zip(b).each {|a, i| x[i] = a }

p x

Python 3, 91 bytes

def f(s):x=sorted(s,key=lambda c:(type(c)==str,c));return[x.pop(-(type(c)==str))for c in s]

Clojure, 151 bytes

#(map(fn[t c](nth((if(=(type 1)t)vec reverse)(sort((group-by type %)t)))(-(c t)1)))(map type %)(reductions(partial merge-with +)(for[i %]{(type i)1})))


(def f #( ... ))
(f [5 \a \x 3 6 \b])
; (3 \x \b 5 6 \a)

This calculates the cumulative sum count of integers and characters, and uses it to lookup the correct element from a sorted list of corresponding type's elements.


Zsh, 43 55 70 95 bytes

b=(${(n)@});for i;echo $b[$[#i>64?--k:++j]]

Try it online!   55bytes   70bytes   95bytes

Create a sorted array b, numbers first. Iterate over the arguments. If i is a letter (>ascii #64) then decrement k and print b[k], (e.g. b[-2] is the 2nd to last value). If i is a number, increment j and print b[j].

NB: Previously I forgot to decrease letters. Fixed now, and saved bytes!


Go, 290 bytes

func f(I[]any){J,K:=StringSlice{},IntSlice{}
var L,M[]int
for i,e:=range I{switch e:=e.(type){case string:J,L=append(J,e),append(L,i)
case int:K,M=append(K,e),append(M,i)}}
for i:=0;i<x+len(M);i++{if i<x{I[L[i]]=J[i]}else{I[M[i-x]]=K[i-x]}}}

Attempt This Online!


import."sort"                 // boilerplate
func f(I[]any){               // boilerplate
J,K:=StringSlice{},IntSlice{} // J and K store the actual elements
var L,M[]int                  // L and M store their indexes
for i,e:=range I{             // for each element,
switch e:=e.(type){           // switch on their type
case string:J,L=append(J,e),append(L,i) // put strings in J/L
case int:K,M=append(K,e),append(M,i)}}  // put ints in K/M
Sort(Reverse(J))              // sort J reversed (descending)
Sort(K)                       // sort K normally (ascending)
x:=len(L)                     //
for i:=0;i<x+len(M);i++{      // combined loop
if i<x{I[L[i]]=J[i]}          // put the strings back in
else{I[M[i-x]]=K[i-x]}}}      // put the ints back in

APL (Dyalog), 26 bytes


(uses ⎕IO=1)

Try it online!


05AB1E, 14 bytes


Try it online or verify all test cases.


{         # Sort the (implicit) input-list, which will put all sorted digits at the
          # front, and all sorted letters at the end
 I        # Push the input-list again
  v       # For-each over its items `y`:
   ydi    #  If the current character `y` is a digit:
      ć   #   Extract the head of the sorted-list; pop and push remainder-list and first
          #   item separated to the stack
       ˆ  #   Pop and add this first item to the global array
     ë    #  Else (it's a letter instead):
      ¤   #   Get the last item of the sorted list (without popping the list itself)
       ˆ  #   Pop and add this last item to the global array
        ¨ #   And then remove this last item from the list
  ]       # Close both the if-else statement and loop
   ¯      # And push the global array
          # (after which it is output implicitly as result)

Your Answer

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

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