6
\$\begingroup\$

Bi-directional translator

The challenge is to create a translator that can translate a [a-zA-Z ] string into another string according to the mappings below. The translator should also be able to translate translated text back into its normal form (hence bi-directional). Case doesn't have to be maintained and can be either lower/uppercase (or both lower and upper-cased) in the output, however your program should be able to handle either lower/uppercase strings.

Here is the specification of the mappings for this challenge:

-------------------
|Letter | Mapping |
-------------------
|   S   |    9    |
|   F   |    1    |
|   H   |    5    |
|   X   |    =    |
|   Z   |   {N}   |
|   M   |   --*   |
|   N   |   :)    |
|   G   |    ]    |
|   T   |    [    |
-------------------

Here are some example in/outputs: (The " or ... or ..." obviously shouldn't be in your actual output, its just to demonstrate the possible outputs)

> ABS
< AB9 or ab9 or Ab9 or aB9

> foo
< 1oo or 1OO or ...

> FIZZ BUZZ
> 1i{N}{N} bu{N}{N} or 1I{N}{N} BU{N}{N} or ...

> {n}[:) 
< ztn or ZTN or ...

> bar
< bar or BAR or ...

The inputs will always be in [a-zA-Z ] or a "translated" string containing the mapped symbol, other symbols or characters outside wouldn't be inputted.

\$\endgroup\$
2
  • \$\begingroup\$ Welcome to the site! To clarify, should submissions consist of two programs (one per direction), or one that can do both? \$\endgroup\$
    – rydwolf
    Commented Oct 31, 2020 at 18:11
  • \$\begingroup\$ @RedwolfPrograms Thanks! The program should be able to do both. \$\endgroup\$
    – Anonymous
    Commented Oct 31, 2020 at 18:20

8 Answers 8

6
\$\begingroup\$

Retina 0.8.2, 70 68 57 bytes

.[}*]|\)

T`l`L
T`-{=519[]:NGTSF\HXZM`Ro
{
{N}
-
--*
:
:)

Try it online! Link includes test cases. Uppercases the result. Explanation:

.[}*]|\)

Remove the suffixes from {N}, --* and :) leaving their first character.

T`l`L

Uppercase everything.

T`-{=519[]:NGTSF\HXZM`Ro

Translate the first characters. The string is mapped to its reverse, so that - maps to M etc. and vice versa. The H is a special character and needs to be quoted. The - is normally a special character but placing it at the beginning avoids this.

{
{N}
-
--*
:
:)

