Znajdź tabelę tłumaczeń


17

Biorąc pod uwagę dwa ciągi, znajdź tabelę translacji ( szyfr podstawienia ) między nimi, jeśli tłumaczenie nie jest możliwe, wyślij false. Odpowiedź należy zminimalizować i utworzyć od lewej do prawej. Pierwszym tłumaczonym znakiem między słowami musi być pierwszy w tabeli tłumaczeń. Oprócz tego żaden list, który nie został przetłumaczony (w tym samym miejscu, w którym był pierwotnie), NIE powinien znajdować się w tabeli tłumaczeń.

Prawdopodobnie najłatwiejszy do zdefiniowania za pomocą przykładów:

Ważne przypadki

"bat", "sap" => ["bt","sp"]

Zwróć uwagę na kolejność, wynik ["tb","ps"]nie jest prawidłowy dla tego wyzwania.

"sense", "12n12" => ["se","12"]

Zauważ, że nnie jest przetłumaczone, ponieważ jest to relacja 1 do 1.

"rabid", "snail" => ["rabd","snal"]

Zauważ, że inie jest przetłumaczone, ponieważ jest to relacja 1 do 1.

"ass", "all" => ["s","l"]

A nie jest uwzględnione, pozostaje takie samo, smoże zostać odwzorowane na podstawie ldopasowania wzorca.

"3121212", "ABLBLBL" => ["312","ABL"]

Idealnie pasuje do wzoru.

Falsy Cases

"banana", "angular" => false

(nie tej samej długości, niemożliwe).

"animal", "snails" => false

(każdego znaku można użyć RAZ tylko po każdej stronie tłumaczenia).

"can","cnn" => false

(n jest domyślnie używane w tłumaczeniu, dlatego zdefiniowanie tabeli translacji za pomocą n-> a byłoby niepoprawne)

Tak więc, [aimal,sails]jest to nieprawidłowa odpowiedź, czyniąca to fałsz.

"a1", "22" => false

Patrz „zastrzeżenia”, jest to wymienione jako fałsz. W tym przypadku, to dlatego, ai 1nie mogą oba mapowania 2. (Każda postać może być użyta RAZ tylko po każdej stronie tłumaczenia).


Ta odpowiedź wydaje się być dobrym punktem odniesienia: /codegolf//a/116807/59376

Jeśli masz pytania dotyczące funkcjonalności dwóch niepublicznych par słów, przejdź do tej implementacji.


Zasady we / wy

  • Dane wejściowe mogą być w postaci tablicy 2-elementowej lub 2 osobnych danych wejściowych.
  • Dane wyjściowe mogą być rozdzielane tablicą lub znakiem nowej linii / spacji, podobnie jak to pokazano.
  • Fałszywe wyjście może wynosić 0, -1 lub fałsz. Błąd / puste wyjście również jest w porządku.
  • Masz gwarancję, że anie będą równe bi ani anie bbędą puste.
  • ai bsą sekwencjami liter tylko do wydruku ASCII.

Ostrzeżenia

  • Tłumaczenia muszą odbywać się od lewej do prawej, patrz przykład 1.
  • Nie wolno wyprowadzać znaków, które pozostają takie same.
  • Twój program może przyjmować tylko dwa ciągi ai b.
  • Każda postać może być użyta RAZ tylko po każdej stronie tłumaczenia. To sprawia, że ​​tłumaczenie snailsjest animalsniemożliwe.
  • Rekurencyjne zamiany nie powinny wystąpić. Przykład zamiany rekurencyjnej: "a1","22"->[a1,12]gdzie a jest najpierw zastępowane przez 1, wówczas oba wynikowe 1 są zastępowane przez 2. To nie jest poprawne, zakładamy, że wszystkie tłumaczenia odbywają się niezależnie od siebie, co oznacza, że ​​jest to fałsz. Znaczenie: „a1” z tabelą translacji [a1,12] przyjmuje wartość 12 (nie 22)

Oznaczenie tego „tłumaczenia” jako prostego szyfru zastępczego może pomóc w wyjaśnieniu intencji.
Greg Martin

