Mapowanie między liczbą całkowitą a wymownym słowem

10

Cel, powód

Chodzi o to, aby podać kod niezbędny do odwzorowania 32-bitowej liczby całkowitej na / z wymawianego słowa o długości maksymalnie 9 znaków. Może to być przydatne na przykład w celu ułatwienia zapamiętania numeru seryjnego lub wpisania formularza.

Wymagana jest zarówno metoda translacji liczby całkowitej na odpowiednie słowo, jak i translacja słowa z powrotem na odpowiednią liczbę całkowitą.

Zasady

Pomiędzy liczbami całkowitymi a słowami musi istnieć odwzorowanie jeden na jeden, a cały zestaw 32-bitowych liczb całkowitych (lub, inaczej mówiąc, dowolna liczba całkowita od 0 do 4294967295) musi być odwzorowalna. Chociaż oczywiście nie wszystkie słowa będą znaczące, a wprowadzanie słów, które nie są odwzorowane na liczbę całkowitą, może mieć nieokreślone zachowanie.

Możesz swobodnie decydować, który zestaw wyrazów „wymawialnych” ma znaczenie, i jak wykonać mapowanie, ale słowa muszą co najmniej przestrzegać następujących zasad:

  • Jako znaki należy używać tylko podstawowych 26 liter (A ... Z). Akcenty, obudowa itp. Nie powinny być używane do rozszerzania możliwych kombinacji.
  • Maksymalnie 9 znaków na słowo.
  • dwie spółgłosek (BCDFGHJKLMNPQRSTVWXZ - 20 możliwości) nie powinny być umieszczone obok siebie (muszą być otoczone samogłosek).
  • dwie samogłoski (AEIOUY - 6 możliwości) nie powinny być umieszczane obok siebie (muszą być otoczone spółgłosek).

Uwaga: najprostszy schemat, w którym wszystkie słowa są konstruowane jako CVCVCVCVC( Cspółgłoska i Vsamogłoska) daje 4147200000 kombinacji, a 32-bitowa liczba całkowita ma 4294967296 możliwych wartości, więc to nie wystarczy. Musisz zwiększyć liczbę kombinacji, dopuszczając krótsze słowa lub też dopuszczając VCVCVCVCVkombinacje.

Obowiązują inne standardowe zasady, a standardowe luki są zabronione.

Wejścia wyjścia

Do każdego zgłoszenia należy podać dwa fragmenty kodu:

  • Taki, który przyjmuje liczbę całkowitą jako argument / dane wejściowe i zwraca / drukuje odpowiednie słowo
  • Taki, który przyjmuje słowo jako argument / input i zwraca / wypisuje odpowiednią liczbę całkowitą

Alternatywnie możesz przesłać pojedynczy fragment kodu, który obsługuje obie operacje:

  • Gdy podano liczbę całkowitą jako dane wejściowe, wyprowadza odpowiednie słowo
  • Gdy podano ciąg jako dane wejściowe, wypisuje odpowiednią liczbę całkowitą

Warunki wygranej

To jest , odpowiedź, która ma najmniej bajtów (przy sumowaniu obu fragmentów kodu, dla rozwiązań wybierających oddzielne fragmenty kodu) wygrywa.

ciemny
źródło
Czy są jakieś ograniczenia przestrzenne lub czasowe? Czy musimy zmieścić się w 32 GB pamięci?
John Dvorak,
@JanDvorak Cóż, powinniśmy być w stanie przetestować Twój program na „standardowym” komputerze. Ale algorytm powinien być prosty. Co masz na myśli, że wymaga tak dużej ilości pamięci?
przyciemniony
Mógłbym po prostu wygenerować wszystkie możliwe dziewięcioliterowe słowa, które pasują do Twojej formuły, a następnie zindeksować zestaw lub przeprowadzić wyszukiwanie binarne.
John Dvorak,
@JanDvorak Muszę przyznać, że o tym nie myślałem. Bardziej myślałem o rozwiązaniach, które zasadniczo przeprowadzały konwersję base-26, z pewnymi poprawkami, aby spełnić ograniczenie samogłoski / spółgłoski. Ale w jakiś sposób wątpię, by „brutalny” sposób, jaki miałeś na myśli, może być skuteczny w golfa. W każdym razie, jeśli naprawdę muszę to wyjaśnić, powiedzmy, że nie wolno ci przydzielić więcej niż 4 GB pamięci.
dim
Możesz wymagać od autorów odpowiedzi uruchomienia ich kodu dla niektórych z góry określonych wartości (0,1,10,2 ** 32-1 i podobnych), a następnie z powrotem i uwzględnienia wyników w odpowiedzi.
John Dvorak,

Odpowiedzi:

1

JavaScript (ES6), 205 bajtów

p=>(a='bcdfghjklmnpqrstvwxzaeiouy',1/p)?[...Array(9)].map(_=>r=a[p%(n=26-n)+(p=p/n|0,n<7)*20]+r,n=p>(p%=4e9)?20:6,r='')&&r:[...p].map(c=>r=r*(n=26-n)+a.search(c)%20,n=a.search(p[r=0])<20?6:20)&&r+(n<7)*4e9

