16
\$\begingroup\$

Given a list of strings, output a single string formed by taking a character from each string at each position, sorting them by ASCII ordinal, and appending them in order to the output string. In other words, for n input strings, the first n characters of the output will be the first characters of each of the inputs sorted by ordinal, the second n characters of the output will be the second characters of each of the inputs sorted by ordinal, and so on. You may assume that the strings are all of equal length, and that there will be at least one string. All strings will be composed of only ASCII printable characters (ordinals 32-127).

Reference implementation in Python (try it online):

def stringshuffle(strings):
  res = ''
  for i in range(len(strings[0])):
    res += ''.join(sorted([s[i] for s in strings],key=ord))
  return res

Examples:

"abc","cba" -> "acbbac"
"HELLO","world","!!!!!" -> "!Hw!Eo!Lr!Ll!Od"

Rules

  • Standard loopholes are forbidden
  • This is , so shortest answer in bytes wins

Leaderboard

The Stack Snippet at the bottom of this post generates the leaderboard from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 290px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 64526; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 45941; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>

\$\endgroup\$
0

30 Answers 30

10
\$\begingroup\$

GS2, 4 bytes

*Ü■/

This reads the strings from STDIN, separated by linefeeds.

The source code uses the CP437 encoding. Try it online!

Test run

$ xxd -r -ps <<< '2a 9a fe 2f' > zip-sort.gs2
$ echo -e 'HELLO\nworld\n!!!!!' | gs2 zip-sort.gs2 
!Hw!Eo!Lr!Ll!Od

How it works

*       Split the input into the array of its lines.
 Ü      Zip the resulting array.
  ■     Map the rest of the program over the resulting array.
   /        Sort.
\$\endgroup\$
7
\$\begingroup\$

Haskell, 39 36 bytes

import Data.List
(>>=sort).transpose

Usage example: ((>>=sort).transpose) ["HELLO","world","!!!!!"] -> "!Hw!Eo!Lr!Ll!Od".

Transpose the list of strings, map sort over it and concatenate the resulting list of strings (>>= in list context is concatMap).

\$\endgroup\$
2
  • \$\begingroup\$ i came up with exactly this! \$\endgroup\$ Nov 23, 2015 at 17:58
  • \$\begingroup\$ I did not; I keep forgetting to exploit the Monad instance for things like lists. (+1) \$\endgroup\$
    – ballesta25
    Nov 24, 2015 at 10:42
4
\$\begingroup\$

Pyth, 5 bytes

Zips(C) the input(Q), Maps Sort, then sums.

sSMCQ

Try it online.

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

JavaScript (ES6), 57 bytes

a=>a[0].replace(/./g,(c,i)=>a.map(w=>w[i]).sort().join``)
\$\endgroup\$
4
\$\begingroup\$

TeaScript, 9 bytes

_t¡ßlp¡)µ

TeaScript has all the right built-ins implemented in all the wrong ways.

Try it online

Ungolfed