Czy tablice asocjacyjne są dozwolone jako dane wyjściowe? Mogłoby mi to zaoszczędzić trochę bajtów
Jörg Hülsermann

@ JörgHülserman Nie jestem do końca pewien konsekwencji tego, może pozwolę zrobić 2 wersje, aby zobaczyć różnicę? Zedytuję to, jeśli uważam, że nie jest szkodliwe dla wyzwania.
Magic Octopus Urn

Spójrz na moje pierwsze rozwiązanie jako ciąg, a drugie ma jako wynik tablicę asocjacyjną
Jörg Hülsermann

@ JörgHülsermann ahhh ... Widzę, jak teraz go używasz, myślę, że nie mogę tego zabronić, nie wszystkie języki obsługują struktury podobne do skrótów.
Magic Octopus Urn

Odpowiedzi:


7

JavaScript (ES6), 128 bajtów

f=
(s,t)=>!t[s.length]&&[...s].every((c,i)=>n[d=t[i]]==c||d&&!m[c]&&!n[d]&&(n[m[c]=d]=c,c==d||(a+=c,b+=d)),m={},n={},a=b='')&&[a,b]
<div oninput=o.textContent=f(s.value,t.value)><input id=s><input id=t><pre id=o>


Nie działa assi allpowinno być s,l.
Magic Octopus Urn

Tak, ten fragment może się potknąć, również zweryfikowany, jest w porządku.
Magic Octopus Urn

1
@carusocomputing To było zderzenie nazwy zmiennej - zostało już naprawione. Przepraszam za to.
Neil

7

JavaScript (ES6), 108 107 105 106 bajtów

Edycja : Naprawiono w celu obsługi danych wejściowych takich jak "22" / "a1"fałsz.


Zwraca jeden 0lub tablicę dwóch ciągów.

f=(a,b,x)=>[...a].some((c,i)=>d[C=b[i]]?d[C]!=c:(d[C]=c)!=C&&(s+=c,t+=C,!C),s=t='',d=[])?0:x||f(b,a,[s,t])

Sformatowane i skomentowane

f = (                       // given:
  a,                        // - a = first string
  b,                        // - b = second string
  x                         // - x = reference result from previous iteration,
) =>                        //       or undefined
  [...a].some((c, i) =>     // for each character c at position i in a:
    d[                      //   if we already have a translation
      C = b[i]              //   of the character C at the same position in b,
    ] ?                     //   then:
      d[C] != c             //     return true if it doesn't equal c
    :                       //   else:
      (d[C] = c) != C &&    //     store the translation C -> c in the dictionary
      (                     //     if the characters are different:
        s += c, t += C,     //       append them to the translation strings s and t
        !C                  //       return true if C is undefined
      ),                    //
    s = t = '', d = []      //   initialize s, t and d  
  ) ?                       // if some() returns true:
    0                       //   there was a translation error: abort
  :                         // else:
    x ||                    //   if this is the 2nd iteration, return x
    f(b, a, [s, t])         //   else do a recursive call with (b, a)

Przypadki testowe


f('22')('a1')też powinien być fałszywy.
Neil,

Mam nadzieję, że tym razem mam rację.
Arnauld

1
Jest to zawsze przydatne, gdy okazuje się, że twoja poprawka błędu upraszcza coś krótszego!
Neil

7

PHP> = 7,1, 130 bajtów

18 bajtów zapisanych przez @Titus

for([,$x,$y]=$argv;a&$o=$y[$i];)$o==($p=$x[$i++])?:$k[$c[$p]=$o]=$p;echo$y==strtr($x,$c)&$x==strtr($y,$k)?join($k)." ".join($c):0;

Przypadki testowe

Rozszerzony

for([,$x,$y]=$argv;a&$o=$y[$i];)
$o==($p=$x[$i++])?:$k[$c[$p]=$o]=$p; # if char string 1 not equal char string 2 make key=char1 value=char2 and key array
echo$y==strtr($x,$c) # boolean replacement string 1 equal to string 2
    &$x==strtr($y,$k) # boolean replacement string 2 equal to string 1
    ?join($k)." ".join($c) # output for true cases
:0; #Output false cases

PHP> = 7,1, 148 bajtów