Punkt odcięcia między CVCVCVCVC i VCVCVCVCV wynosi 4e9, więc zaczyna się mylnie przy 5244160000 (wprowadzanie numeryczne) lub zesuwurib(wprowadzanie ciągów).

Neil
źródło
Sześć miesięcy później ... Przyznam ci punkty akceptacji, ponieważ jesteś najkrótszy (i nie mogę zaakceptować odpowiedzi rturnbull, która nie spełnia wyjaśnienia, które poczyniłem w komentarzach).
dim
2

PHP, 353 bajtów

Kodowanie + dekodowanie

is_numeric($argn)zawiera wartość logiczną. Prawdą jest, jeśli wejście jest liczbą całkowitą.

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);if(is_numeric($a=$argn)){$r=($a)%26<6?$v[$a%26]:$c[$a%26-6];$a=$a/26^0;while($a){$z=count($t=in_array($r[0],$v)?$c:$v);$r=$t[$n=$a%$z].$r;$a=$a/$z^0;}echo$r;}else{for($p=1;$i++<strlen($a);){$u=($b=in_array($a[-$i],$c))?$c:$v;$s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0);$p*=$i>1?count($u):26;}echo$s;}

PHP, 190 bajtów (kodowanie) + 195 bajtów (dekodowanie) = 385 bajtów

Kodowanie

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);$r=($a=$argn)%26<6?$v[$a%26]:$c[$a%26-6];$a=$a/26^0;while($a){$z=count($t=in_array($r[0],$v)?$c:$v);$r=$t[$n=$a%$z].$r;$a=$a/$z^0;}echo$r;

5391360000 = 26 * 120 ** Dostępne są 4 kombinacje

Kodowanie wersji online bez E_NOTICE

Rozszerzony

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);
sort($c); # End of Prepare the two array
$r=($a=$argn)%26<6?$v[$a%26]:$c[$a%26-6]; #base 26 decision input mod 26 <6 end with vowel
$a=$a/26^0; #integer division input with 26
while($a){
    $z=count($t=in_array($r[0],$v)?$c:$v); # use vowel if last entry is consonant and viceversa
    $r=$t[$n=$a%$z].$r; # base 6 or base 20 decision
    $a=$a/$z^0; # divide through base
}echo$r; # Output result

Dane wejściowe => Dane wyjściowe

4294967296 => TYPYQACOV 
333 => DAT 
1 => E 
7 => C 
4294967276 => UTOPOQAMI

Jeśli trzeba zawsze 9 wynik Byte proszę wymienić while($a)z while(strlen($r)<9)+ 10 bajtów

Rozszyfrowanie

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);for($p=1;$i++<strlen($a=$argn);){$u=($b=in_array($a[-$i],$c))?$c:$v;$s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0);$p*=$i>1?count($u):26;}echo$s;

Rozszerzony

$c=array_diff(range("A","Z"),$v=["A","E","I","O","U","Y"]);
sort($c); # End of Prepare the two array
for($p=1;$i++<strlen($a=$argn);){ 
    $u=($b=in_array($a[-$i],$c))?$c:$v; # find use array for $a[-$i]
    $s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0); # sum value
    $p*=$i>1?count($u):26; # raise multiple for next item
}echo$s;

Dane wejściowe => Dane wyjściowe

ABABABABE => 1
E => 1
UTOPOQAMI => 4294967276
BABABADAT => 333
DAT => 333
TYPYQACOV => 4294967296

Dekodowanie wersji online bez E_NOTICE

Dodatkowa kontrola

Jeśli potrzebujemy sprawdzić, czy ciąg jest prawidłowy.

Dodaj $x.=$b?:0;na końcu pętli dekodującej + 10 bajtów

Zastąpić echo$s;w echo!preg_match('#([01])\1$#',$x)?$s:_;+ 32 bajtów

Jörg Hülsermann
źródło
1

R, 165 bajtów

Kodowanie i dekodowanie w jednej funkcji.

Ta funkcja wykorzystuje metodę brute-force do tworzenia wszystkich możliwych wartości, a następnie po prostu zwraca indeks, gdy podano dane wejściowe ciągu i zwraca ciąg, gdy dane wejściowe są liczbami całkowitymi. W rezultacie jest bardzo wolny i zużywa ponad 16 GB pamięci!

function(x){i=c(1,5,9,15,21,25)
d=apply(expand.grid(c<-letters[-i],v<-letters[i],c,v,c,v,c,v,c(c,"")),1,paste,collapse="")
`if`(mode(x)=="numeric",d[x],which(d==x))}

Możliwe są 4 354 560 000 wartości. Obejmuje to wszystkie ciągi formularza CVCVCVCV (C), przy czym ostatnie C jest opcjonalne.

rturnbull
źródło
@ mbomb007 Gigabytes, przepraszam za literówkę. Funkcja wykonuje zarówno kodowanie, jak i dekodowanie w zależności od tego, czy argument jest łańcuchem, czy liczbą całkowitą. Zaktualizowałem post, aby to wyjaśnić.
rturnbull
Czy downvoter może zostawić komentarz sugerujący poprawę? Dzięki.
rturnbull
1
W komentarzach do pytania dim wyjaśnia, że ​​nie można użyć więcej niż 4 GB pamięci ....
Socratic Phoenix