A quine of sorts

30

0

Given a string x, output the characters in x sorted according to the order of appearance in your source code.

Examples

Source: ThisIs A Test
 Input: Is it a Test?
Output: TissI   etta?

Source: Harry - yer a wizard.
 Input: I'm a what?
Output: aa  wh'?Imt

Source: Mr. H. Potter, The Floor, Hut-on-the-Rock, The Sea
 Input: 
Output:

Rules

  • Standard loopholes & i/o rules apply
  • Input & output can be either a string, a list of characters, or a list of bytes.
  • If a character is used multiple times in the source, use the first occurrence.
  • If one or more characters does not appear in the source, they should be at the end; their order does not matter, nor does it have to be consistent.
  • Source must be non-empty
  • Newlines are treated the same as other characters.
  • The order in which the code is executed doesn't matter; just the raw string.
  • The input is in the same encoding as the code.
  • The input is sorted by characters, not by bytes.
  • Sorting is case sensitive
  • This is , so shortest answer in bytes for each language wins!

let f = (s, i, o) => o.split("").map(x => [x, s.indexOf(x) == -1 ? s.length + 100 : s.indexOf(x)]).sort(([, a], [, b]) => a - b).map(([x]) => x).join("") === o && i.split("").sort().join("") === o.split("").sort().join("");let g = (s, i) => i.split("").map(x => [x, s.indexOf(x) == -1 ? s.length + 100 + Math.random() : s.indexOf(x)]).sort(([, a], [, b]) => a - b).map(([a]) => a).join("");$(() => $("button").click(() => $("#result").text(f($("#source").val(), $("#input").val(), $("#output").val()) ? "Valid" : `Invalid; example output: \`${g($("#source").val(), $("#input").val())}\``)));
body,label{display: flex;flex-direction: column;}*{white-space: pre;font-family: Inconsolata, Consolas, mono-space;font-size: 14px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><label>Source: <textarea id="source">ThisIs A Test</textarea></label><label>Input: <textarea id="input">Is it a Test?</textarea></label><label>Output: <textarea id="output">TissI   etta?</textarea></label><div><button>Validate</button> <span id="result"></span></div>

tjjfvi

Posted 2019-06-27T15:16:11.430

Reputation: 489

Do unprintable characters need to be accounted for? And if not, what about whitespace? – negative seven – 2019-06-27T15:40:43.740

2@negativeseven Any characters from the source code encoding need to be accounted for, including whitespace. – tjjfvi – 2019-06-27T15:46:37.570

2related – Rod – 2019-06-27T17:46:36.107

3You should probably make explicit mention in the spec that matching is case sensitive. – Shaggy – 2019-06-27T23:36:45.363

1Can we get x encoded in UTF-8 or UTF-16 if our solution isn't encoded in Unicode at all, and the Unicode characters in x represent characters in the solution's code page? For example, some golfing languages use custom code pages to reduce their byte count but still be readable with the naked eye. – Erik the Outgolfer – 2019-06-29T07:03:20.517

@Erik No, the input is in whatever encoding the source code is in, including custom code pages. – tjjfvi – 2019-06-29T23:39:32.117

If that was allowed, a golfing language answer could probably be a no-op, because none of the characters in the source are in UTF-8. – tjjfvi – 2019-06-29T23:46:12.260

1@tjjfvi I'm not talking about no-ops here (which would be certainly invalid); at least a few of the answers below, instead of taking input in plain bytes (0x00-0xFF), take the input as the UTF-8 string that the byte sequence would represent (e.g. when we post an answer, we usually post the UTF-8 version of our code, not the hexdump), and then use the UTF-8 representation of the source code to sort the input. Is this allowed? I feel like it should be an option too (alongside the plain byte stream), because otherwise solutions in golfing languages with custom codepages would be hindered greatly. – Erik the Outgolfer – 2019-06-30T19:19:14.710

@tjjfvi This is my understanding: We should write some source-code (which is some bytes) and we may use a code-page (which encodes those bytes as some string of characters - whether that be UTF-8 or UTF-16 or ASCII or ...) and running our code must sort an input composed solely of characters that appear on the aforementioned code-page according to their position in the encoded source-code and output that string of characters. We then score our submission by the byte length of the source-code (in bytes, not in whatever encoding is used to display the characters). Is my understanding correct? – Jonathan Allan – 2019-07-01T10:23:38.330

1@Jonathan Yes, that is correct. – tjjfvi – 2019-07-02T03:20:02.160

1@Erik If the source is valid in encoding X, and is given in encoding X, then it may only handle characters in encoding X. The encoding used by the interpreter etc. is irrelevant. – tjjfvi – 2019-07-02T03:22:53.233

1+1 for "Harry - yer a wizard." – HighlyRadioactive – 2019-10-09T10:01:31.923

Answers

13

Python 3.8 (pre-release), 102 100 96 85 79 76 68 61 59 60 bytes

c="print(sorted(x:=input(),key=('c=%r;'%c+x).find))";exec(c)

Try it online!

-2 bytes by using this

-4 bytes by realizing that <0 == ==-1 and removing the unnecessary +1

-11 bytes thanks to Neil

-6 bytes thanks to dzaima

-3 bytes thanks to rod

-8 bytes thanks to negative seven pointing out that the program can output a list of chars

-7 bytes due to Embodiment of Ignorance switching back to Python 3.8 and using :=

-2 bytes due to Jo King switching out the variable name s for c, so we could leave out the ;c

+1 bytes because negative seven pointed out that it wasn't filtering ; correctly

MilkyWay90

Posted 2019-06-27T15:16:11.430

Reputation: 2 264

('s=%r;exec(s)'%s+x).find(x)? – Neil – 2019-06-27T17:21:52.767

@Neil Is the current solution invalid, and substituting ('s=%r;exec(s)'%s).find(x) with your code would make it valid? – MilkyWay90 – 2019-06-27T17:24:38.407

@Neil Oh, wait, I see your golf – MilkyWay90 – 2019-06-27T17:28:12.360

You can switch to input() and save 4 bytes

– Rod – 2019-06-27T18:03:13.743

the c isn't ordered, but can be fixed at the cost of 1 byte

– Rod – 2019-06-27T18:13:29.190

It seems output should be fine as a list of characters. – negative seven – 2019-06-27T19:48:34.233

@JoKing I don't see the different – MilkyWay90 – 2019-06-28T02:29:50.943

61 bytes in python 3.8 tinyurl.com/y593h4a9 – Embodiment of Ignorance – 2019-06-28T06:01:10.900

@EmbodimentofIgnorance Wow, nice golf! – MilkyWay90 – 2019-06-28T14:57:04.360

@JoKing I see now. Thanks! – MilkyWay90 – 2019-06-28T14:59:30.627

4; isn't being sorted correctly in the current version – negative seven – 2019-06-28T16:45:59.347

@negativeseven Fixed – MilkyWay90 – 2019-06-28T21:32:14.293

7

APL (Dyalog Unicode), 14 bytesSBCS

Anonymous tacit prefix function.

'''∘⍋⊃¨⊂'∘⍋⊃¨⊂

 enclose argument (to act on it as a whole)

⊃¨ from that, pick one character for each of the following indices:

∘⍋ the indices that would sort the argument in the the order given by the following string (all non-members go in order of appearance at the end):

'''∘⍋⊃¨⊂' the characters '∘⍋⊃¨⊂

Try it online!

Adám

Posted 2019-06-27T15:16:11.430

Reputation: 37 779

6

C# (Visual C# Interactive Compiler), 48 bytes

n=>n.OrderBy((@"n=>.OrdeBy(@""+)Ixf"+n).IndexOf)

Try it online!

Embodiment of Ignorance

Posted 2019-06-27T15:16:11.430

Reputation: 7 014

5

JavaScript (Node.js), 60 58 56 bytes

-2 bytes from Jo King

f=_=>_.sort((a,b)=>(p=g=>`f=${f+g}`.indexOf(g))(a)-p(b))

Try it online!

Luis felipe De jesus Munoz

Posted 2019-06-27T15:16:11.430

Reputation: 9 639

Your code seems to only work when the source is f=.... If that is the case, please include that in your submission & byte count. – tjjfvi – 2019-06-27T17:31:14.203

4

Perl 6, 56 bytes

<slurp.comb.sort({"<$_>~EVAL$^a".index($a)}).say>~~.EVAL

Try it online!

Jo King

Posted 2019-06-27T15:16:11.430

Reputation: 38 234

3

05AB1E, 24 22 21 bytes

Σ"Σ"'"«"'«Rrk}"«Rrk}R

