Wprowadzenie
W przeszłości mieliśmy tutaj kilka podstawowych wyzwań związanych z konwersją, ale niewiele z nich zaprojektowano tak, aby poradzić sobie z liczbami o dowolnej długości (to znaczy liczbami, które są na tyle długie, że przekraczają typ danych liczb całkowitych). skomplikowane. Jestem ciekawy, jak można uzyskać taką zmianę kodu podstawowego.
Wyzwanie
Napisz program lub funkcję w wybranym języku, który może przekonwertować ciąg jednej bazy na ciąg innej bazy. Dane wejściowe powinny być liczbą do konwersji (ciąg znaków), z bazy (liczba bazy 10), na bazę (liczba bazy 10) oraz zestaw znaków (łańcuch znaków). Dane wyjściowe powinny być konwertowaną liczbą (ciągiem).
Niektóre dalsze szczegóły i zasady są następujące:
- Liczba do konwersji będzie nieujemną liczbą całkowitą (ponieważ
-
i.
może znajdować się w zestawie znaków). Podobnie będzie wynik. - Zera wiodące (pierwszy znak w zestawie znaków) powinny zostać przycięte. Jeśli wynik wynosi zero, powinna pozostać pojedyncza cyfra zero.
- Minimalny obsługiwany zakres podstawowy wynosi od 2 do 95, składający się z drukowalnych znaków ascii.
- Dane wejściowe dla liczby do konwersji, zestaw znaków i dane wyjściowe muszą być typu danych ciągu. Podstawy muszą być typu danych liczb całkowitych typu base-10 (lub liczby całkowite zmiennoprzecinkowe).
- Długość ciągu liczb wejściowych może być bardzo duża. Trudno oszacować rozsądne minimum, ale spodziewaj się, że będzie w stanie obsłużyć co najmniej 1000 znaków i wypełnić 100 znaków w mniej niż 10 sekund na przyzwoitej maszynie (bardzo hojny dla tego rodzaju problemu, ale nie chcę prędkość, na której należy się skupić).
- Nie można używać wbudowanych funkcji zmiany bazy.
- Zestaw znaków może być wprowadzany w dowolnym układzie, nie tylko typowym 0-9a-z ... itd.
- Załóż, że zostaną użyte tylko prawidłowe dane wejściowe. Nie martw się obsługą błędów.
Zwycięzca zostanie określony na podstawie najkrótszego kodu spełniającego kryteria. Zostaną oni wybrani w ciągu co najmniej 7 dni bazowych-10, lub jeśli / kiedy będzie wystarczająco dużo zgłoszeń. W przypadku remisu zwycięży kod, który działa szybciej. Jeśli wystarczająco blisko prędkości / wydajności, odpowiedź, która nadeszła wcześniej, wygrywa.
Przykłady
Oto kilka przykładów danych wejściowych i wyjściowych, które Twój kod powinien obsługiwać:
F("1010101", 2, 10, "0123456789")
> 85
F("0001010101", 2, 10, "0123456789")
> 85
F("85", 10, 2, "0123456789")
> 1010101
F("1010101", 10, 2, "0123456789")
> 11110110100110110101
F("bababab", 2, 10, "abcdefghij")
> if
F("10", 3, 2, "0123456789")
> 11
F("<('.'<)(v'.'v)(>'.'>)(^'.'^)", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? ")
> !!~~~~~~~!!!~!~~!!!!!!!!!~~!!~!!!!!!~~!~!~!!!~!~!~!!~~!!!~!~~!!~!!~~!~!!~~!!~!~!!!~~~~!!!!!!!!!!!!~!!~!~!~~~~!~~~~!~~~~~!~~!!~~~!~!~!!!~!~~
F("~~~~~~~~~~", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? ")
> ~
F("9876543210123456789", 10, 36, "0123456789abcdefghijklmnopqrstuvwxyz")
> 231ceddo6msr9
F("ALLYOURBASEAREBELONGTOUS", 62, 10, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
> 6173180047113843154028210391227718305282902
F("howmuchwoodcouldawoodchuckchuckifawoodchuckcouldchuckwood", 36, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? ")
> o3K9e(r_lgal0$;?w0[`<$n~</SUk(r#9W@."0&}_2?[n
F("1100111100011010101010101011001111011010101101001111101000000001010010100101111110000010001001111100000001011000000001001101110101", 2, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? ")
> this is much shorter
You cannot use built in change-of-base functions to convert the entire input string/number at once
? W szczególności, czy mogę użyć wbudowanego do konwersji danych wejściowych na bazę pośrednią? Czy mogę użyć wbudowanego programu do konwersji na bazę docelową? Czy coś podobnegoconvert input with canonical form for given base; convert to base 10; convert to target base; convert back to specified character set with string replacement
?Odpowiedzi:
CJam, 34 bajty
Format wejściowy jest
input_N alphabet input_B output_B
w osobnej linii.Uruchom wszystkie przypadki testowe.
Wyjaśnienie
Działa to dla tej samej liczby bajtów:
Jedyna różnica polega na tym, że budujemy ciąg zamiast zbierać wszystko ze stosu i odwracać go.
źródło
Python 2 ,
11511410610594 bajtówSugestie dotyczące gry w golfa mile widziane. Wypróbuj online!
Edycja: -9 bajtów dzięki mbomb007. -2 bajty dzięki FlipTack.
Nie golfowany:
źródło
while z:s=d[z%t]+s;z/=t
oszczędza 9 bajtów.z=0
is=''
w deklaracji funkcji, aby zapisać bajtów.print
zamiastreturn
jest dozwolone domyślnie .Poważnie, 50 bajtów
Hex Dump:
Jestem z tego dumny pomimo jego długości. Dlaczego? Ponieważ zadziałało idealnie przy drugiej próbie. Napisałem to i debugowałem w dosłownie 10 minut. Zwykle debugowanie programu Poważnie zajmuje godzinę.
Wyjaśnienie:
źródło
C (funkcja) z biblioteką GMP , 260
Okazało się to dłużej, niż się spodziewałem, ale i tak jest.
mpz_*
Rzeczy naprawdę zjada dużo bajtów. Próbowałem#define M(x) mpz_##x
, ale to dało zysk netto 10 bajtów.Funkcja
F()
jest punktem wejścia. Konwertuje ciąg wejściowy nampz_t
kolejne mnożenie przezfrom
-base i dodanie indeksu danej cyfry na liście cyfr.Ta funkcja
O()
jest rekurencyjną funkcją wyjściową. Każda rekurencja zmienia sięmpz_t
wedługto
-base. Ponieważ daje to cyfry wyjściowe w odwrotnej kolejności, rekurencja skutecznie umożliwia zapisanie cyfr na stosie i wyjście w prawidłowej kolejności.Kierowca testowy:
Dodano nowe linie i wcięcia dla czytelności.
źródło
JavaScript (ES6), 140 bajtów
W przeciwieństwie do kodu @ Mwr247 (który używa arytmetyki base-f do dzielenia s za każdym razem za każdym razem, zbierając resztę w miarę upływu czasu) Używam arytmetyki base-t do pomnożenia odpowiedzi za każdym razem za każdym razem, dodając każdą cyfrę s w miarę upływu czasu.
Nie golfowany:
źródło
Ruby,
11311210598979587 bajtówW pewnym sensie podwoiłem swoją odpowiedź w Pythonie (jakoś), więc oto odpowiedź Ruby. Siedem dodatkowych bajtów dzięki manatwork , kolejny bajt dzięki Martinowi Büttnerowi i 8 kolejnych bajtów dzięki cia_rana .
Nie golfowany:
źródło
s=d[z%t]+s;z/=t
zamiastz,m=z.divmod t;s=d[m]+s
?APL, 10 bajtów
To jest operator APL. W APL
⍵
i⍺
są używane do przekazywania wartości, podczas gdy⍵⍵
i⍺⍺
są zwykle używane do przekazywania funkcji. Nadużywam tego, aby mieć 3 argumenty.⍺⍺
jest lewym argumentem,⍵⍵
jest „wewnętrznym” prawym argumentem i⍵
prawym „zewnętrznym” argumentem.Gruntownie:
⍺(⍺⍺{...}⍵⍵)⍵
Następnie wystarczy
⍳
znaleźć pozycje ciągu wejściowego w tabeli „z”, a następnie użyć[]
do indeksowania do tabeli „do” z tymi pozycjami.Przykład:
źródło
JavaScript (ES6), 175 bajtów
Zrozumiałem, że już wystarczająco długo mogę przesłać ten, który stworzyłem, aby stworzyć przykłady. Może później spróbuję zagrać w golfa.
źródło
Japt, 9 bajtów
Spróbuj
źródło