wypisuje 0 dla false Wypisuje true jako łańcuch

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)$x[$i]==$o?:$c[$x[$i]]=$o;echo$y==strtr($x,($f=array_flip)($k=$f($c)))&$x==strtr($y,$k)?join($k)." ".join($c):0;

Przypadki testowe

Rozszerzony

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo$y==strtr($x,($f=array_flip)($k=$f($c))) # boolean replacement string 1 equal to string 2
&$x==strtr($y,$k) # boolean replacement string 2 equal to string 1
    ?join($k)." ".join($c) # output for true cases
:0; #Output false cases

PHP> = 7,1, 131 bajtów

Drugą odpowiedź można skrócić, jeśli dozwolone są tablice asocjacyjne

wypisuje 0 dla false Wypisuje true jako tablicę asocjacyjną zamiast ciągu

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)$x[$i]==$o?:$c[$x[$i]]=$o;print_r($y==strtr($x,($f=array_flip)($f($c)))&$x==strtr($y,$k)?$c:0);

Przypadki testowe

PHP> = 7,1, 227 bajtów

drukuje 0 dla fałszu

[,$x,$y]=$argv;echo strlen($x)==strlen($y)?strtr($x,$c=array_filter(($f=array_flip)($z=$f(array_combine(($p=str_split)($x),$p($y)))),function($v,$k){return$k!=$v;},1))==$y&$x==strtr($y,$z)?join(array_keys($c))." ".join($c):0:0;

Przypadki testowe

Rozszerzony

[,$x,$y]=$argv; # 
echo strlen($x)==strlen($y) #compare string lengths
?strtr($x,  # replace function
$c=array_filter( # filter 
($f=array_flip)($z=$f( # # remove doubles like in testcase: a1 => 22
    array_combine(($p=str_split)($x),$p($y))  # replacement array keys string 1 values string 2 
))
    ,function($v,$k){return$k!=$v;},1)) # remove all keys that equal to values in array
    ==$y # boolean replacement string 1 equal to string 2
&$x==strtr($y,$z) # boolean replacement string 2 equal to string 1        
?join(array_keys($c))." ".join($c) # output for true cases
    :0 # Output if replacement from string 1 is not equal to string 2
:0; #Output for different lengths

1
@carusocomputing Dziękujemy za komplement. Zapomniałem małej sztuczki. Wiem, że tutaj jest wielu ludzi, którzy są lepsi ode mnie
Jörg Hülsermann

2
Jesteś zdecydowanie dobry w znajdowaniu rozwiązań +1, ale array_values()wewnątrz join()jest całkowicie bezużyteczny i można go upuścić.
Christoph

1
To nie powiedzie się w a1 22 => falseprzypadku testowym. Ponadto twój pierwszy program nie działa w testerze online.
mbomb007

1
Zamknij się. To jest cudowne.
Tytus

1
Płetwy mogą iść: Zapisz 18 bajtów ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p;w pętli i $y==strtr($x,$c)na pierwszy test.
Tytus

5

Galaretka , 18 bajtów

ẠaQ⁼µ€Ạ
z0EÐḟQZẋÇ$

Nienazwany link monadyczny (funkcja jednego wejścia) pobiera listę, która zwraca:
pobiera pustą listę w przypadkach falsey; lub
listę zawierającą dwie listy znaków w prawdziwych przypadkach.

Wypróbuj online! (stopka dzieli listę spacją, aby uniknąć wydrukowania reprezentacji wygładzonej)
... lub zobacz a pakiet testowy .

W jaki sposób?

ẠaQ⁼µ€Ạ - Link 1, valid?: mapping list
    µ€  - perform the code to the left for €ach mapping entry