Try it online!

Explanation:

Σ                    }               # Sort
 "Σ"                                 # Σ string literal
    '"                               # " string literal
       «                             # Concatenate last two literals
        "'«Rrk}"                     # '«Rrk} another literal
                «                    # Concat again
                 R                   # Reverse literal (so: }krR'«'"Σ)
                  r                  # reverse stack 
                   k                 # find the current sorting index in our code string 
                     R               # reverse our sorted string

First time trying stuff in 05AB1E so probably lots to be saved

Expired Data

Posted 2019-06-27T15:16:11.430

Reputation: 3 129

Are you sure this is correct? The string it now sorts on is }krR«'«. NOTE: ' is a single character, so just '" is enough (unlike C# where it needs an additional trailing '). Currently your code first pushes the string Σ, then the string ", then the string «, then the string '«Rrk}, and then it does the append, reverse, reverse stack, index. Smart usage of the reverse of the string and at the end, though! I will see if I can find a fix for your answer, and will delete mine afterwards. – Kevin Cruijssen – 2019-06-27T16:58:57.090

@kevincruijssen So can't I just get rid of the second ' – Expired Data – 2019-06-27T17:00:53.977

1Yeah, you indeed can. :) Then it correctly sorts on }krR«'"Σ. PS: I tend to use = (print without popping) for debug purposes sometimes. You can also add --debug-stack as argument, but it's a bit weird in the new 05AB1E version imho. – Kevin Cruijssen – 2019-06-27T17:03:48.640

