23
\$\begingroup\$

Your challenge is to sort a string, but rather than by the normal alphabetical order (abc..xyz), you will be sorting strings by a specified alphabet.

You must write a program or function that takes two inputs: An alphabet A and an string S. Both will only contain lowercase English letters, and both will contain at least one character.

You must move letters in S so that the letter that appears first in A appears first, then whichever letter appears second in A, etc. There may be some letters in S that do not appear in A, these should be left at the end and not moved around relative to each other.

Test cases:

A       S               Result
axd     haxuizzxaxduxha aaaxxxxdhuizzuh
a       xyz             xyz
abc     dcba            abcd
il      nmiuplliu       iillnmupu
asdf    qwerty          qwerty

Fewest bytes wins!

\$\endgroup\$
  • \$\begingroup\$ Can we print/return an array of singleton strings? Can we take one string and one array of singleton strings as input? \$\endgroup\$ – Dennis May 28 '18 at 3:47
  • \$\begingroup\$ @Dennis Yes, both are fine representations of strings. \$\endgroup\$ – Pavel May 28 '18 at 3:56
  • \$\begingroup\$ Can we take either or both inputs as an array of individual characters? \$\endgroup\$ – Shaggy May 28 '18 at 12:29
  • \$\begingroup\$ @Shaggy A string is a character array, so yes. \$\endgroup\$ – Pavel May 28 '18 at 14:45

25 Answers 25

5
\$\begingroup\$

05AB1E, 4 bytes

Rvy†

Try it online!

Explanation

R     # Reverse the alphabet
 vy   # For each letter ...
   †  # Push S with the current letter filtered to the front
\$\endgroup\$
  • \$\begingroup\$ Smarter than Σ²sk>. \$\endgroup\$ – Magic Octopus Urn May 31 '18 at 23:22
  • \$\begingroup\$ Too bad about R€† working as expected though :). Sometimes that can work as a smaller vy loop. Nice answer man. \$\endgroup\$ – Magic Octopus Urn May 31 '18 at 23:28
10
\$\begingroup\$

Python 3, 50 47 46 44 bytes

-3 bytes thanks to ngn!

-1 byte thanks to mypetlion

lambda a,s:s.sort(key=lambda c:a.find(c)%27)

Try it online!

Takes in a string as the alphabet and a list of chars as the string and sorts the list in place.

The %27 ensures that if the character is not in the alphabet, the index returned puts it after the rest of the alphabet.

\$\endgroup\$
  • 2
    \$\begingroup\$ -a[::-1].find(c) -> (a+c).find(c) \$\endgroup\$ – ngn May 28 '18 at 0:53
  • 1
    \$\begingroup\$ (a+c).find(c) -> a.find(c)%27 to save 1 byte \$\endgroup\$ – mypetlion May 28 '18 at 17:38
7
\$\begingroup\$

Haskell, 42 bytes

a#s=[c|c<-a,d<-s,c==d]++[c|c<-s,all(/=c)a]

Try it online!

a#s=                     -- take alphabet a and string s
        c<-a             -- for all c in a
             d<-s        --   for all d in s
    [c|       c==d]             keep c if c equals d
   ++                    -- append
    [c|c<-s        ]     --   all c of s
         ,all(/=c)a      --   that are not in a 
\$\endgroup\$
7
\$\begingroup\$

Perl 6,  55  43 bytes