Ạ       -     none of mapping entry falsey? (this & Main's z0 handle unequal input lengths)
  Q     -     deduplicate mapping entry
   ⁼    -     is equal to mapping list? (non-vectorising)
 a      -     and
      Ạ - none falsey (both mapping lists must pass that test)
        - The whole function returns 1 if the mapping list is acceptable, 0 if not

z0EÐḟQZẋÇ$ - Main link: list of strings
z0         - transpose with filler 0 (unequal lengths make pairs containing zeros)
   Ðḟ      - filter discard:
  E        -     all equal? (removes the untranslated character pairs)
     Q     - deduplicate (removes the repeated translation pairs)
      Z    - transpose (list of pairs to pair of lists)
         $ - last two links as a monad:
       ẋ   -     repeat list this many times:
        Ç  -         call last link (1) as a monad

5

Retina , 194 191 185 229 225 241 bajtów

.+
$&;$&
+`^\w(\w*;)\w
$1
^;\w.*|.+;;.*|;;

^((.)*)(.)(.*;(?<-2>.)*(?(2)(?!)))\3
$1$4
+`((.)(.)*)\2((.)*;.*(.)(?<-3>.)*(?(3)(?!)))\6((?<-5>.)*(?(5)(?!)))$
$1$4$7
^(.)*(.)(.)*(\2)?.*;(?<-1>.)*(?(1)(?!))(.)(?<-3>.)*(?(3)(?!))(?(4)(?!\5)|\5).*

Wypróbuj online!

Oddziela dane wejściowe ;. Wyjście jest również; oddzielone. Fałszywe dane wejściowe są oznaczone pustymi wyjściami.

Wiem, że to boleśnie gadatliwe, wciąż próbuję zmniejszyć bajty. Większość tych bajtów służy do usuwania fałszywych danych wejściowych.

Edycje

  • Okazuje się, że mój program miał znaczną wadę. Zostało to naprawione teraz, ale kosztem ponad 40 bajtów.

  • Znalazłem kolejny błąd, w którym mój program nie zadeklarował danych wejściowych jako a1;22fałszywych, ale po naprawieniu byłem w stanie utrzymać program poniżej 250 bajtów

Wyjaśnienie

(bardziej szczegółowe wyjaśnienia będą dostępne wkrótce)

Najpierw musimy sprawdzić, czy długości sznurków ai bsą takie same czy nie. Jeśli nie są, usuwamy wszystko.

Duplikuje dane wejściowe, aby zachować je podczas wykonywania testów długości.

.+                      Matches everything
$&;$&                   $& indicates the match, so $&;$& will duplicate the match and separate it with a semi-colon

Teraz w pętli usuwamy pierwszy znak ai pierwszy znak, baż jeden z ciągów stanie się pusty.

+`                     Repeatedly (until no more substitutions could be made) replace
  ^\w                   A word character (letter or number) at the beginning
     (\w*;)             Capture Group 1: matches any number of word characters and a semicolon
           \w           And a word character after the semi-colon
                       with
$1                      The result of the first capture group

Teraz są możliwości dla „przestrzeni wzorów”.

  • ;;abc Oba ciągi mają jednakową długość
  • def;;abc a jest dłuższy niż b
  • ;def;abc b jest dłuższy niż a

Teraz musimy opróżnić dane wejściowe, jeśli ciągi nie są tej samej długości (scenariusze 2 i 3). To właśnie robi poniższe podstawienie. Usuwa tekst pasujący do scenariuszy 2 i 3.

^;\w.*|.+;;.*|;;

To usuwa znaki, które nie są transliterowane w ciągach ai b. abc;1b2=>ac;12

^((.)*)(.)(.*;(?<-2>.)*(?(2)(?!)))\3
$1$4

Następnie musimy usunąć zduplikowane znaki. sese;1212=> se;12, ale zachowuje dane wejściowe takie jakaba;123

+`((.)(.)*)\2((.)*;.*(.)(?&lt;-3&gt;.)*(?(3)(?!)))\6((?&lt;-5&gt;.)*(?(5)(?!)))$
$1$4$7

Na koniec usuwamy dane wejściowe, jeśli istnieją zduplikowane znaki, które są odwzorowane na różne znaki, takie jak aba;123lub a1;22.

^(.)*(.)(.)*(\2)?.*;(?.)*(?(1)(?!))(.)(?.)*(?(3)(?!))(?(4)(?!\5)|\5).*

I wreszcie usuń zduplikowane znaki.


Za pomocą tych grup równoważących widzę!
Neil

@Neil Indeed! Skorzystałem również z tego, (?(1)(?!))czego nauczyłem się z twojej odpowiedzi :)
Kritixi Lithos