3

Jelly, 16 14 bytes (Jelly Code page), 25 bytes (UTF8)

“Ṿv`Ṿ;³³i@Þ”v`

Try it online!

A full program that takes a single argument, the string to be sorted.

Thanks to @JonathanAllan for pointing out a bug!

As per @EriktheOutgolfer, although the code can be input using the Jelly code page, the characters sorted are the equivalent UTF-8 ones rather than the bytes of the source. As such, I’ve included the score in UTF-8 bytes as well. Note the same probably applies to all languages with custom code pages.

Explanation

“Ṿv`Ṿ;³³i@Þ”   | The string "Ṿv`Ṿ;³³i@Þ", referred to below as S
            v` | Evaluate this string as Jelly code using the string itself as the argument

The string above evaluates as:

Ṿ          | Uneval the string S (effectively wraps it in “”)
 v`        | Eval it (effectively removes the “”)
   Ṿ       | Uneval it again, adding back in the “”
    ;³     | Concatenate the input to this
      ³i@Þ | Sort the input with respect to the first occurence of each character in the “”-wrapped string S concatenated to the input

Ṿv` is a no-op effectively here, but exists to ensure all characters are represented.

Nick Kennedy

Posted 2019-06-27T15:16:11.430

Reputation: 11 829

So... I posted my Jelly answer, and then it clicked on me: the interpreter converts the bytecode to UTF-8 before executing it, hence either the bytecount should be increased, or the code be changed to fit the codepage.

– Erik the Outgolfer – 2019-06-28T19:24:26.753

@EriktheOutgolfer I don’t understand what you’re getting st here. How is this different to any other codegolf challenge in this regard? – Nick Kennedy – 2019-06-28T19:27:14.477

The self-referential aspect is different, so, in fact, the code sorts UTF-8 characters and not the bytes it's supposed to. – Erik the Outgolfer – 2019-06-28T19:28:11.110

3

Ruby, 57 bytes

->s{s.sort_by{|o|%{->s{.ort_by|%}index()9}.index(o)||99}}

Try it online!

Fairly straightforward, assuming I haven't missed a golfing trick. Take in a list of characters and sort by their index in a string consisting of all the uniq characters in the code in order of their appearance. Often their first appearance is in that very string, but that doesn't change the order.

histocrat

Posted 2019-06-27T15:16:11.430

Reputation: 20 600

3

Jelly, 14 bytes

“;fɓḟṾⱮ”ṾɓfⱮ;ḟ

A full program accepting a (Python formatted) string (of Jelly code-page characters) which prints the output.
(as a monadic link it yields a list of lists of characters)

Try it online!

How?

“;fɓḟṾⱮ”ṾɓfⱮ;ḟ - Main Link: list of characters, S
“;fɓḟṾⱮ”       - list of characters = [';', 'f', 'ɓ', 'ḟ', 'Ṿ', 'Ɱ']
        Ṿ      - un-evaluate = ['“', ';', 'f', 'ɓ', 'ḟ', 'Ṿ', 'Ɱ', '”']
         ɓ     - start a new dyadic chain, F(S, T=that):
           Ɱ   - for each character, t, in T:
          f    -   (S) filter keep any of (the single character, t)
             ḟ - (S) filter discard any of (the characters in T)
            ;  - concatenate

Jonathan Allan

Posted 2019-06-27T15:16:11.430

Reputation: 67 804

So... I posted my Jelly answer, and then it clicked on me: the interpreter converts the bytecode to UTF-8 before executing it, hence either the bytecount should be increased, or the code be changed to fit the codepage.

– Erik the Outgolfer – 2019-06-28T19:23:21.547

@EriktheOutgolfer I think this one is safe in that respect since this method does not employ any sorting and meets the I/O being in the same encoding (Jelly's code page) criteria. – Jonathan Allan – 2019-06-28T19:51:32.273

Eh... I think the f and work on Unicode characters, because that's what kind of characters the string actually has inside. For example ”ĿO returns 319 if tested locally encoded in JELLY, so it sees the Ŀ and not the C7. – Erik the Outgolfer – 2019-06-28T19:59:58.540

I think f and work on Unicode too, but is that a problem here? I pass in the restricted set of Unicode characters that appear on Jelly's code page (that is, bytes encoded using that encoding, fulfilling "The input is in the same encoding as the code"); filter them correctly (since these inputted bytes were encoded as Unicode), and then output them correctly. What I then count is the bytes of the code (fulfilling "The input is sorted by characters, not by bytes" and "shortest answer in bytes for each language wins"). – Jonathan Allan – 2019-06-28T20:08:31.123

The problem is that you're passing it the restricted set of Unicode chars the JELLY encoding represents, but you're supposed to pass it JELLY characters instead. If you test it locally, I'm pretty sure that it won't work, since the arguments aren't converted from JELLY to UTF-8.

– Erik the Outgolfer – 2019-06-28T20:12:28.920

@EriktheOutgolfer note the same applies to the 05AB1E, Charcoal and APL answers too as far as I can tell – Nick Kennedy – 2019-06-28T20:15:33.630

@EriktheOutgolfer what conversion is necessary? The input is simply bytes which have been encoded to some characters using Jelly's code-page. The sorting happens according to the characters of the byte-code as displayed in that same encoding. Internally the filtering is of characters, by characters. The output is again bytes encoded in the same fashion. It feels to me like that aligns with the bullet points given in the OP. – Jonathan Allan – 2019-06-28T20:31:34.077

1@JonathanAllan I feel like the "have been encoded to some characters using Jelly's code-page" is what I'm referring to in my previous comment. Since the code's encoding consists of single bytes from 0x00 to 0xFF, that's what the argument's encoding should consist of too, Instead, the argument is passed after being mapped from JELLY to UTF-8, so each of its characters isn't necessarily a single byte anymore. Basically, the code is in JELLY while the argument is in UTF-8, even though it has been mapped to that from JELLY. While the correct UTF-8 output is returned, it should be JELLY all along. – Erik the Outgolfer – 2019-06-28T20:38:55.640

I suggest continuing the discussion over TNB. – Erik the Outgolfer – 2019-06-28T20:39:27.897

2

J, 14 bytes

Anonymous tacit prefix function.

]/:']/:''i'i:]

Try it online!

] the argument

i: last occurrence (non-members get the index beyond end of lookup string) of each character in:

']/:''i' the characters ]/:'i

/: use that to sort:

] the argument

Adám

Posted 2019-06-27T15:16:11.430

Reputation: 37 779

Are the four leading spaces a result of the echo or the code? – tjjfvi – 2019-06-27T16:27:42.933

1@tjjfvi It is how TIO is configured. Fixed now. – Adám – 2019-06-27T16:43:02.343

2

Charcoal, 37 bytes

≔´≔´´´η´F´Φ´θ´⁼´ι´κ´¬´№ηFηΦθ⁼ικΦθ¬№ηι

Try it online! Explanation:

≔´≔´´´η´F´Φ´θ´⁼´ι´κ´¬´№η

There are two ways of quoting characters in Charcoal; ´ quotes any single character while ”y... quotes any character except and also counts as a separate string. It turns out that the overhead in having to deal with means that it doesn't end up any golfier.

FηΦθ⁼ικ

Loop over the characters in turn, outputting any matching characters from the input. This sorts the input.

Φθ¬№ηι

Output any unmatched characters in the input.

Neil

Posted 2019-06-27T15:16:11.430

Reputation: 95 035

2

05AB1E, 31 26 19 bytes

Σ'"'ÿs"Σ'ÿÿsìyk"ìyk

-7 bytes by taking inspiration of @EmbodimentOfIgnorance's approach in his C# answer of appending the current character before indexing.

Try it online or try it with added debug-line to see the strings that's being indexed into.

Explanation:

Σ                 # Sort the (implicit) input-string by:
 '"              '#  Push string '"'
   'ÿ            '#  Push string "ÿ"
     s            #  Swap the order of these two strings on the stack
      "Σ'ÿÿsìyk"  #  Push string "Σ'ÿÿsìyk", where the `ÿ` are automatically filled with
                  #  the previous strings we created: `Σ'"ÿsìyk`
                  #  (top to bottom from stack; left to right in string)
       ì          #  Prepend this string in front of the character we're sorting
        yk        #  And then get the index of the character we're sorting in this string
                  # (after the sorting the resulting string is output implicitly)

