Dekompresja sztuki ASCII od liczby bazowej n


24

Jest to inspirowane odpowiedzią 05AB1E autorstwa Magic Octupus Urn .

Biorąc pod uwagę dwa argumenty, dodatnią liczbę całkowitą i ciąg / listę znaków:

  1. Przetłumacz liczbę na base-n, gdzie n jest długością łańcucha.
  2. Dla każdego znaku zamień każdy wygląd indeksu tego znaku w liczbie podstawowej n na ten znak.
  3. Wydrukuj lub zwróć nowy ciąg.

Przykłady:

Input:
2740, ["|","_"]
2740 -> 101010110100 in base 2
     -> Replace 0s with "|" and 1s with "_"
Output: _|_|_|__|_||

Input:
698911, ["c","h","a","o"]
698911 ->  2222220133 in base 4
       ->  Replace 0s with "c", 1s with "h", 2s with "a", and 3s with "o"
Output -> "aaaaaachoo"

Input:
1928149325670647244912100789213626616560861130859431492905908574660758972167966, [" ","\n","|","_","-"]
Output:
    __   __    
   |  |_|  |   
___|       |___
-   -   -   -  
 - - - - - - - 
- - - - - - - -
_______________

Input: 3446503265645381015412, [':', '\n', '.', '_', '=', ' ', ')', '(', ',']
Output:
_===_
(.,.)
( : )
( : )

Zasady:

  • IO jest elastyczny .
    • Możesz wziąć liczbę w dowolnej bazie, o ile jest ona spójna między danymi wejściowymi
    • Lista znaków musi być jednak indeksowana przez 0, gdzie 0 to pierwszy znak, a n-1 to ostatni
  • Możliwymi znakami mogą być dowolne znaki ASCII do wydruku oraz białe znaki, takie jak tabulatory i znaki nowej linii
  • Podana lista znaków będzie miała długość z zakresu 2-10włącznie. Oznacza to, że najmniejsza podstawa jest binarna, a największa jest dziesiętna ( nie ma tu przykrych liter )
  • Standardowe luki są zabronione
  • Nie wahaj się odpowiedzieć, nawet jeśli Twój język nie obsługuje większych przypadków testowych.

Ponieważ jest to , wygrywa najkrótszy kod dla każdego języka. ( Wiem, że wszystkie języki gry w golfa mają wbudowane jeden bajt ;)


Piaskownica (usunięto)
Jo King

3
Dzień dobry, czuję się zaszczycony. 05AB1E ascii-art było kiedyś moim ulubionym.
Magic Octopus Urn

możesz stworzyć nowe wyzwanie: znajdź permutację znaków w tablicy, aby zminimalizować liczbę :)
mazzy

Odpowiedzi:


8

05AB1E , 7 6 bajtów

gв¹sèJ

Ponieważ została zainspirowana odpowiedzią 05AB1E, odpowiedź podana w 05AB1E wydaje się odpowiednia. :)

-1 bajt dzięki @Enigma , usuwając foreach i robiąc to pośrednio.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

g         # `l`: Take the length of the first (string) input
 в        # And then take the second input in base `l`
          # For each digit `y` of this base-converted number:
  ¹sè     #  Push the `y`'th character of the first input
     J    # Join everything together (and output implicitly)

1
gв¹sèJaby zapisać bajt.
Emigna,