_t()m(#lp())j``

Explanation

_t()        // Transposes input array
    m(#     // Loops through inputs
       lp() // Sorts characters by char code
     )
j``         // Joins back into string
\$\endgroup\$
1
  • \$\begingroup\$ @intrepidcoder works fine for me. Perhaps your browser has cached some files? Perhaps clearing your cache might work. I'm using Safari though. I'll try refreshing the files \$\endgroup\$
    – Downgoat
    Nov 23, 2015 at 2:11
3
\$\begingroup\$

CJam, 5 bytes

q~z:$

Try it here.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I beat you by like 14 seconds ;P. \$\endgroup\$
    – Maltysen
    Nov 23, 2015 at 0:25
3
\$\begingroup\$

Python, 50 48 bytes

lambda x,y=''.join:y(map(y,map(sorted,zip(*x))))

Thanks to @xnor for -2 bytes!

\$\endgroup\$
2
  • 4
    \$\begingroup\$ You can save "".join to a variable. \$\endgroup\$
    – xnor
    Nov 23, 2015 at 1:22
  • \$\begingroup\$ Oh, I had no idea. Thanks! \$\endgroup\$
    – Dennis
    Nov 23, 2015 at 1:31
3
\$\begingroup\$

Vyxal d, 3 bytes

∩vs

Try it Online!

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

Octave, 15 bytes

@(a)sort(a)(:)'

Example:

octave:1> (@(a)sort(a)(:)')(["abc";"cba"])
ans = acbbac
octave:2> (@(a)sort(a)(:)')(["HELLO";"world";"!!!!!"])
ans = !Hw!Eo!Lr!Ll!Od
\$\endgroup\$
2
\$\begingroup\$

K, 10 bytes

,/{x@<x}'+

Join (,/) the sort of ({x@<x}) each (') of the transpose (+) of a list of strings.

In action:

  ,/{x@<x}'+("HELLO";"world";"!!!!!")
"!Hw!Eo!Lr!Ll!Od"

Simple, but K is hurt a bit here by not having a single-character sort function and instead dividing the operation into a scatter-gather index operator @ and a primitive which yields the permutation vector which would sort a list <.

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

Stax, 5 bytes

LMFop

So close to LMNOP :(

Run and debug it at staxlang.xyz!

Put all inputs into one list of strings (L), and transpose this list (M). For each resulting string (F), sort (o) and print (p) it.

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

Pip, 5 bytes

SS*Zg

Attempt This Online!

\$\endgroup\$
0
1
\$\begingroup\$

Julia, 46 bytes

x->(j=join)(map(i->j(sort([i...])),zip(x...)))

This creates an unnamed function that accepts an array of strings and returns a string. To call it, give it a name, e.g. f=x->....

Ungolfed:

function zipsort{T<:AbstractString}(x::Array{T,1})
    # Splat the input array and zip into an iterable
    z = zip(x...)

    # For each tuple consisting of corresponding characters
    # in the input array's elements, splat into an array,
    # sort the array, and join it into a string
    m = map(i -> join(sort([i...])), z)

    # Take the resulting string array and join it
    return join(m)
end
\$\endgroup\$
1
\$\begingroup\$

C++14, 152 bytes

#include<iostream>
#include<regex>
[](auto s){for(int i=0;i<s[0].size();++i){auto r=""s;for(auto k:s)r+=k[i];std::sort(begin(r),end(r));std::cout<<r;}};

Not using any advantage of map+zip (guess why)

Ungolfed + usage

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

int main()
{
    auto lambda = [](auto s)
    {
        for (int i = 0; i < s[0].size(); ++i)
        {
            auto r = ""s;
            for (auto k : s)
                r += k[i];
            std::sort(begin(r), end(r));
            std::cout << r;
        }
    };

    std::vector<std::string> data = { "HELLO", "world", "!!!!!" };
    lambda(data);
}
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 51 bytes

""<>SortBy@ToCharacterCode/@Transpose@Characters@#&

String manipulation in Mathematica is expensive...

\$\endgroup\$
1
\$\begingroup\$

Japt, 12 bytes 20

Ny m_q n q)q

Try it online!

Explanation

Ny       // Transpose inputs
  m_     // Maps through each new string
    q    // Split string
    n    // Sort string
    q    // Join
)q       // Join again
\$\endgroup\$
1
\$\begingroup\$

Perl 6, 33 bytes

{[~] flat ([Z] @_».comb)».sort}

Example usage:

say {[~] flat ([Z] @_».comb)».sort}(< abc cba >) # acbbca

my &code = my $code = {[~] flat ([Z] @_».comb)».sort}

say code "HELLO","world","!!!!!"; # !Hw!Eo!Lr!Ll!Od

say ((<cba abc>),(<testing gnitset gttseni>)).map($code);
# (acbbac ggtentiststteisenngit)
\$\endgroup\$
1
\$\begingroup\$

𝔼𝕊𝕄𝕚𝕟, 15 chars / 30 bytes

Ѩťªï)ć⇀ѨŌ$ø⬯)ø⬯

Try it here (Firefox only).

Just realized that Lodash's sortBy function works on strings, too.

\$\endgroup\$
1
\$\begingroup\$

Jelly, 3 bytes

ZṢ€

Try it online!

Only valid if considered as a full program: the resulting value is a list of strings, but when it's printed Jelly implicitly flattens it.

  €    Map
 Ṣ     sort
Z      over the columns of the input.
\$\endgroup\$
1
\$\begingroup\$

PHP, 92 91 bytes

for($argv[0]='';$a=array_column(array_map(str_split,$argv),$i++|0);print join($a))sort($a);

Try it online!

I'm confident this could be done shorter by not trying to use PHP's built-in array functions, but had to try!

Or 85 bytes

@Night2's swing, done shorter by not trying to use PHP's built-in array functions:

for(;''<$argv[1][$i++];print join($a))for($a=[];''<$a[]=$argv[++$$i][$i-1];sort($a));

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ @Night2 nicely done! You should post that one as your own. It's too bad that array_column won't work on an array of strings otherwise it'd be quite a bit more useful for CG. And of course having to skip $argv[0] is always a pain too... \$\endgroup\$
    – 640KB
    Aug 22, 2019 at 13:25
1
\$\begingroup\$

Japt -P, 3 bytes

Õmñ

Try it here

\$\endgroup\$
1
\$\begingroup\$

PowerShell Core, 56 50 bytes

-join(($a=$args)[0]|% t*y|%{$a|% c*rs($i++)|sort})

-6 bytes thanks to mazzy

Try it online!

\$\endgroup\$
1
1
\$\begingroup\$

Factor, 34 bytes

[ flip [ natural-sort ] map-flat ]

Attempt This Online!

\$\endgroup\$
1
\$\begingroup\$

rSNBATWPL, 39 bytes

x~strfor{flip$x}{y~y sort>}crush-with""

Try It Online!

\$\endgroup\$
0
\$\begingroup\$

Minkolang 0.13, 46 bytes

$od0Z2:$zIz:$xd0G2-[i1+z[di0c*+c$r]xz$(sr$Ok].

Try it here. Expects input like "HELLO""world""!!!!!" (so no commas).

Explanation

$o     Read in whole input as characters
d      Duplicate top of stack (the ")
0Z     Count how often this appears in the stack
2:     Divide by two
$z     Store this in the register (z)
Iz:    Length of stack divided by z (k)
$x     Dump one element from the front/bottom of stack
d      Duplicate top of stack (which is k)
0G     Insert it at the front/bottom of stack
2-     k-2

  [                              Open for loop that repeats k-2 times
   i1+                           Loop counter + 1 (i)
      z[                         Open for loop that repeats z times
        d                        Duplicate top of stack (which is i)
         i                       Loop counter (j)
          0c                     Copy k from front of stack
            *                    Multiply (j*k)
             +                   Add (j*k + i)
              c                  Copy character at position j*k+i to the top
               $r                Swap top two elements of stack (so i is on top)
                 ]               Close for loop
                  x              Dump the top of stack (dump i)
                   z$(           Start a new loop with the top z elements
                      s          Sort
                       r$O       Reverse and output the whole (loop) stack as characters
                          k      Break - exits while loop
                           ].    Close for loop and stop
\$\endgroup\$
0
\$\begingroup\$

GolfScript, 8 bytes

~zip{$}%

Try it online on Web GolfScript.

How it works

~         # Evaluate the input.
 zip      # Zip it.
    {$}%  # Map sort ($) over the resulting array.
\$\endgroup\$
0
\$\begingroup\$

Clojure/ClojureScript, 43 bytes

#(apply str(mapcat sort(apply map list %)))

Creates an anonymous function. Written in a ClojueScript REPL, should also be valid Clojure.

Enter it here, then call via (*1 ["HELLO" "world" "!!!!!"]). Or do (def f *1) and then use (f ["abc" "cba"]).

\$\endgroup\$
0
\$\begingroup\$

Ceylon, 166

String z(String+l)=>String(expand(t(l).map(sort)));[T+]n<T>(T?+i)=>[for(e in i)e else nothing];{[X+]*}t<X>([{X*}+]l)=>l[0].empty then{}else{n(*l*.first),*t(l*.rest)};

While Ceylon has a zip function, it takes only two iterables instead of an iterable of them. unzip, on the other hand, takes an iterable of tuples, and I don't want to convert my strings into tuples. So I implemented my own transpose function, inspired by a Haskell implementation which Google found for me somewhere.

// zip-sort
//
// Question:  http://codegolf.stackexchange.com/q/64526/2338
// My answer: ...

// Takes a list of strings (same length), and produces
// a string made by concatenating the results of sorting
// the characters at each position.
String z(String+ l) =>
        String(expand(t(l).map(sort)));

// Narrow an iterable of potential optionals to their non-optional values,
// throwing an AssertionError if a null is in there.
[T+] n<T>(T?+ i) =>
        [for (e in i) e else nothing];

// Transpose a nonempty sequence of iterables, producing an iterable of
// sequences.
// If the iterables don't have the same size, either too long ones are
// cut off or too short ones cause an AssertionError while iterating.
{[X+]*} t<X>([{X*}+] l) =>
        l[0].empty
        then {}
        else { n(*l*.first), *t(l*.rest) };

The types of n and t could be defined much more general, but this is Codegolf ;-) (n is a special case of what I proposed as assertNarrow two weeks ago).

\$\endgroup\$
0
\$\begingroup\$

Red, 85 bytes

func[b][repeat c length? b/1[foreach a sort collect[foreach m b[keep m/:c]][prin a]]]

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Brev, 53 41 bytes

(as-list flatten(over(sort args char<?)))

Example:

((as-list flatten (over (sort args char<?))) "HELLO" "world" "!!!!!")
\$\endgroup\$

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.