# Sort useless characters

This challenge is inspired by this very nice answer by TidB.

In TidB's answer, every eight character is in the correct order: gnilwoB edoC (Code Bowling backwards). The other strings however are were in a strange, random order.

Your challenge is to fix this.

Take a (non-empty) string and a positive integer n as input. The string will contain ASCII characters in the range: 32-126 (space to tilde).

You must sort the string in ascending order (seen from the left, based on the ASCII-code value), but skip every nth character, starting from the end of the string. As an example, let's take the string abcdABC123 as input, and n=4, then we'll get:

abcdABC123   <- Input string. (n=4)
_b___B___3   <- These will not be sorted (every 4th starting from the end)
1_2AC_acd_   <- The remaining characters, sorted
1b2ACBacd3   <- The final string (the output)

Another example:

9876543210   <- Input string (n=2)
_8_6_4_2_0   <- These will not be sorted
1_3_5_7_9_   <- The remaining characters, sorted
1836547290   <- The final string (the output)

The input string can be taken on an optional format (string, list of characters, list of single character strings ...). The input integer can also be taken on an optional format.

Test cases:

The format will be n=__, followed by the input string on the next line. The output is on the line below.

n=1   (All elements will stay in place)
nafgaksa1252#"%#
nafgaksa1252#"%#

n=214  (The last character will stay in place. All other are sorted.
&/lpfAVD
&/AVflpD

n=8
g7L9T E^n I{><#ki XSj!uhl y= N+|wA}Y~Gm&o?'cZPD2Ba,RFJs% V5U.W;1e  0_zM/d$bH@vKoQ 43Oq*C g n !#$%&'i*+,./01l234579;w<=>?@ADoEFGHIJKBLMNOPQR STUVWXYeZ^_abcdhjkmqsuovyz{|}~C

# MATL, 15 14 bytes

ttfiX\qgP)S5M(

Inputs are a string enclosed in single quotes and a number. Single-quote symbols in the string should be escaped by duplicating (as in MATLAB and Octave).

### Explanation

Consider inputs 'abcdABC123' and 4.

tt     % Implicitly input string. Duplicate twice
% STACK: 'abcdABC123', 'abcdABC123', 'abcdABC123'
f      % Find: indices of nonzero elements: gives [1 2 ... n] where n is input length
% STACK: 'abcdABC123', 'abcdABC123', [1 2 3 4 5 6 7 8 9 10]
i      % Input n
% STACK: 'abcdABC123', 'abcdABC123', [1 2 3 4 5 6 7 8 9 10], 4
X\     % 1-based modulo
% STACK: 'abcdABC123', 'abcdABC123', [1 2 3 4 1 2 3 4 1 2 3 4]
qg     % Subtract 1, convert to logical: gives true (1) for 1, false (0) otherwise
% STACK: 'abcdABC123', 'abcdABC123', [0 1 1 1 0 1 1 1 0 1]
P      % Flip
% STACK: 'abcdABC123', 'abcdABC123', [1 0 1 1 1 0 1 1 1 0]
)      % Use as logical index into the string
% STACK: 'abcdABC123', 'acdAC12'
S      % Sort
% STACK: 'abcdABC123', '12ACacd'
5M     % Push logical index again
% STACK: 'abcdABC123', '12ACacd', [1 0 1 1 1 0 1 1 1 0]
(      % Write into original string as specified by the index. Implicitly display
% STACK: 1b2ACBacd3

1-based modulo means that mod([1 2 3 4 5], 3) gives [1 2 3 1 2] instead of the usual (0-based) [1 2 0 1 2]. This is needed here to handle the case n=1 adequately.

• I wish 05AB1E had that last command... – mbomb007 Mar 15 '17 at 20:55

# PHP, 101 bytes

negative string indexes (PHP 7.1) save 21 bytes - and possibly the day:

for([,$s,$n]=$argv;a&$c=$s[$i-=1];)$i%$n+1?$a[]=$c:0;for(sort($a);++$i;)echo$i%$n+1?$a[+$k++]:$s[$i];

Run with php -nr '<code>' '<string>' <N>.

breakdown

for([,$s,$n]=$argv; # import command line arguments to$s and $n a&$c=$s[$i-=1];)    # loop backward through string
$i%$n+1?$a[]=$c:0;      # if index is not n-th, copy character to array
for(sort($a); # sort array ++$i;)              # loop forward through string:
echo$i%$n+1             # if index is not n-th
?$a[+$k++]              # print character from array
:$s[$i]                 # else print character from string
;
• why $i-=1 and not$i-- ? – Jörg Hülsermann Mar 15 '17 at 16:26
• @JörgHülsermann Because $i-- doesn´t work if$i is NULL. – Titus Mar 15 '17 at 18:18

# Perl 5, 94 bytes

88 bytes of code + -F -pl flags.

$_=join"",(map{(--$i%$n?"":$F[$#F-$i--]),$_}sort grep$i++%$n,reverse@F),chop if($n=<>)>1

Try it online!

It's quite too long in my opinion, but already not that ugly... I'm still trying to golf it further anyway.

# Jelly, 14  13 bytes

FṢṁ
ṚsṚµḢ€ż@Ç

Full program that prints the string to STD out*.

Try it online!

### How?

ṚsṚµḢ€ż@Ç - Main link: string s, non-negative number n
Ṛ         - reverse s
s        - split into chunks of size n
Ṛ       - reverse the resulting list
µ      - monadic chain separation (call that list x)
Ḣ€    - head €ach - yield a list of the first entries of each of x and modify x
Ç - call the last link (1) as a monad - get the sorted and re-split list
ż@  - zip together (with reversed @rguments)

FṢṁ - link 1, sort and reshape like self: list of lists
F   - flatten into a single list
Ṣ  - sort
ṁ - mould the result like the input

I can't help but think there is a way to use the fact that modifies its input

* for a function one would want to flatten the output into a single list with F.
For example an input of "abcdABC123", 4 yields:
[[['1'],['b']],[['2','A','C'],['B']],[['a','c',',d'],['3']]]
rather than:
['1','b','2','A','C','B','a','c',',d','3']

# Python + NumPy, 115 114 bytes

from numpy import *
def f(x,n):l=len(x);x=array(x);m=[1<2]*l;m[-1::-n]=[1>2]*len(m[0::n]);x[m]=sort(x[m]);return x

Takes a regular Python list as input (wasn't sure whether taking an array would be considered kosher); returns a NumPy array containing the result.

Works by masking out the relevant indices and sorting the rest.

## Python 2, 119 113 bytes

n,l=input()
i=range(len(l))
print"".join(sorted(l[~a]for a in i if a%n)[-a+a/n]if a%n else l[~a]for a in i)[::-1]

Builds a list of all characters to be sorted, sorts them and merges them for printing, while avoiding some of the reversing via negative indexing.

• print"".join(sorted(l[~a]for a in i if a%n)[-a+a/n]if a%n else l[~a]for a in i)[::-1] saves 5 bytes – TidB Mar 16 '17 at 9:26
• @TidB Thanks, almost eliminated the scrollbar! (Apparantly there was a trailing newline involved in my previous count, therefore it seems to be 113 now instead of 114.) – moooeeeep Mar 16 '17 at 10:25

# Ruby, 64 bytes

Uses regex to grab all irrelevant characters, both for replacement and for sorting.

->i,s,j=-1{s.gsub(r=/.(?!(?=.{#{i}})*\$)/){s.scan(r).sort[j+=1]}}

Try it online