Expand the {, - and : to the full strings again.

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

05AB1E, 65 63 bytes

u"{N}"¬.:"--*"¬.:":)"¬.:"SFHXZMNGT[]:-{=519"‡"{-:N-)}*"3ιD€нs‡

Uses the same approach as Neil's answer. Probably not going to be too competitive among the golf answers, but there's definitely improvements to be made here (I'm still a novice with 05AB1E, especially with string manipulation).

Explanation:

u            uppercase the input

"{N}"        push '{N}'
     ¬       extract and push head ('{')
      .:     replace all {N} => {

"--*"        push '--*'
     ¬       extract and push head ('-')
      .:     replace all --* => -

":)"         push ':)'
    ¬        extract and push head (':')
     .:      replace all :) => :

"SFH...519"  push lookup string

            bifurcate (push a, reversed(a))
 ‡           transliterate input with lookup

             set up stack for reverse process
             to do { -> {N} ... etc

"{-:N-)}*"   push literal string
3ι           uninterleave by 3
  D          duplicate
   €         apply single function map 
    н        extract first element
     s       swap
      ‡      transliterate

The bi-directional bit is achieved by transliterating with a bifurcated lookup string; each character that should be swapped is in the opposite position with the one it should be swapped with in the lookup string. The main problem (and potential savings) is that I repeat a lot of logic for the "{N}" -> "{" ... part at the beginning as in the "{" -> "N" ... part at the end. Originally, I thought transliterate could go both ways, so I was going to set up the stack carefully at the beginning, but I don't think transliterate likes it when there's a multi-character string in the list (it probably goes by character, rather than doing a replace all?).

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You can save a few bytes by reusing the "{-:N-)}*"3ι for the initial replacements with the register: tio.run/##yy9OTMpM/f@/… \$\endgroup\$
    – ovs
    Commented Nov 1, 2020 at 8:30
  • \$\begingroup\$ And .: can take two lists of strings and do all replacements at once like this, which might be helpful. \$\endgroup\$
    – ovs
    Commented Nov 1, 2020 at 8:43
  • \$\begingroup\$ In addition to what @ovs suggested in his second comment, you can also save the €н in another variable and use that at the end as well: 45 bytes. \$\endgroup\$ Commented Nov 2, 2020 at 8:29
6
\$\begingroup\$

JavaScript (ES6),  118 113  109 bytes

s=>s.toUpperCase(A=[':)',...'NF1G]H5S9T[X=Z','{N}','M','--*']).replace(/[{-]..|:?./g,c=>A[A.indexOf(c)^1]||c)

Try it online!

How?

Because the input is guaranteed to contain exclusively [a-zA-Z] and/or the special patterns, we can use the following minimal regular expression to match them all:

/[{-]..|:?./g
 [{-]..        // either "{" or "-" followed by 2 other characters
               // -> to match "{N}" or "--*"
        :?.    // or any character, preceded by an optional ":"
               // -> to match ":)" or any single character

Working on the uppercase version of the input, we look for the position of each matched pattern in the lookup array A[] and replace it with its counterpart, or leave it unchanged if it is not found (which may only happen for ABCDEIJKLOPQRUVWY).

\$\endgroup\$
1
  • 1
    \$\begingroup\$ That's a clever way to go about this, nicely done! \$\endgroup\$
    – Anonymous
    Commented Oct 31, 2020 at 19:52
4
\$\begingroup\$

Perl 5 -p, 90, 88 bytes

$_=uc;s/.[}*]|://g;y/-{)SFHXGT915=][ZNM/MZN915=][SFHXGT{:-/;s/{/{N}/g;s/:/:)/g;s/-/--*/g

Try it online!

using the same algorithm as Neil's answer

saved 2 bytes removing the backslash before the opening brace, and removing the colon instead of closing parenthesis in :)

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

Python 3, 189 147 127 135 bytes

s=input().upper()
b=[*'915=][',':)','--*','{N}']
for k,v in zip(*['SFHXGTNMZ',b][::0>max(map(s.find,b))or-1]):s=s.replace(k,v)
print(s)

Try it online! If this were not codegolf the conditional should obviously be outside of the for rather than repeated at each iteration. What wouldn't we do for a few bytes...

  • saved 42 bytes by replacing the dict with two lists;
  • saved 20 bytes thanks to ovs' [::True or-1] dark magic.
  • added 8 bytes because of missing .upper()
\$\endgroup\$
6
  • 1
    \$\begingroup\$ You can save a few bytes by reversing the arguments of zip if necessary instead of that if statement and using [*'...',] instead of list('...')+[]: tio.run/##Dcy7DsIgFADQvV/… \$\endgroup\$
    – ovs
    Commented Nov 1, 2020 at 22:20
  • \$\begingroup\$ @ovs Nice! And saved an extra two bytes because we no longer to save a copy of the initial string. \$\endgroup\$
    – Stef
    Commented Nov 1, 2020 at 22:27
  • \$\begingroup\$ This doesn't handle the foo case, does it? \$\endgroup\$
    – Sisyphus
    Commented Nov 2, 2020 at 0:21
  • \$\begingroup\$ @Sisyphus FOO works but foo doesn't, I suppose this needs to increase a few bytes to add .upper() to the input \$\endgroup\$ Commented Nov 2, 2020 at 0:39
  • 1
    \$\begingroup\$ So it has to be 135 bytes because of adding .upper() to s=input() \$\endgroup\$ Commented Nov 2, 2020 at 0:41
2
\$\begingroup\$

Haskell, 186 bytes

import Data.Char
k="S 9 F 1 H 5 X = Z {N} M --* N :) G ] T [ "
v=words$k++map toLower k
w=v++reverse v
_!""=""
[]!(t:u)=t:w!u
(a:b:c)!s|n<-length a,take n s==a=b++w!drop n s|1<2=c!s
(w!)

Try it online!

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

Python 3, 226 189 181 bytes

Saved a whopping 37 bytes thanks to ovs!!!
Saved 6 bytes thanks to Stef!!!

from re import*
def f(s,m="9 1 5 = --* :\) ] \[ {N}".split()):
 for t,r in zip(*(m,"SFHXMNGTZ")[::2*bool(search(f"({'|'.join(m)})",s,I))-1]):s=sub(t,r,s,0,I)
 return sub(r'\\','',s)

Try it online!

Will reverse the translation if any of the mappings are in the input.

\$\endgroup\$
4
  • \$\begingroup\$ 189 bytes \$\endgroup\$
    – ovs
    Commented Nov 1, 2020 at 22:04
  • \$\begingroup\$ 181 bytes \$\endgroup\$
    – Stef
    Commented Nov 1, 2020 at 22:08
  • \$\begingroup\$ @ovs Sweetness - thanks! :D \$\endgroup\$
    – Noodle9
    Commented Nov 1, 2020 at 23:00
  • \$\begingroup\$ @Stef Nice one - thanks! :D \$\endgroup\$
    – Noodle9
    Commented Nov 1, 2020 at 23:00
0
\$\begingroup\$

C (gcc), 333 bytes I'--* e=ac[ly 5al1 o1 9a[a:) N

void f(char*i,char*o,int*a,int*e,char**c){int t=0;int s=0;char*p=0;while(i[0]){char x=e[(uint8_t)i[0]];if(x){int l;s=a[(s*23)+x-1];if((l=a[((s+1)*23)-1]))t=l;if(!p)p=i;if(s){i++;continue;}}s=0;if(t){if(t>9)o+=sprintf(o,c[t-10]);else o+=sprintf(o,c[t+8]);t=0;p=0;continue;}if(p){while(p<i){o[0]=p[0];o++;p++;}p=0;}o[0]=i[0];o++;i++;}}

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Could we please resolve it : .code.tio.c:26:1: warning: return type defaults to ‘int’ [-Wimplicit-int] f(chari,charo,inta,inte,char*c){int t=0,s=0,l;charp=0,x;while(*i){if(x=e[(uint8_t)*i]){s=a[s*23+x-1];if(l=a[-~s*23-1])t=l;if(s){i++;continue;}}if(t){o+=sprintf(o,c[t>9?t-10:t+8]);s=t=p=0;continue;}if(p=p?:i){while(p<i)*o++=*p++;p=0;}*o++=*i++;}} ^ .code.tio.c: In function ‘f’: \$\endgroup\$ Commented Nov 2, 2020 at 20:43
  • \$\begingroup\$ And this please ? .code.tio.c:26:189: warning: assignment to ‘int’ from ‘char ’ makes integer from pointer without a cast [-Wint-conversion] f(chari,charo,inta,inte,char*c){int t=0,s=0,l;char*p=0,x;while(*i){if(x=e[(uint8_t)*i]){s=a[s*23+x-1];if(l=a[-~s*23-1])t=l;if(s){i++;continue;}}if(t){o+=sprintf(o,c[t>9?t-10:t+8]);s=t=p=0;continue;}if(p=p?:i){while(p<i)*o++=*p++;p=0;}*o++=*i++;}} \$\endgroup\$ Commented Nov 2, 2020 at 20:45
  • \$\begingroup\$ While such practices may be frowned upon for production code, compiler and interpreter warnings are generally not a problem for code golf. \$\endgroup\$
    – ceilingcat
    Commented Nov 3, 2020 at 1:36
  • \$\begingroup\$ Suggest s,t;l;f(i,o,a,e,c)char*i,*o,**c;int*a,*e;{for(char*p=t=s=0,x;*i;){z:if(x=e[255&*i])if(s=a[s*23+x-1],t=(l=a[s*23+22])?:t,s){i++;goto z;}t?o+=sprintf(o,c[t>9?t-10:t+8]),s=t=p=0:((p=p?:i)?o=mempcpy(o,p,i-p),p=0:0,*o++=*i++);}} \$\endgroup\$
    – ceilingcat
    Commented Dec 26, 2020 at 6:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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