@Emigna Thanks. Nie mogę uwierzyć, że teraz nie myślałem o ¹sèsobie ... (Wiedziałem, że zmiana na ?a Jda w tym przypadku ten sam
efekt

6

Java 8, 72 50 bajtów

a->n->n.toString(a.length).chars().map(c->a[c-48])

-22 bajty dzięki @ OlivierGrégoire , zwracając IntStreamzamiast drukowania bezpośrednio.

Wypróbuj online .

Wyjaśnienie:

a->n->                  // Method with char-array and BigInteger parameters
  n.toString(a.length)  //  Convert the input-number to Base `amount_of_characters`
   .chars()             //  Loop over it's digits (as characters)
   .map(c->a[c          //   Convert each character to the `i`'th character of the input
              -48])     //   by first converting the digit-character to index-integer `i`

2
a->n->n.toString(a.length).chars().map(c->a[c-48])(50 bajtów), ponieważ „IO jest elastyczny”
Olivier Grégoire,

String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";}(69 bajtów) rekurencyjny, dla zabawy.
Olivier Grégoire,

6

Python 3 , 49 bajtów

Nie mogę jeszcze komentować, więc zamieszczam odpowiedź w języku Python 2 dostosowaną do języka Python 3.5.

f=lambda n,s:n and f(n//len(s),s)+s[n%len(s)]or''

2
Witamy w PPCG! Czuć się swobodnie zawierać odnośnik TIO aby pomóc zaprezentować swoje rozwiązanie.
Jo King

5

Japt, 2 bajty

Może przyjąć drugie wejście jako tablicę lub ciąg znaków. Pomija 2 ostatnie przypadki testowe, ponieważ liczby przekraczają maksymalną liczbę całkowitą JavaScript. Wymień ssię ìdo wyjścia tablicę znaków zamiast.

sV

Spróbuj


5

Haskell , 40 39 bajtów

0!_=[]
n!l=cycle l!!n:div n(length l)!l

Wypróbuj online!

Ponieważ Inttyp Haskella jest ograniczony 9223372036854775807, nie udaje się to w przypadku większych liczb.

-1 bajt dzięki Laikoni .

Nie golfił

(!) :: Int -> [Char] -> [Char]

0 ! _ = []  -- If the number is 0, we reached the end. Base case: empty string
n ! l = 
  let newN = (n `div` length l) in   -- divide n by the base
    cycle l!!n                       -- return the char encoded by the LSD ... 
    : newN!l                         -- ... prepended to the rest of the output (computed recursively)

Wypróbuj online!


Fajny pomysł do użycia cyclezamiast mod! div n(length l)zapisuje bajt.
Laikoni

4

MATL , 2 bajty

YA

Wypróbuj online!

Dane wejściowe to liczba i ciąg znaków.

Nie udaje się przekroczyć liczb z 2^53powodu precyzji zmiennoprzecinkowej.

Wyjaśnienie

Co YAwiadomo, wbudowana (podstawowa konwersja z określonymi symbolami docelowymi).


4

JavaScript (ES6), 48 bajtów

Pobiera dane wejściowe w składni curry (c)(n), gdzie c jest listą znaków, a n jest liczbą całkowitą.

Bezpieczny tylko dla n <2 53 .

c=>n=>n.toString(c.length).replace(/./g,i=>c[i])

Wypróbuj online!


JavaScript (ES6), 99 bajtów

Z obsługą dużych liczb całkowitych

Pobiera dane wejściowe w składni curry (c)(a), gdzie c jest listą znaków, a a jest liczbą cyfr dziesiętnych (jako liczb całkowitych).

c=>g=(a,p=0,b=c.length,r=0)=>1/a[p]?g(a.map((d,i)=>(r=d+r*10,d=r/b|0,r%=b,d|i-p||p++,d)),p)+c[r]:''

Wypróbuj online!


4

x86 32-bitowy kod maszynowy (32-bitowe liczby całkowite): 17 bajtów.

(zobacz także inne wersje poniżej, w tym 16 bajtów dla wersji 32-bitowej lub 64-bitowej, z konwencją wywoływania DF = 1).

Dzwoniący przekazuje argumenty do rejestrów, w tym wskaźnik do końca bufora wyjściowego (jak moja odpowiedź C ; zobacz to w celu wyjaśnienia i wyjaśnienia algorytmu) . Wewnętrzny glibc _itoarobi to , więc nie jest on przeznaczony tylko do gry w golfa kodu. Rejestry przekazujące arg są zbliżone do x86-64 System V, z tym wyjątkiem, że mamy arg w EAX zamiast EDX.

Po powrocie EDI wskazuje na pierwszy bajt łańcucha C zakończonego na 0 w buforze wyjściowym. Zwykle rejestrem wartości zwracanej jest EAX / RAX, ale w języku asemblera można użyć dowolnej konwencji wywoływania dogodnej dla funkcji. ( xchg eax,edina końcu dodaje 1 bajt).

Dzwoniący może obliczyć jawną długość, jeśli chce, z buffer_end - edi. Ale nie sądzę, abyśmy mogli usprawiedliwić pominięcie terminatora, chyba że funkcja faktycznie zwróci zarówno wskaźniki początkowe + końcowe, jak i wskaźnik + długość. Pozwoliłoby to zaoszczędzić 3 bajty w tej wersji, ale nie sądzę, aby było to uzasadnione.

  • EAX = n = liczba do dekodowania. (Dla idiv. Pozostałe argumenty nie są domyślnymi operandami.)
  • EDI = koniec bufora wyjściowego (wersja 64-bitowa nadal używa dec edi, więc musi być w niskim 4GiB)
  • ESI / RSI = tablica odnośników, inaczej LUT. nie zatkany.
  • ECX = długość stołu = podstawa. nie zatkany.

nasm -felf32 ascii-compress-base.asm -l /dev/stdout | cut -b -30,$((30+10))- (Ręcznie edytowane w celu zmniejszenia komentarzy, numeracja linii jest dziwna).

   32-bit: 17 bytes        ;  64-bit: 18 bytes
                           ; same source assembles as 32 or 64-bit
 3                         %ifidn __OUTPUT_FORMAT__, elf32
 5                         %define rdi edi
 6   address               %define rsi esi
11          machine        %endif
14          code           %define DEF(funcname) funcname: global funcname
16          bytes           
22                         ;;; returns: pointer in RDI to the start of a 0-terminated string
24                         ;;; clobbers:; EDX (tmp remainder)
25                         DEF(ascii_compress_nostring)
27 00000000 C60700             mov     BYTE [rdi], 0
28                         .loop:                    ; do{
29 00000003 99                 cdq                    ; 1 byte shorter than   xor edx,edx / div
30 00000004 F7F9               idiv    ecx            ; edx=n%B   eax=n/B
31                         
32 00000006 8A1416             mov     dl, [rsi + rdx]   ; dl = LUT[n%B]
33 00000009 4F                 dec     edi               ; --output  ; 2B in x86-64
34 0000000A 8817               mov     [rdi], dl         ; *output = dl
35                         
36 0000000C 85C0               test    eax,eax           ; div/idiv don't write flags in practice, and the manual says they're undefined.
37 0000000E 75F3               jnz     .loop         ; }while(n);
38                         
39 00000010 C3                 ret
           0x11 bytes = 17
40 00000011 11             .size: db $ - .start

Zaskakujące jest to, że najprostsza wersja zasadniczo bez kompromisów prędkości / rozmiaru jest najmniejsza, ale std/ cldkosztuje 2 bajty, stosbaby przejść w kolejności malejącej i nadal przestrzegać wspólnej konwencji wywoływania DF = 0. (A STOS zmniejsza się po przechowywaniu, pozostawiając wskaźnik wskazujący jeden bajt za niski na wyjściu z pętli, co kosztuje dodatkowe bajty do obejścia.)

Wersje:

Wymyśliłem 4 znacząco różne sztuczki implementacyjne (używając prostego movload / store (powyżej), używając lea/ movsb(schludny, ale nie optymalny), używając xchg/ xlatb/ stosb/ xchgi takiego, który wchodzi do pętli z nakładającym się instrukcją. Zobacz kod poniżej) . Ostatni potrzebuje 0znaku końca w tablicy odnośników, aby skopiować jako terminator łańcucha wyjściowego, więc liczę to jako +1 bajt. W zależności od wersji 32/64-bitowej (1-bajtowej inclub nie) oraz od tego, czy możemy założyć, że zestawy wywołujące DF = 1 ( stosbmalejąco) lub cokolwiek innego, różne wersje są (powiązane) najkrótsze.

DF = 1 do przechowywania w kolejności malejącej sprawia, że ​​wygrana dla xchg / stosb / xchg, ale dzwoniący często tego nie chce; Wydaje się, że przenoszenie pracy na osobę dzwoniącą jest trudne do uzasadnienia. (W przeciwieństwie do niestandardowych rejestrów przechodzących argumenty i zwracających wartość, które zwykle nie kosztują dodatkowego programu wywołującego asm). Ale w 64-bitowym kodzie cld/ scasbdziała inc rdi, unikając obcięcia wskaźnika wyjściowego do 32-bitowego, więc czasami niewygodne jest zachowanie DF = 1 w 64-bitowych funkcjach czyszczenia. . (Wskaźniki do statycznego kodu / danych są 32-bitowe w plikach wykonywalnych innych niż PIE x86-64 w Linuksie i zawsze w ABI Linux x32, więc w niektórych przypadkach można używać wersji x86-64 używającej 32-bitowych wskaźników.) ta interakcja sprawia, że ​​interesujące jest spojrzenie na różne kombinacje wymagań.

  • IA32 z DF = 0 na konwencji wywoływania wejścia / wyjścia: 17B ( nostring) .
  • IA32: 16B (z konwencją DF = 1: stosb_edx_arglub skew) ; lub z przychodzącym DF = dontcare, pozostawiając ustawione: 16 + 1Bstosb_decode_overlap lub 17Bstosb_edx_arg
  • x86-64 z 64-bitowymi wskaźnikami i DF = 0 w konwencji wywoływania wejścia / wyjścia: 17 + 1 bajtów ( stosb_decode_overlap) , 18B ( stosb_edx_arglub skew)
  • x86-64 z 64-bitowymi wskaźnikami, inna obsługa DF: 16B (DF = 1 skew) , 17B ( nostringz DF = 1, używając scasbzamiast dec). 18B ( stosb_edx_argzachowanie DF = 1 z 3 bajtami inc rdi).

    Lub jeśli pozwolimy na powrót wskaźnika do 1 bajtu przed ciągiem, 15B ( stosb_edx_argbez inckońca). Wszystko gotowe do ponownego wywołania i rozwinięcia kolejnego łańcucha do bufora z inną bazą / tabelą ... Ale to miałoby większy sens, gdybyśmy nie zachowali zakończenia 0, a ty możesz umieścić ciało funkcji w pętli, więc to naprawdę osobny problem.

  • x86-64 z 32-bitowym wskaźnikiem wyjściowym, DF = 0 konwencja wywoływania: brak poprawy w stosunku do 64-bitowego wskaźnika wyjściowego, ale nostringpowiązanie 18B ( ) teraz.

  • x86-64 z 32-bitowym wskaźnikiem wyjściowym: brak poprawy w stosunku do najlepszych 64-bitowych wersji wskaźnika, więc 16B (DF = 1 skew). Lub ustawić DF = 1 i pozostawić, 17B dla skewz, stdale nie cld. Lub 17 + 1B dla stosb_decode_overlapz inc edina końcu zamiast cld/ scasb.

Z konwencją wywoływania DF = 1: 16 bajtów (IA32 lub x86-64)

Wymaga DF = 1 na wejściu, pozostawia to ustawienie. Mało prawdopodobne , przynajmniej na podstawie funkcji. Robi to samo co powyższa wersja, ale z xchg, aby uzyskać resztę do / z AL przed / po XLATB (wyszukiwanie tabeli z R / EBX jako bazą) i STOSB ( *output-- = al).

Z normalnym DF = 0 na konwencji wejścia / wyjścia, / / wersja ma 18 bajtów dla kodu 32 i 64-bitowych i 64-bitowych jest czyste (współpracuje z 64-bitowego wskaźnika wyjściowego).stdcldscasb

Zauważ, że argumenty wejściowe znajdują się w różnych rejestrach, w tym RBX dla tabeli (dla xlatb). Zauważ też, że ta pętla zaczyna się od zapisania AL, a kończy na ostatnim znaku, który nie został jeszcze zapisany (stąd movna końcu). Pętla jest więc „wypaczona” w stosunku do innych, stąd nazwa.

                            ;DF=1 version.  Uncomment std/cld for DF=0
                            ;32-bit and 64-bit: 16B
157                         DEF(ascii_compress_skew)
158                         ;;; inputs
159                             ;; O in RDI = end of output buffer
160                             ;; I in RBX = lookup table  for xlatb
161                             ;; n in EDX = number to decode
162                             ;; B in ECX = length of table = modulus
163                         ;;; returns: pointer in RDI to the start of a 0-terminated string
164                         ;;; clobbers:; EDX=0, EAX=last char
165                         .start:
166                         ;    std
167 00000060 31C0               xor    eax,eax
168                         .loop:                    ; do{
169 00000062 AA                 stosb
170 00000063 92                 xchg    eax, edx
171                         
172 00000064 99                 cdq                    ; 1 byte shorter than   xor edx,edx / div
173 00000065 F7F9               idiv    ecx            ; edx=n%B   eax=n/B
174                         
175 00000067 92                 xchg    eax, edx       ; eax=n%B   edx=n/B
176 00000068 D7                 xlatb                  ; al = byte [rbx + al]
177                         
178 00000069 85D2               test    edx,edx
179 0000006B 75F5               jnz     .loop         ; }while(n = n/B);
180                         
181 0000006D 8807               mov     [rdi], al     ; stosb would move RDI away
182                         ;    cld
183 0000006F C3                 ret

184 00000070 10             .size: db $ - .start

Podobna nieskrzywiona wersja przekracza EDI / RDI, a następnie go naprawia.

                            ; 32-bit DF=1: 16B    64-bit: 17B (or 18B for DF=0)
70                         DEF(ascii_compress_stosb_edx_arg)  ; x86-64 SysV arg passing, but returns in RDI
71                             ;; O in RDI = end of output buffer
72                             ;; I in RBX = lookup table  for xlatb
73                             ;; n in EDX = number to decode
74                             ;; B in ECX = length of table
75                         ;;; clobbers EAX,EDX, preserves DF
76                             ; 32-bit mode: a DF=1 convention would save 2B (use inc edi instead of cld/scasb)
77                             ; 32-bit mode: call-clobbered DF would save 1B (still need STD, but INC EDI saves 1)
79                         .start:
80 00000040 31C0               xor     eax,eax
81                         ;    std
82 00000042 AA                 stosb
83                         .loop:
84 00000043 92                 xchg    eax, edx
85 00000044 99                 cdq
86 00000045 F7F9               idiv    ecx            ; edx=n%B   eax=n/B
87                         
88 00000047 92                 xchg    eax, edx       ; eax=n%B   edx=n/B
89 00000048 D7                 xlatb                  ; al = byte [rbx + al]
90 00000049 AA                 stosb                  ; *output-- = al
91                         
92 0000004A 85D2               test    edx,edx
93 0000004C 75F5               jnz     .loop
94                         
95 0000004E 47                 inc    edi
96                             ;; cld
97                             ;; scasb          ; rdi++
98 0000004F C3                 ret
99 00000050 10             .size: db $ - .start
    16 bytes for the 32-bit DF=1 version

Próbowałem alternatywnej wersji tego z lea esi, [rbx+rdx]/ movsbjako wewnętrzną pętlę. (RSI jest resetowane przy każdej iteracji, ale zmniejsza się RDI). Ale nie może użyć xor-zero / stos do terminatora, więc jest o 1 bajt większy. (I to nie jest 64-bitowe czyszczenie dla tabeli odnośników bez prefiksu REX na LEA.)


LUT z jawną długością i terminatorem 0: 16 + 1 bajtów (32-bit)

Ta wersja ustawia DF = 1 i pozostawia to w ten sposób. Liczę dodatkowy wymagany bajt LUT jako część całkowitej liczby bajtów.

Fajną sztuczką jest tutaj dekodowanie tych samych bajtów na dwa różne sposoby . Wchodzimy w środek pętli z resztą = podstawa i iloraz = liczba wejściowa i kopiujemy terminator 0 na swoje miejsce.

Za pierwszym razem przez funkcję pierwsze 3 bajty pętli są zużywane jako wysokie bajty disp32 dla LEA. To, że LEA kopiuje bazę (moduł) do EDX, idivprodukuje resztę do późniejszych iteracji.

Drugi bajt idiv ebpto FD, który jest kodem op dla stdinstrukcji, że ta funkcja musi działać. (To było szczęśliwe odkrycie. Patrzyłem na to divwcześniej, co odróżnia się od idivużywania /rbitów w ModRM. Drugi bajt div epbdekodowania jako cmc, który jest nieszkodliwy, ale nie jest pomocny. Ale za pomocą idiv ebptego możemy faktycznie usunąć stdgórę funkcji).

Zauważ, że rejestry wejściowe są jeszcze raz różne: EBP dla bazy.

103                         DEF(ascii_compress_stosb_decode_overlap)
104                         ;;; inputs
105                             ;; n in EAX = number to decode
106                             ;; O in RDI = end of output buffer
107                             ;; I in RBX = lookup table, 0-terminated.  (first iter copies LUT[base] as output terminator)
108                             ;; B in EBP = base = length of table
109                         ;;; returns: pointer in RDI to the start of a 0-terminated string
110                         ;;; clobbers: EDX (=0), EAX,  DF
111                             ;; Or a DF=1 convention allows idiv ecx (STC).  Or we could put xchg after stos and not run IDIV's modRM
112                         .start:
117                             ;2nd byte of div ebx = repz.  edx=repnz.
118                             ;            div ebp = cmc.   ecx=int1 = icebp (hardware-debug trap)
119                             ;2nd byte of idiv ebp = std = 0xfd.  ecx=stc
125                         
126                             ;lea    edx, [dword 0 + ebp]
127 00000040 8D9500             db  0x8d, 0x95, 0   ; opcode, modrm, 0 for lea edx, [rbp+disp32].  low byte = 0 so DL = BPL+0 = base
128                             ; skips xchg, cdq, and idiv.
129                             ; decode starts with the 2nd byte of idiv ebp, which decodes as the STD we need
130                         .loop:
131 00000043 92                 xchg    eax, edx
132 00000044 99                 cdq
133 00000045 F7FD               idiv    ebp            ; edx=n%B   eax=n/B;
134                             ;; on loop entry, 2nd byte of idiv ebp runs as STD.  n in EAX, like after idiv.  base in edx (fake remainder)
135                         
136 00000047 92                 xchg    eax, edx       ; eax=n%B   edx=n/B
137 00000048 D7                 xlatb                  ; al = byte [rbx + al]
138                         .do_stos:
139 00000049 AA                 stosb                  ; *output-- = al
140                         
141 0000004A 85D2               test    edx,edx
142 0000004C 75F5               jnz     .loop
143                         
144                         %ifidn __OUTPUT_FORMAT__, elf32
145 0000004E 47                 inc     edi         ; saves a byte in 32-bit.  Makes DF call-clobbered instead of normal DF=0
146                         %else
147                             cld
148                             scasb          ; rdi++
149                         %endif
150                         
151 0000004F C3                 ret
152 00000050 10             .size: db $ - .start
153 00000051 01                     db 1   ; +1 because we require an extra LUT byte
       # 16+1 bytes for a 32-bit version.
       # 17+1 bytes for a 64-bit version that ends with DF=0

Ta nakładająca się sztuczka dekodowania może być również używana z cmp eax, imm32: zajmuje tylko 1 bajt, aby skutecznie przeskoczyć do przodu o 4 bajty, tylko flagi clobbering. (Jest to straszne z punktu widzenia wydajności procesorów, które wyznaczają granice instrukcji w pamięci podręcznej L1i, BTW).

Ale tutaj używamy 3 bajtów, aby skopiować rejestr i przejść do pętli. Zwykle zajęłoby to 2 + 2 (mov + jmp) i pozwoliłoby nam wskoczyć do pętli tuż przed STOS zamiast przed XLATB. Ale wtedy potrzebowalibyśmy osobnego STD i nie byłoby to zbyt interesujące.

Wypróbuj online! (z _startdzwoniącym, który wykorzystuje sys_writewynik)

Najlepiej jest debugować, aby uruchomić go poniżej stracelub zrzucić dane wyjściowe, aby zobaczyć, czy \0w odpowiednim miejscu znajduje się terminator i tak dalej. Ale możesz zobaczyć, że to faktycznie działa i produkować AAAAAACHOOza wkład

num  equ 698911
table:  db "CHAO"
%endif
    tablen equ $ - table
    db 0  ; "terminator" needed by ascii_compress_stosb_decode_overlap

(W rzeczywistości xxAAAAAACHOO\0x\0\0..., ponieważ zrzucamy z bufora 2 bajty wcześniej do stałej długości. Widzimy więc, że funkcja zapisała bajty, które powinna, i nie nadepnęła na bajty, których nie powinna. wskaźnik początkowy przekazany do funkcji był drugim przedostatnim xznakiem, po którym następowały zera.)


3

Galaretka , 4 bajty

ṙ1ṃ@

Wypróbuj online!

jest do tego dosłownie wbudowany. Pozostałe trzy bajty odpowiadają indeksowaniu Jelly na podstawie jednego.


Z ciekawości, dlaczego Jelly ma nawet wbudowaną funkcję Dekompresja bazy; konwertuje x na długość bazy (y), a następnie indeksuje na y. Czy dotyczy to wyjątkowych przypadków, w których podstawa, na którą chcesz przekonwertować, i długość łańcucha / liczby całkowitej / listy są równe? Kiedy go szukam, mogę znaleźć tylko trzy odpowiedzi: 1 ; 2 ; 3 . Trochę dziwne, wbudowane w codzienne wyzwania związane z golfem. : S
Kevin Cruijssen

3
@KevinCruijssen jest bardzo przydatny, gdy na przykład chcesz przekonwertować N na szesnastkowy za pomocą liter szesnastkowych zamiast listy liczb.
Pan Xcoder,

@KevinCruijssen To metoda kompresji ciągów znaków. W pierwszym przykładzie pożądany jest ciąg znaków “sspspdspdspfdspfdsp”, ale z “çƥ÷£ḟ’ṃ“spdf”¤tobą oszczędzasz sześć bajtów. Jest to szczególnie przydatne w przypadku 250 podstawowych liczb Jelly
dylnan

3

Python 2 , 49 48 bajtów

-1 bajt dzięki Jo King

f=lambda n,s:n and f(n/len(s),s)+s[n%len(s)]or''

Wypróbuj online!

Alternatywna wersja (nie kończy się dla dużych liczb), 45 43 bajtów

-2 bajty dzięki Jo King

f=lambda n,s:s*n and f(n/len(s),s)+(s*n)[n]

Wypróbuj online!


3

Węgiel , 3 1 bajtów

θη

Wypróbuj online! Link jest do pełnej wersji kodu. Edycja: Zapisano 2 bajty dzięki tylko @ ASCII. Poprzednia wersja przed dodaniem wbudowanego 8 bajtów:

⭆↨θLη§ηι

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

    η       Second input
   L        Length
  θ         First input
 ↨          Base convert to array
⭆           Map over values and join
      η     Second input
       ι    Current value
     §      Index into list
            Implicitly print result

Właściwie to powinno już działać, ale najwyraźniej jeszcze raz popsułem> _>
tylko ASCII,

Ponadto byłby to 1 bajt : P (obecnie jest zepsuty, więc nie używam argumentów jako tablicy liczb i ciągów) (zastanawiam się też, jak (nie) użyteczne są dane niejawne)
tylko

@ Tylko ASCII Czy nie masz na myśli „1 bajtów” (patrz wyjście -vl ;-) Również niejawne dane wejściowe wydają się być prawie bezużyteczne w przypadku węgla drzewnego, z wyjątkiem takich wyzwań.
Neil

1
@ Tylko ASCII Liczba mnoga „bajty” zamiast pojedynczego „bajtu” jest tym, co Neil ma na myśli. ;) Co do twojej 1-bajtowej odpowiedzi, dlaczego przekreślono θη? Wygląda trochę myląco. Dlaczego nie usunąć go całkowicie i odejść ?
Kevin Cruijssen

1
@Nit Po dwukrotnym sprawdzeniu dodałem wbudowane, zanim pytanie zostało zadane, ale nie zdawałem sobie z tego sprawy, ponieważ miał błąd.
Neil

3

D , 112 bajtów

import std.conv;C u(C,I)(I n,C b){C t;for(I l=b.length;n;n/=l)t=to!C(n%l)~t;foreach(ref c;t)c=b[c-48];return t;}

Wypróbuj online!

To jest port odpowiedzi C ++ HatsuPointerKun

Stylem wywołania jest u(ulong(n), to!(char[])(b)), gdzie ni gdzie bsą argumenty lewy i prawy

D określone rzeczy

Niestety musimy zaimportować, std.convaby wykonać konwersje dowolnego typu powyżej bardzo podstawowej konwersji typu.

Korzystając z systemu szablonów golfy i nadając tej funkcji wymagane typy (dlatego wywoływanie jej nie jest po prostu u(n,b)), możemy skracać wystąpienie każdego z nich char[]i ulongje 1bajtować wewnątrz funkcji.

D inicjuje dla nas nasze typy, więc C t;jest krótkiC t=cast(char[])([])

to!Ckonwertuje liczbę całkowitą n%lna tablicę znaków (używając punktów kodowych) i ~jest konkatenacją

foreach(ref c;t)jest jak for(... : ...)pętla C ++ , ale trochę dłużej. refjest jak &, traktuje się cjako skopiowane przez odniesienie (tzn. możemy modyfikować t). Na szczęście D określa typ cbez żadnego słowa kluczowego oznaczającego typ.



3

C ++, 150 144 bajtów, uint64dane wejściowe

-6 bajtów dzięki Zacharýowi

#include<string>
using s=std::string;s u(uint64_t n,s b){s t;for(;n;n/=b.size())t=std::to_string(n%b.size())+t;for(auto&a:t)a=b[a-48];return t;}

Użycie zmiennej do przechowywania rozmiaru zwiększyłoby liczbę bajtów o 1

Aby wywołać funkcję:

u(2740, "|_")

Pierwsza liczba, druga to ciąg znaków (tablica znaków)

Przypadki testowe :

std::cout << u(2740, "|_") << '\n' << u(698911, "chao") << '\n';
return 0;

1
3 bajty do ogolenia: Nie potrzebujesz już miejsca #include, możesz zmienić ;;na sprawiedliwy ;i '0'możesz być48
Zacharý

1
Również pętla while może być forpętlą:for(;n;n/=b.size())t=std::to_string(n%b.size())+t;
Zacharý

@ceilingcat, zapomniałem, że b.size()to się nie zmienia w tej pętli.
Zacharý

@ceilingcat To zwiększyłoby liczbę bajtów o 1, zamiast ją
obniżać

2

Gałązka, 66 bajtów

Utworzono plik, macroktóry należy importedytować w szablonie.

{%macro d(n,c)%}{%for N in n|split%}{{c[N]}}{%endfor%}{%endmacro%}

Oczekiwane wartości:

Dla pierwszych argumentów ( n):

  • numer
  • strunowy

W przypadku drugiego argumentu ( c):

  • Tablica liczb
  • Tablica ciągów

Jak używać:

  • Utwórz .twigplik
  • Dodaj {% import 'file.twig' as uncompress %}
  • Wywołaj makro uncompress.d()

Niegolfowany (niefunkcjonalny):

{% macro d(numbers, chars) %}
    {% for number in numbers|split %}
        {{ chars[number] }}
    {% endfor %}
{% endmacro %}


Możesz przetestować ten kod na: https://twigfiddle.com/54a0i9


2

Pyth, 9 8 7 bajtów

s@LQjEl

Zapisano bajt dzięki hakr14 i kolejne dzięki Mr. Xcoder.
Wypróbuj tutaj

Wyjaśnienie

s@LQjEl
    jElQ      Convert the second input (the number) to the appropriate base.
 @LQ          Look up each digit in the list of strings.
s             Add them all together.

Zapisać bajt zastępując m@Qdz@LQ
hakr14

Zapisz bajt, zastępując vzgo E.
Pan Xcoder,

2

C89, sygnowany w ograniczonym zakresie int n, 64 53 bajtów

  • dziennik zmian: weź char **outi zmodyfikuj, zamiast brać i zwracaćchar *

Przyjmuje liczbę jako int, tablicę odnośników jako tablicę + długość.
Dane wyjściowe są zapisywane w pliku char *outbuf. Dzwoniący przekazuje (przez odniesienie) wskaźnik na koniec bufora. Funkcja modyfikuje ten wskaźnik, aby wskazywał pierwszy bajt ciągu po powrocie.

g(n,I,B,O)char*I,**O;{for(**O=0;n;n/=B)*--*O=I[n%B];}

Jest to poprawne C89 i działa poprawnie nawet przy włączonej optymalizacji. tzn. nie zależy od -O0zachowania gcc, gdy spada z końca funkcji innej niż void lub ma inne UB.

Przekazywanie wskaźnika na koniec bufora jest normalne dla zoptymalizowanej funkcji typu int->, takiej jak wewnętrzna glibc_itoa . Widzieć tę odpowiedź, aby uzyskać szczegółowe wyjaśnienie dzielenia liczb całkowitych na cyfry za pomocą pętli div / mod, tak jak my tutaj, zarówno w C, jak i x86-64 asm. Jeśli podstawa ma potęgę 2, możesz przesunąć / maskować, aby najpierw wyodrębnić cyfry MSD, ale w przeciwnym razie jedyną dobrą opcją jest najpierw cyfra najmniej znacząca (z modulo).

Wypróbuj online! . Wersja bez golfa:

/* int n = the number
 * int B = size of I = base
 * char I[] = input table
 * char **O = input/output arg passed by ref:
 *    on entry: pointer to the last byte of output buffer.
 *    on exit:  pointer to the first byte of the 0-terminated string in output buffer
 */
void ungolfed_g(n,I,B,O)char*I,**O;
{
    char *outpos = *O;     /* Golfed version uses *O everywhere we use outpos */
    *outpos = 0;           /* terminate the output string */
    for(;n;n/=B)
        *--outpos = I[n%B]; /* produce 1 char at a time, decrementing the output pointer */
    *O = outpos;
}

W tej wersji o jawnej długości wejście to taki, char table[]który nie potrzebuje kończącego bajtu 0, ponieważ nigdy nie traktujemy go jako łańcucha. To może byćint table[] dla nas wszystkich. C nie ma kontenerów, które znają swoją długość, więc wskaźnik + długość to normalny sposób na przekazanie tablicy o rozmiarze. Więc wybieramy to zamiast konieczności strlen.

Maksymalny rozmiar bufora wynosi około sizeof(int)*CHAR_BIT + 1, więc jest mały i ma stałą czasową kompilacji. (Używamy tak dużo miejsca z base = 2 i wszystkimi bitami ustawionymi na 1.) np. 33 bajty dla 32-bitowych liczb całkowitych, w tym0 terminator.


C89, podpisany int, tabela jako łańcuch C o niejawnej długości, 65 bajtów

B;f(n,I,O)char*I,**O;{B=strlen(I);for(**O=0;n;n/=B)*--*O=I[n%B];}

To jest to samo, ale dane wejściowe są ciągiem o niejawnej długości, więc musimy sami znaleźć tę długość.


2

Bash + podstawowe narzędzia , 49 bajtów

dc -e`echo -en $2|wc -c`o$1p|tr -dc 0-9|tr 0-9 $2

Wypróbuj online!

Komentarze / wyjaśnienia

To pobiera argumenty wiersza poleceń jako dane wejściowe (liczba w bazie 10, a następnie pojedynczy ciąg z listą znaków) i wysyła na standardowe wyjście. Znaki specjalne, takie jak spacja, nowa linia itp., Można wprowadzać w notacji ósemkowej (na przykład \040spacja) lub \nw nowej linii, \tw tabulacji lub w dowolnej innej sekwencji zmiany znaczenia, która echo -eitr interpretować identycznie.

Wiele bajtów dotyczy obsługi znaków specjalnych i większych przypadków testowych. Jeśli będę musiał obsługiwać tylko nieprzyjemne znaki, a liczby będą małe (na przykład pierwszy przypadek testowy), zrobią to następujące 24 bajty:

dc -e${#2}o$1p|tr 0-9 $2

Wykorzystuje to rozszerzenie parametrów, ${#2}aby uzyskać liczbę znaków w ciągu, buduje program dc do konwersji podstawowej, a następnie przesyła przekonwertowaną liczbę tr.

Nie będzie to jednak obsługiwać znaków nowej linii, spacji ani tabulatorów, więc aby poradzić sobie z sekwencjami ucieczki bez wpływu na bazę, liczę znaki wc -cpo interpretacji ucieczek echo -en. Rozszerza to program do 38 bajtów:

dc -e`echo -en $2|wc -c`o$1p|tr 0-9 $2

Niestety, dc ma irytującą „cechę”, w której jeśli wypisuje dużą liczbę, będzie owijać ją liniowo ukośnikiem + sekwencją nowej linii, więc większe przypadki testowe mają tę dodatkową moc wyjściową. Aby go usunąć, przepuszczam dane wyjściowe dc, tr -dc 0-9aby usunąć znaki nienumeryczne. I oto jesteśmy.


Chciałem zasugerować, dc -e${#2}o$1p|tr 0-9 "$2"aby wziąć dane wejściowe dosłownie zamiast w postaci \, aby mógł obsługiwać spacje, ale trnie ma opcji, aby na przykład nie traktować go -jako znaku zakresu. Jeśli dane wejściowe -nie znajdują się na jednym końcu łańcucha, są łamane. Być może możesz użyć sed "y/0123456789/$2/". Nie, nie sądzę, GNU sedwymaga , aby oba argumenty ybyły tej samej długości i wydaje się, że dusi się na nowej linii.
Peter Cordes,

2

APL (Dyalog Unicode) , 14 13 12 bajtów

⊢⌷⍨∘⊂⊥⍣¯1⍨∘≢

Wypróbuj online!

Infix milcząca funkcja; nie może obsłużyć największego przypadku testowego z powodu reprezentacji zmiennoprzecinkowej.

Zaoszczędzono 1 2 bajty dzięki @ Adám!

13 bajtów dla nagłówka dodane: ⎕IO←0: I ndex O Rigin = 0 ⎕FR←1287: C loat R ePresentation = 128 bitów. (Zapomniałem, że to nie dotyczy ).

W jaki sposób?

⊢⌷⍨∘⊂⊥⍣¯1⍨∘≢    Tacit function, infix.
               Tally (number of elements in) the right argument.
         ⍨∘     Then swap the arguments of
     ⊥⍣¯1       Base conversion (to base ≢<r_arg>)
               Enclose (convert to an array)
  ⍨∘            Then swap the arguments of
               Index
               (Into) the right argument.

2

Attache , 17 bajtów

{_[_2&ToBase!#_]}

Wypróbuj online!

Wyjaśnienie

{_[_2&ToBase!#_]}
{               }  ?? anonymous lambda; input: _ = dictionary, _2 = encoded
   _2&ToBase       ?? convert _2 to base
            !#_    ?? ... Size[_]
 _[            ]   ?? and take those members from the dictionary

1

Płótno , 7 bajtów

L┬{╵⁸@p

Wypróbuj tutaj!

Proste wdrożenie:

L┬{╵⁸@p
L      get the length of the input (popping the item)
 ┬     base decode the other input
  {    for each number there
   ╵     increment
    ⁸@   in the 1st input get that numbered item
      p  and output that

Zestaw znaków wejściowych może być również ciągiem, o ile nie zawiera nowej linii, ponieważ Canvas nie ma znaku nowej linii i automatycznie konwertuje go na obiekt 2D.


1

Stax , 6 5 bajtów

n%|E@

Uruchom i debuguj

Wyjaśnienie:

n%|E@ Full program, implicit input in order list, number
n%    Copy the list to the top and get its length
  |E  Convert the number to that base
    @ Map: index

1

SOGL V0.12 , 10 bajtów

l;A─{IaWp}

Wypróbuj tutaj!

Dość długo, biorąc pod uwagę, że pomysł jest w dużej mierze zaimplementowany w języku: tutaj , wchodząc

¶    __   __    ¶   |  |_|  |   ¶___|       |___¶-   -   -   -  ¶ - - - - - - - ¶- - - - - - - -¶_______________¶

podaje skompresowany ciąg przy użyciu tej metody.



1

Stax , 2 bajty

:B

Uruchom i debuguj

:Bto instrukcja, która to robi. Normalnie działałby na „ciąg” * zamiast tablicy „ciągów”. W końcu oznacza to, że wynikiem jest tablica tablic jednoznakowych. Ale produkcja i tak domyślnie spłaszcza się.

* Stax tak naprawdę nie ma typu łańcucha. Tekst jest reprezentowany przez tablice liczb całkowitych punktów kodowych.


Huh, nigdy nie zauważyłem tego polecenia ...
zmarnowałem

Tam jest dużo. Kiedyś dodałem instrukcję do stax, która już istniała, i właśnie o tym zapomniałem. (tablica nie schodzi?)
rekurencyjne

1

J , 12 bajtów

]{~#@]#.inv[

W jaki sposób?

      #.inv    convert
           [   the left argument (the number)      
   #@]         to base the length of the right argument (the list of characters)    
  {~           and use the digits as indices to
]              the list of characters        

Wypróbuj online!



1

C (gcc) , 110 bajtów

char s[99],S[99];i;f(x,_)char*_;{i=strlen(_);*s=*S=0;while(x)sprintf(S,"%c%s",_[x%i],s),strcpy(s,S),x/=i;x=s;}

Wypróbuj online!

Opis:

char s[99],S[99];           // Two strings, s and S (capacity 99)
i;                          // A variable to store the length of the string
f(x,_)char*_;{              // f takes x and string _
    i=strlen(_);            // set i to the length of _
    *s=*S=0;                // empty s and S
    while(x)                // loop until x is zero
        sprintf(S,"%c%s",   // print into S a character, then a string
                _[x%i],s),  // character is the x%i'th character of _, the string is s
        strcpy(s,S),        // copy S into s
        x/=i;               // divide x by the length of the string (and loop)
    x=s;}                   // return the string in s

1
Jeśli zaczniesz na końcu bufora i będziesz pracować wstecz, możesz tego uniknąć sprintf. Moja wersja C ma 53 bajty , a bufor wyjściowy jest dostarczany przez program wywołujący. Możesz to zrobić strcpyna końcu, jeśli chcesz skopiować bajty na początek bufora.
Peter Cordes

To jest wspaniałe. Nie obchodzi mnie, czy jest to niewygodny format we / wy. Niezręczne wejścia / wyjścia to twierdzenie C o sławie! Dobra robota, polecam umieszczenie tego w poście z poradami C.
LambdaBeta

Wysłano odpowiedź na Porady dotyczące gry w golfa w C, wyjaśniając i uzasadniając technikę.
Peter Cordes

1

CJam , 11 bajtów

liq_,@\b\f=

Wypróbuj online! Pobiera dane wejściowe jako liczbę, następnie nową linię, a następnie znaki w sztuce ASCII.

Wyjaśnienie

li           e# Read the first line and convert it to an integer
  q_,        e# Read the rest of the input and push its length n
     @\b     e# Convert the number to its base-n equivalent, as an array of numbers
        \f=  e# Map over the array, taking each element's index from the string

Ponieważ „IO jest elastyczny”, myślę, że możesz się go pozbyć liqna początku, a to oszczędza 3 bajty!
Chromium

1

JavaScript, 39 bajtów

Rozwiązanie Port of Rod's Python .

s=>g=n=>n?g(n/(l=s.length)|0)+s[n%l]:""

Wypróbuj online


Działa tylko dla wersji n64-bitowej, prawda? (Python ma wbudowane liczby całkowite o dowolnej dokładności, ale liczby JS są liczbami doublezmiennoprzecinkowymi o naturalnej precyzji, które można przekonwertować na liczby całkowite). Wydaje się, że nie działa w przypadku większych przypadków testowych w pytaniu, takich jak 1928149325670647244912100789213626616560861130859431492905908574660758972167966. Och, ale pytanie pozwala na takie odpowiedzi. Nadal należy zauważyć.
Peter Cordes

1

SimpleTemplate , 86 bajtów

Wow, to było ogromne wyzwanie!

Było to utrudnione z powodu braku bezpośredniego dostępu do określonych indeksów, gdy indeks jest zmienną.
Błąd również wydłużył go, wymagając przechowywania wartości w zmiennej.

{@setA argv.1}{@eachargv.0}{@setC C,"{@echoA.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}

Oczekiwane wartości:

Pierwszym argumentem ( argv.0) może być:

  • Liczba całkowita
  • Ciąg z liczbami
  • Tablica liczb całkowitych

Drugi argument ( argv.1) może być:

  • Ciąg
  • Tablica

Jak to działa

Działa w ten sposób:

  • Przechodzi przez liczbę / ciąg znaków przekazany jako pierwszy argument
  • Ustawia zmienną Cna tablicę zawierającą:
    • Poprzednia wartość C
    • Ciąg "{@echoA."
    • Wartość pętli
    • Ciąg "}"
  • Łączy wszystko razem (przy użyciu joinfunkcji PHP )
    To powoduje na przykład Czawarcie"{@echoA.0}{@echoA.1}..."
  • Ocenia wynik C

Nie golfowany:

{@set args argv.1}
{@each argv.0 as number}
    {@set code code, "{@echo args.", number , "}"}
    {@call join into code "", code}
{@/}
{@eval code}

Możesz wypróbować ten kod na: https://ideone.com/NEKl2q


Optymalny wynik

Gdyby nie było błędów, byłby to najlepszy wynik, uwzględniający ograniczenia (77 bajtów):

{@eachargv.0}{@setC C,"{@echoargv.1.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}
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.