Given a permutation of the alphabet and an input string, encrypt the input string by replacing all characters with the one's you've been given. The capitalization should be kept the same and non-letters are not to be changed.

[hnvwyajzpuetroifqkxmblgcsd], "Hello, World!" -> "Zytti, Giktw!"

As [abcdefghijklmnopqrstuvwxyz] has been mapped to [hnvwyajzpuetroifqkxmblgcsd]


Input may be taken in any reasonable form, output can either be to STDOUT or as a String.

More test cases:

[ghrbufspqklwezvitmnjcdyaox], "Foo"                -> "Fvv"
[ubjvhketxrfigzpwcalmoqysdn], "123Test String :D"  -> "123Mhlm Lmaxze :V"
[qscxudkgemwrtbvnzolhyfaipj], "AAbcdeFghijK"       -> "QQscxuDkgemW"

Standard ruleset applies!

  • 3
    \$\begingroup\$ You should mention in the specs that caps should be encoded the same way as lowercase characters. \$\endgroup\$
    – agtoever
    Commented Sep 25, 2021 at 11:44
  • 3
    \$\begingroup\$ Is the input alphabet always in lowercase? \$\endgroup\$
    – pxeger
    Commented Sep 25, 2021 at 12:18
  • 3
    \$\begingroup\$ This needs some clarification. Will the input always be lowercase? You should mention that uppercase letters are mapped the same way as the lowercase letters. It's implied that non letter characters are untouched, but should be explicitly said so \$\endgroup\$ Commented Sep 25, 2021 at 12:20
  • 3
    \$\begingroup\$ This challenge appears to be a duplicate of codegolf.stackexchange.com/q/98301, which is itself closed as a duplicate of codegolf.stackexchange.com/q/22704. \$\endgroup\$
    – Dingus
    Commented Sep 25, 2021 at 15:11
  • 3
    \$\begingroup\$ @Dingus I'd close as a dupe of Encode the simple substitution cipher, but you can't do that since it's closed itself, and correct me if I'm wrong, but I don't think it's really a dupe of DVORAK Keyboard layout, since that's a subset of this challenge, and I don't think most answers can be trivially ported from that. \$\endgroup\$
    – user
    Commented Sep 25, 2021 at 20:09

8 Answers 8


05AB1E, 7 bytes


Try it online!

Du       # make a copy of the permutation and convert it to uppercase
  ì      # prepend the uppercase copy to the permutation
   D{    # make a copy of the new string and sort it
         # this always creates 'A ... Za ... z'
     s   # swap alphabet and permutation
      ‡  # transliterate the second input based on the given strings

JavaScript (Node.js), 60 bytes

Expects (permutation_string)(string).


Try it online!

JavaScript (ES6), 42 bytes

Assuming using lists of ASCII codes is acceptable:


Try it online!


Jelly, 8 bytes


Try it online!

Chaining rules make this too long.

How it works

Œu;$ØẠ,y - Main link. Takes permutation P on the left, string S on the right
   $     - Last two links as a monad f(P):
Œu       -   Uppercase P
  ;      -   Prepend that to P
    ØẠ   - Alphabet; Yield "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
      ,  - Pair; [ØẠ, P ; upper(P)]
       y - Transliterate S, according to that mapping

Zsh, 18 bytes

tr a-zA-Z $1${1:u}

Attempt This Online!



Vyxal, 7 bytes


Try it Online!


:⇧+      # append the uppercase version of the input to the input
   kL    # push a-zA-Z
     $   # swap those
      Ŀ  # and transĿiterate the message

APL (Dyalog Extended), 25 21bytes


Try it online!

This can most definitely be shorter.

-4 bytes thanks to ovs.

  • 1
    \$\begingroup\$ You can use (Pick) instead of indexing with brackets to save a byte. Then the inner dfn can be converted to a tacit function for 3 more bytes saved: Try it online! \$\endgroup\$
    – ovs
    Commented Sep 25, 2021 at 21:53

Python 3, 147 179 151 Bytes

This method doesn't work for test cases containing ABCDEF due to the "g-97" statement.

x=[ord(i) for i in input()];c=chr
print("".join([c(g)*(not(c(g).isalpha())) or(c(x[g-97])*(g>97)or c(x[g-65]-32))for g in[ord(i)for i in input()]]))

There must be a shorter way to do this using mapping, but I haven' quite figured the mapping function out yet. Golf'ed down from an original 180 just a shame its not quite a one liner.

x=[ord(i)for i in input()];y=[ord(i) for i in input()];t=""
for i in range(len(y)):
    if 122>g>97:t+=chr(x[g-97])
    else:t+=chr(g)*(not(90>g>65))or chr(x[g-65]-32)

New method gets it to work with fewer bytes:

x=[ord(i)for i in input()];c=chr
print("".join([(c(x[g-97])if 123>g>96 else c(x[g-65]-32))if c(g).isalpha()else c(g)for g in[ord(i)for i in input()]]))

Movatica has a shorter solution using the string library. And using := I could reduced my answer to a one-liner at the expense of a few bytes


Python 3, 84 bytes

Codebook needs to be a string too.

lambda a,s:s.translate(str.maketrans(ascii_letters,a+a.upper()))
from string import*

Try it online!


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