Kevin Cruijssen

Posted 2019-06-27T15:16:11.430

Reputation: 67 575

There seems to be a typo in the explanation ("y" instead of "s") – ArBo – 2019-06-27T16:47:15.030

@ArBo Fixed, thanks – Kevin Cruijssen – 2019-06-27T16:54:56.250

1Strictly speaking I had that inspiration over 12 hours earlier when I golfed 11 bytes of @MilkyWay90's answer... – Neil – 2019-06-29T23:46:11.680

This is good! I saw that but couldn't see a way to turn mine into this while saving bytes – Expired Data – 2019-06-29T23:47:33.240

2

Python 2, 62 bytes

lambda a:sorted(a,key=('lambd :sorted(,ky=\'\\+).fin'+a).find)

Same concept as my C# answer.

Try it online!

Embodiment of Ignorance

Posted 2019-06-27T15:16:11.430

Reputation: 7 014

\\\' should be \'\\. Nice approach though! Saved 23 bytes in my Java answer. – Kevin Cruijssen – 2019-06-28T09:45:53.117

1@KevinCruijssen Fixed – Embodiment of Ignorance – 2019-06-29T03:18:25.987

2

PowerShell, 68 bytes

$p=$args
&($t={$p|sort-object{"`$p=`$args
&(`$t={$t})$_"|% i*f $_}})

Try it online!

Andrei Odegov

Posted 2019-06-27T15:16:11.430

Reputation: 939

2

>

  • sort instead sort-object works too. 2) the variable $b defined out of scope your code. the Standard loopholes requires a complete answer. For Powershell it means: any person can wirte the code to a file as a powershell script and run it in a terminal. Your code does not work from script file. Sorry.
  • – mazzy – 2019-06-28T11:14:21.990

    1@mazzy, thank you very much. 1) the sort alias does not work in pwsh on Ubuntu 18.04 2) yes, this is my fault, but I corrected myself, and as a result, the code became longer, of course :) – Andrei Odegov – 2019-06-28T15:55:13.870

    (oO)! I've created sort alias for Powershell. code became longer - this is the challenge :)

    – mazzy – 2019-06-28T17:15:22.027

    awesome $_ at the end of a source code! – mazzy – 2019-06-29T09:25:51.823

    1

    Yes, you are right. Each individual character of $p is append to the end of the string with the source code and gets an index equal to $src.Length, but since “their order does not matter and should not be consistent,” it is not matter. In this answer, the entire input string is appended to the end of the string with the source code.

    – Andrei Odegov – 2019-06-29T09:35:15.693

    @mazzy, don't standard I/O rules allow you to give a function from the input to the output? I dunno what counts as a function in PowerShell... – dfeuer – 2019-06-29T22:09:38.107

    1@dfeuer, I don't understand your question. Sorry. – mazzy – 2019-06-30T04:27:01.507

    2

    Java 10, 129 100 bytes

    s->{s.sort(java.util.Comparator.comparing(c->("s->{.ort(javuilCmpcng\"\\+)dexOf;}"+c).indexOf(c)));}
    

    -29 bytes by porting the +c from @EmbodimentOfIgnorance's C# answer.

    Try it online.

    Explanation:

    s->{                 // Method with char-List parameter and no return-type
      s.sort(java.util.Comparator.comparing(c->
        ("s->{.ort(javuilCmpcng\"\\+)dexOf;}"
                         //  Push a String containing the characters in the code
         +c)             //  Append the current character
            .indexOf(c)  //  And get the first index of the current character in the String
    

    NOTE: Usually it's cheaper to use s.sort((a,b)->Long.compare(a,b)) instead of s.sort(java.util.Comparator.comparing(c->c), but in this case it would be 11 bytes longer:

    s->{var v="s->{var =\"\\;.ot(,)Lngcmpe+idxOf}";s.sort((a,r)->Long.compare((v+a).indexOf(a),(v+r).indexOf(r)));}
    

    Try it online.

    Kevin Cruijssen

    Posted 2019-06-27T15:16:11.430

    Reputation: 67 575

    2

    Japt, 18 bytes

    ñÈi"ñÈi\"\\ bX" bX
    

    Try it

    ñÈi"ñÈi\"\\ bX" bX     :Implicit input of string or character array
    ñ                      :Sort by
     È                     :Passing each X through the following function
      i                    :  Prepend X with
       "ñÈi\"\\ bX"        :    Literal string (The \s are annoying me!)
                    bX     :  First index of X
    

    Shaggy

    Posted 2019-06-27T15:16:11.430

    Reputation: 24 623

    1

    Jelly, 26 bytes (UTF-8*)

    “®³nÞṾ©V”Ṿ©VV
    

    Try it online!

    Takes input as a Python-formatted string in the 1st command-line argument.

    Unique characters:

    “®³nÞṾ©V”
    

    *Note: I discovered that this doesn't work when encoded in JELLY, since it sorts the UTF-8 characters instead of its own bytes.

    Erik the Outgolfer

    Posted 2019-06-27T15:16:11.430

    Reputation: 38 134