Zastanawiam się, czy krótsze byłoby najpierw usunięcie duplikatów, a następnie sprawdzenie pozostałych zestawów - po każdej stronie powinna pozostać tylko jedna litera ;.
Neil

@ Neil Znalazłem błąd podczas eksperymentowania z tym kodem. Rano przyjrzę się temu.
Kritixi Lithos

4

Galaretka , 28 26 bajtów

QL$€⁼L€
EÐḟQZK0Ç?
ZÇ0L€E$?

Wypróbuj online!

QL$€⁼L€      Checks validity of mapping
QL$€          number of unique characters in mapping
    ⁼         equals
     L€       number of characters in mapping

EÐḟQZK0Ç?  Writes valid mapping or 0
EÐḟ           filter maps where a = b
   Q          filter duplicate maps
    Z         zip by column [["ac"],["bd"]] => ["ab","cd"]
     K0Ç?   print if valid map, else print 0

ZÇ0L€E$?      main link: takes an array of 2 strings
Z              zip by column: ["ab", "cd"] => [["ac"],["bd"]]
 Ç     ?       print mapping if
   L€E$         all pairs are same length (returns 0 if initial strings were
  0             else 0

1
Witamy w PPCG! Skąd do cholery znasz już galaretkę z tylko 21 punktami? Bardzo imponujące!
Magic Octopus Urn

2
Dzięki. Rozejrzałem się trochę po stronie i wydawało się, że to fajny język do nauki.
layagyasz

05AB1E to kolejny łatwy i przyjemny do wypróbowania.
Magic Octopus Urn

3

Rubin, 133 bajty

->a,b{a.size!=b.size||(m=a.chars.zip b.chars).any?{|i,j|m.any?{|k,l|(i==k)^(j==l)}}?0:m.select{|x,y|x!=y}.uniq.transpose.map(&:join)}

Wypróbuj online!

Bardziej czytelnie:

->a, b{
    # Pair the letters in each string - [AB, AB, AB,...]
    pairs = a.chars.zip(b.chars)

    # If there's any combination of two pairs that share one character but not both,
    # or if the strings have different lengths, then the input's invalid.
    if a.size != b.size || pairs.any?{|i,j| pairs.any? {|k, l| (i==k)!=(j==l) }} 
        return 0 # 0 isn't actually falsy in Ruby, but this challenge allows it anyway
    end
    return pairs.select{|x,y| x != y} # Remove unchanged letters
                .uniq                 # Remove duplicates
                .transpose            # Change [AB, AB, AB] form to [AAA, BBB] form.
                .map(&:join)          # Convert the arrays back into strings
}

Tylko dla kopnięć, oto wersja 84-bajtowa w Gorubach, którą jest Ruby, ale z flagą golfową ustawioną podczas kompilacji interpretera. Między innymi pozwala skracać wywołania metod do ich najkrótszego unikalnego identyfikatora.

->a,b{a.sz!=b.sz||(m=a.ch.z b).ay?{|i,j|m.y?{|k,l|(i==k)^(j==l)}}?0:m.rj{|x,y|x==y}.u.tr.m(&:j)}

Dlaczego nie opublikować drugiej odpowiedzi z implementacją Goruby? Czy to nie jest akceptowany język golfa?
Magic Octopus Urn

@carusocomputing Jest całkowicie; wydawało mi się, że nie zasługuje na własną odpowiedź - jest dokładnie taka sama jak moja główna odpowiedź, tylko ze skrótami nazw metod. Być może, jeśli znajdę sposób, aby wykorzystać więcej różnic Goruby, opublikuję osobną odpowiedź.
Tutleman

3

Python 2 , 198,193,189,182,179,175,169, 165 bajtów

def f(a,b):
 r=([""]*2,0)[len(a)!=len(b)]
 for u,v in zip(a,b):
	if r:
		q,w=r
		f=q.find(u)
		if u!=v:r=(([q+u,w+v],r)[f>-1 and w[f]==v],0)[f<0 and v in w]
 print r

Wypróbuj online!

  • -4 bajty! dzięki mbomb007 za sugerowanie użycia tabulacji zamiast spacji.

  • zmodyfikowałem format wejściowy, ponownie dzięki mbomb007.


what do you mean by that? please stop making unwanted edits which doesnt add any value to answer!
Keerthana Prabhakaran

tab saved around 4 bytes! Thank you!
Keerthana Prabhakaran


And I made your program have each test case on a single line, which is extremely helpful to anyone testing your program.
mbomb007

I'd would have better if you could have mentioned that in your edit comment!
Keerthana Prabhakaran

3

Python 3.6, 211 185 181 178 bytes

Exits with an error for falsy results.

def f(x,y,d={}):
    for a,b in zip(x,y):1/(a not in d or b==d[a]or len(x)-len(y));d[a]=b;1/([*d.values()].count(b)<2)
    return map(''.join,zip(*[x for x in d.items()if x[0]!=x[1]]))

This requires Python 3.6, which you can run in a shell here.

You can test it without the correct output ordering on TIO here. (TIO doesn't have 3.6).

Ungolfed:

from collections import*
d=OrderedDict()                     # keep order
x,y=input()
if len(x)!=len(y):1/0               # equal lengths
for a,b in zip(x,y):
    if a in d and d[a]!=b:1/0       # no duplicate keys
    else:d[a]=b
    if d.values().count(b)>1:1/0    # no duplicate values
print map(''.join,zip(*[x for x in d.items()if x[0]!=x[1]])) # format, no no-ops

If only order didn't matter...


Shouldn't a1,12 return a1,12 instead of False? Under the Caveats section it is said that "a1" with translation table of [a1,12] evaluates to 12.
fergusq

1
Well, the program in your TIO link returns False. 1a 21 would also be wrong, as the oeder has to be preserved.
fergusq

@fergusq Fixed. But notice that you have a typo in your comment if that's the test case you're referring to, since you said a1,12 instead of a1,22.
mbomb007

I misunderstood you. You referred to the Caveats section in your question edit, but the Caveats section actually handles a different case – not the bijection rule. That confused me.
fergusq

It handles a different rule, but it still says that the result of that test case is false, which is what mattered.
mbomb007

2

Röda, 108 119 bytes

{c=[{_<>_|[[_,_]]|orderedUniq}()]d=[]e=[]c|_|{{d+=a;e+=b}if[a!=b]}for a,b[d,e]if[0,1]|{|n|c|[_[n]]|sort|count|[_2=1]}_}

Try it online!

This is a function that takes two lists of characters from the stream and pushes two lists to the stream.

This could be sorter if I was allowed to return pairs.

Explanation (out-dated):

{
    c=[{
        _<>_|       /* pull two lists and interleave them */
        [[_,_]]|    /* "unflat", create lists from pairs */
        orderedUniq /* remove duplicates */
    }()]            /* c is a list of the pairs */
    d=[]
    e=[]
    c| /* push the pairs to the stream */
    _| /* flat */
    {  /* for each pair (a, b): */
        { /* if a != b (remove "1-to-1 relations"):  */
            d+=a;
            e+=b
        }if[a!=b]
    }for a,b
    /* return d and e if no character is mapped to more than one character */
    [d,e]if c|[_[0]]|sort|count|[_2=1]
}

Here's an underscore solution that contains no variables (114 bytes):

{[[{_<>_}()|[[_,_]]|unorderedUniq]]|[[_()|_|[_]if[_1!=_2]],[_1()|_|[_2]if[_1!=_2]]]if[[_1()|_][::2],[_1()|_][1::2]]|[sort(_)|count|[_2=1]]}

That's a lot of underscores.


What does the <> do?
Kritixi Lithos

@KritixiLithos It's the interleave operator. a() <> b() is same as interleave([a()], [b()]) (or just interleave(a, b), if a and b are arrays).
fergusq

This fails the a1 22 => false test case. "all translations occur independent of each other, meaning this is falsy."
mbomb007

@mbomb007 I don't quite understand what you say? Do you mean it has to be a bijection, ie. no two characters must be mapped to a same character?
fergusq

Yes. That's what the question says. (Each character can only be used ONCE on each side of the translation)
mbomb007

1

AWK, 140 bytes

BEGIN{RS="(.)"}RT~/\W/{S=1}RT~/\w/&&S{if(RT!=x=A[++b]){if(B[z=RT]==""){B[z]=x
c=c x
d=d z}a=B[z]!=x?0:a}}!S{A[++a]=RT}END{if(a==b)print c,d}

Usage: Place code in FILE then:

awk -f FILE <<< "string1 string2"

The input strings need to be whitespace separated.

The output is empty if they fail, or 2 strings separated by a space.


1

k, 28 bytes

{$[(y?y)~x?x;+?(~=/)#x,'y;]}

Explanation:

{                          } /function that takes in two strings, x and y
 $[         ;            ;]  /if statement (to check if there is a mapping)
         x?x                 /first index of [each letter in x] in x
   (y?y)                     /first index of [each letter in y] in y
        ~                    /make sure they match
                     x,'y    /zip together the two strings
               (~=/)#        /remove equal pairs
              ?              /unique pairs only
             +               /transpose ("unzip", in a way)

1

APL (Dyalog) with AGL, 22 bytes

{≡/⍳⍨¨⍺⍵:↓⍉↑∪⍺(≠é,¨)⍵}

Try it online!

{} anonymous function:

 If…

  ⍺⍵ the arguments

  ⍳⍨¨ when self-indexed (i.e. the first occurrences of their elements in themselves)

  ≡/ are equivalent

: then:

  ⍺()⍵ apply the following tacit function to the arguments:

    concatenate corresponding elements (errors on mismatching lengths)

   é then filter by (é is just the primitive function /)

    where the strings are different

   unique (remove duplicates)

  ↓⍉↑ transpose list-of-pairs to pair-of-lists (lit. mix into table, transpose table, split into lists)

 else, do nothing


1
patiently awaits the explanation of this answer :P
Magic Octopus Urn

1
@carusocomputing I'm on it.
Adám

@carusocomputing OK?
Adám

I missed that reply, sorry! ↓⍉↑ still has me a little confused.
Magic Octopus Urn

1
@carusocomputing Maybe this helps? Note that in APL and J, a matrix is not the same as a list of lists.
Adám


0

PHP (>=7.1), 165 bytes

for([,$x,$y]=$argv;a&$c=$x[$i];$t[$c]=$d)$z+=($d=$y[$i++])&&$d==($t[$c]??$d);foreach($t as$a=>$b)$a==$b?:$r[$a]=$b;print_r($z<$i|array_unique($r)<$t||a&$y[$i]?0:$t);

prints 0 for falsy, associative array else. Run with -r or test it online.

breakdown

for([,$x,$y]=$argv;         # import arguments to $x and $y
    a&$c=$x[$i];            # loop through $x
    $t[$c]=$d)                  # 2. add pair to translation
$z+=                            # 1. increment $z if
    ($d=$y[$i++])&&             # there is a corresponding character in $y and
    $d==($t[$c]??$d);           # it equals a possible previous replacement
                            # remove identities from translation
foreach($t as$a=>$b)$a==$b?:$r[$a]=$b;
print_r(
    $z<$i                   # if not all tests passed
    |array_unique($t)<$t    # or there are duplicates in the translation
    ||a&$y[$i]              # or $y has more characters
    ?0                      # then print 0
    :$r                     # else print translation
);

Are associative arrays as Output allowed? Could you please add that it works above version 7.1
Jörg Hülsermann

@JörgHülsermann Output can be as an array or ..., so I´d say yes. Current PHP version is implicit for all my postings; but if I find something important to edit, I´ll add the version.
Titus

The valid cases shows only one meaning of array output. If associative arrays are also allowed I can save a few bytes. If it is allowed and array_unique($r)!=$r is in every case array_unique($r)<$r I will upvote your post alone for this trick. In the moment I am searching for an explanation
Jörg Hülsermann

@JörgHülsermann array_unique($t)<$t (had to change that because can to cnn is invalid) works, because array comparison (unlike string comparison) compares lengths before anything else.
Titus

The test can to cnn cost me 17 Bytes Forget my suggestion
Jörg Hülsermann
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.