->\A,\S{[~] S.comb.sort:{%(A.comb.antipairs){$_}//∞}}

Try it

->\A,\S{[~] S.comb.sort:{A.index($_)//∞}}

Try it

Expanded:

-> \A, \S {
  [~]  # reduce using &infix:«~» (shorter than `.join`)

    S.comb.sort: # split into character list and sort by:

      {  # bare block lambda with implicit parameter $_

        A.index( $_ ) # get the position

        //  # if it is undefined (not in `A`)
        ∞   # return Inf instead (so it comes at end of result)
      }
}
\$\endgroup\$
  • \$\begingroup\$ Since there will only be up to 26 different characters in the input, and ∞ is 3 bytes, you can replace it with 27 and it'll still work and save a byte. \$\endgroup\$ – Pavel Nov 6 '18 at 16:45
6
\$\begingroup\$

Haskell, 40 34 bytes

-6 bytes huge thanks to Laikoni.

foldr(\c->r(==c)<>r(/=c))
r=filter

Try it online!

The first line is an expression that takes two arguments: S and A.

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice! You can even drop f= because anonymous functions are allowed. \$\endgroup\$ – Laikoni May 29 '18 at 12:18
  • 1
    \$\begingroup\$ Furthermore (<>) is now in Prelude, so this can be shortened to foldr(\c->r(==c)<>r(/=c)) for 34 bytes: Try it online! \$\endgroup\$ – Laikoni May 29 '18 at 13:30
6
\$\begingroup\$

Stax, 6 bytes

{xrINo

Run and debug it

This sorts by a block that does this.

  • Reverse the alphabet.
  • Get the index of each character in the reversed alphabet. Missing yields -1.
  • Negate the index.
\$\endgroup\$
5
\$\begingroup\$

Python 2, 38 bytes

def f(a,s):s.sort(None,a[::-1].find,1)

a must be a string, s a list of strings of length 1. f sorts s in place.

Try it online!

Alternate version, string I/O, 48 bytes

lambda a,s:`sorted(s,None,a[::-1].find,1)`[2::5]

Try it online!

How it works

s.sort(None,a[::-1],1) is shorthand for s.sort(cmp=None,key=a[::-1],reverse=1).

From the docs:

reverse is a boolean value. If set to True, then the list elements are sorted as if each comparison were reversed.

\$\endgroup\$
  • \$\begingroup\$ TIL sort can take 4 arguments. \$\endgroup\$ – Pavel May 28 '18 at 4:11
  • \$\begingroup\$ Only in Python 2. Python 3 deprecated cmp and made key and reverse keyword-only arguments, so its list.sort takes only one positional argument. \$\endgroup\$ – Dennis May 28 '18 at 4:19
4
\$\begingroup\$

J, 5 bytes

]/:i.

Dyadic verb, taking the alphabet on its left and the string to be sorted on the right.

i. finds the indeces of string's characters in the alphabet, the alphabet length if not found.

   'axd' i. 'haxuizzxaxduxha'
3 0 1 3 3 3 3 1 0 1 2 3 1 3 0

/: sorts its left agrument according to the order specified in the right one.

] the rigth argument (the string)

  'haxuizzxaxduxha' /: 3 0 1 3 3 3 3 1 0 1 2 3 1 3 0
aaaxxxxdhuizzuh

Try it online!

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

Python 2, 35 50 bytes

lambda a,s:sorted(s,key=lambda c:-a[::-1].find(c))

Try it online!

Takes a and s as strings; returns a list of singelton strings.

Note: Ouch! Gained 15 bytes to fix...

\$\endgroup\$
  • \$\begingroup\$ Ha! This is actually exactly the same as my original code for my answer. Great minds think alike \$\endgroup\$ – Jo King May 30 '18 at 10:34
  • 1
    \$\begingroup\$ @Jo King: Stop controlling my thoughts! :) \$\endgroup\$ – Chas Brown May 31 '18 at 6:06
4
\$\begingroup\$

K (ngn/k), 9 bytes

{y@>-x?y}

Try it online!

{...} is a function with arguments x and y

x?y finds for each element in y the index of its first occurrence in x; if an element is not found in x, its index is considered 0N (-263)

- negates all indices except that it keeps the 0N-s intact, because 263≡-263 (mod 264)

> returns a sort-descending permutation

y@ indexes y with that

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 13 bytes

Fθ×ι№ηιΦη¬№θι

Try it online! Link is to verbose version of code. Explanation:

 θ              First input
F               Loop over characters
     η          Second input
      ι         Current character
    №           Count matches
   ι            Current character
  ×             Repeat
                Implicitly print
        η       Second input
       Φ        Filter
           θ    First input
            ι   Current character
          №     Count matches
         ¬      Logical not
                Implicitly print non-matching characters
\$\endgroup\$
3
\$\begingroup\$

Jelly, 4 bytes

fⱮ;ḟ

A dyadic link accepting the string on the left and the alphabet on the right (as lists of characters) and returning the result (also as a list of characters).

Try it online!

How?

fⱮ;ḟ - Link: string; alphabet                                    e.g. smallnotxl; xl
 Ɱ   - map (for each character in the alphabet):                      1=x; 2=l
f    -   filter keep (keep occurrences of this character from string)   x    lll -> xlll
   ḟ - filter discard (discard all alphabet characters from string)   smanot
  ;  - concatenate                                                    xlllsmanot
\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Unicode), 5 bytesSBCS

Anonymous tacit prefix function, taking [string,ordering] as argument.

⍋⍨/⌷⊃

Try it online!

/ Reduce by the following function:

  … namely the reversed-arguments version of the following function:

   grade the right string according to the left ordering (missing letters go at the end)

 use that to index into…

 the first element of the argument (i.e. the string)

\$\endgroup\$
3
\$\begingroup\$

JavaScript (SpiderMonkey), 50 bytes

Takes input in currying syntax (a)(s), where a is a string and s is an array of characters. Returns an array of characters.

a=>s=>s.sort((b,c)=>(g=c=>-1/a.search(c))(b)-g(c))

Try it online!

How?

We define the helper function g() as:

c => -1 / a.search(c)

which returns:

  • 1 if c does not belong to the alphabet
  • a float value in [-Inf, 0) based on the position of c in the alphabet otherwise (-Inf, -1, -1/2, -1/3, etc.)

We sort s[ ] by computing g(b) - g(c) for each pair of characters (b, c) passed to the callback of sort().

Because the implementation of sort() in SpiderMonkey is stable, all characters of s[ ] that do not belong to the alphabet are simply moved at the end in order of appearance and are let unchanged when they are compared with each other.


JavaScript (ES6), 61 bytes

Takes input in currying syntax (a)(s), where both a and s are arrays of characters. Returns a string.

a=>s=>a.map(C=>s=s.filter(c=>c!=C||!(o+=c)),o='')&&o+s.join``

Try it online!

\$\endgroup\$
3
\$\begingroup\$

R, 69 62 58 bytes

function(a,s)c(rep(a,rowSums(outer(a,s,"=="))),s[!s%in%a])

Try it online!

Input and output are vectors of individual characters.

Explanation:

function(a,s)c(                              ,           ) #combine:
                   a,                                      #[each char in a
               rep(                                        #each repeated
                     rowSums(               )              #the number of
                             outer(a,s,"==")               #occurrence in s]
                                              s            #with s
                                               [ s%in%a]   #all chars in a
                                                !          #omitted
\$\endgroup\$
3
\$\begingroup\$

Brain-Flak (BrainHack), 118 bytes

{({}(<>))<>}{}<>{<>([[]()]<{<>(({})<({}<>[({}<>)]){(<()>)}{}{}>)<>}<>({}<{({}<>)<>}<>>)>[]){({}()<(({}))>)}{}{}<>{}}<>

Try it online!

Input is the first string, followed by a null, followed by the second string. A version that uses a newline as the separator instead adds 24 bytes:

Brain-Flak, 142 bytes

(()){{}(({}(<>))[(()()()()()){}]<>)}{}<>{<>([[]()]<{<>(({})<({}<>[({}<>)]){(<()>)}{}{}>)<>}<>({}<{({}<>)<>}<>>)>[]){({}()<(({}))>)}{}{}<>{}}<>

Try it online!

Explanation

# Move A to other stack reversed
# Zeroes are pushed under each character for later.
# (This is the only part that needs to change in order to use newline as separator.)
{({}(<>))<>}{}<>

# For each character in A, starting at the end:
{

  # Track current length of S.
  <>([[]()]<

    # For each character in S:
    {

      # While keeping character from A
      <>(({})<

        # Move character from S to second stack and push difference
        ({}<>[({}<>)])

        # Delete character if equal
        {(<()>)}{}{}

      >)

    <>}

    # Move S back to first stack while maintaining character from A
    <>({}<{({}<>)<>}<>>)

  # Push difference between old and new lengths of S
  >[])

  # Insert character from A at beginning of S that many times
  {({}()<(({}))>)}{}{}

<>{}}<>
\$\endgroup\$
2
\$\begingroup\$

C (gcc), 97 bytes

f(D,d,S,s,i,o)char*D,*S;{
  while(d--){
    for(i=o=s;i--;)S[i]-D[d]?S[--o]=S[i]:0;
    while(o--)S[o]=D[d];
  }
}

All whitespaces (spaces and newlines) in the code above are only for readability and should be removed.

The dictionary is passed in D and have length d, the string is passed in S and have length s. i and o should be omitted.

Try it online!

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

Pyth,  9  5 bytes

ox+vz

Try it here!

ox+vz    Full program. Input format: "S" \n "A".
o        Sort the characters of S by (variable: N)...
 x       ... N's index in...
  +vz    ... A + N
\$\endgroup\$
2
\$\begingroup\$

Java 8, 98 bytes

a->s->{for(int i=a.length;i-->0;s=s.replaceAll("[^"+a[i]+"]","")+s.replaceAll(a[i],""));return s;}

Try it online.

Explanation:

a->s->{       // Method with String-array and String parameters, and String return-type
  for(int i=a.length;i-->0;
              //  Loop backwards over the alphabet
    s=        //   Replace the current `s` with:
      s.replaceAll("[^"+a[i]+"]","") 
              //    All the current characters of `a` in `s`
      +s.replaceAll(a[i],""));
              //    Concatted with everything else
  return s;}  //  Return the modified `s`
\$\endgroup\$
  • \$\begingroup\$ Couldn't go lower, even with Java 11's new String.repeat(int) method. Nice! :) \$\endgroup\$ – Olivier Grégoire May 29 '18 at 14:34
  • \$\begingroup\$ @OlivierGrégoire Oh, didn't knew early access to Java 11 was already available. That .repeat(n) looks promising, though. :D \$\endgroup\$ – Kevin Cruijssen May 29 '18 at 14:48
2
\$\begingroup\$

Perl 5 with -pF, 43 bytes

$_=<>;print$F[0]x s/@{[shift@F]}//g while@F

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Isn't there a flag that gives you $_=<>; for free? \$\endgroup\$ – Pavel May 28 '18 at 14:39
  • \$\begingroup\$ @Pavel yeah, sorry I'm using it to populate @F, but I didn't add it to the header! I'll do that now! Thank you! \$\endgroup\$ – Dom Hastings May 28 '18 at 17:37
  • \$\begingroup\$ You can cut 10 bytes off this and still use the same logic: Try it online! \$\endgroup\$ – Xcali Aug 16 at 3:46
2
\$\begingroup\$

Prolog (SWI), 136 bytes

X/_/[X|_].
X/Y/[Z|R]:-Y\=Z,X/Y/R.
i(_,X,[],[X]).
i(A,X,[Y|R],[X,Y|R]):-X/Y/A.
i(A,X,[Y|R],[Y|S]):-i(A,X,R,S).
A*S*T:-foldl(i(A),S,[],T).

Try it online! Example usage:

[i,l]*[n,m,i,u,p,l,l,i,u]*S.
S = [i, i, l, l, n, m, u, p, u]
\$\endgroup\$
1
\$\begingroup\$

Clean, 61 bytes

import StdEnv
$a s=[c\\c<-a,k<-s|k==c]++[c\\c<-s|all((<>)c)a]

Try it online!

Defines the function $ :: [Char] [Char] -> [Char].

Unsurprisingly, this is literally nimi's Haskell answer but longer.

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

Jelly, 7 bytes

i@oİ$¥Þ

Try it online!

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

APL+WIN, 12 bytes

Prompts for screen input of S then A:

s[(,⎕)⍋s←,⎕]

Try it online! Courtesy of Dyalog Classic

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

PynTree, 13 bytes

§yz:ṡzCæf+yxx

Try it online!

Port of Jo King's Python answer.

Explanation

§yz:ṡzCæf+yxx  Anonymous lambda
§              lambda  ,
 y                    y
  z                     z
   :                     :
    ṡ                     sorted( ,lambda x:
     z                           z
      C                                     (          )( )
       æf                                    (   ).find
         +                                     +
          y                                   y
           x                                    x
            x                                            x
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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