ASCII adalah uncompression dari nomor base-n

24

Ini terinspirasi oleh jawaban 05AB1E oleh Magic Octupus Mm .

Diberikan dua argumen, bilangan bulat positif dan string / daftar karakter:

  1. Menerjemahkan angka ke base-n, di mana n adalah panjang string.
  2. Untuk setiap karakter, ganti setiap tampilan indeks karakter itu di angka dasar-n dengan karakter itu.
  3. Cetak atau kembalikan string baru.

Contoh:

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:
_===_
(.,.)
( : )
( : )

Aturan:

  • IO fleksibel .
    • Anda dapat mengambil nomor di pangkalan apa pun, asalkan konsisten di antara input
    • Daftar karakter harus diindeks 0, di mana 0 adalah karakter pertama dan n-1 adalah yang terakhir
  • Kemungkinan karakter dapat berupa ASCII yang dapat dicetak, bersama dengan spasi putih seperti tab dan baris baru
  • Daftar karakter yang diberikan akan memiliki panjang dalam kisaran 2-10inklusif. Artinya, basis terkecil adalah biner dan yang terbesar adalah desimal ( tidak ada huruf sial di sini )
  • Celah standar dilarang
  • Jangan ragu untuk menjawab meskipun bahasa Anda tidak dapat menangani kasus uji yang lebih besar.

Karena ini adalah , kode terpendek untuk setiap bahasa menang. ( Saya tahu semua bahasa golf Anda memiliki satu byte built-in yang siap digunakan ;)

Jo King
sumber
Kotak Pasir (dihapus)
Jo King
3
Duh, saya merasa terhormat. Ascii -art 05AB1E adalah favorit saya beberapa waktu lalu.
Magic Gurita Guci
Anda dapat membuat tantangan baru: temukan permutasi karakter dalam array untuk meminimalkan jumlahnya :)
mazzy

Jawaban:

8

05AB1E , 7 6 byte

gв¹sèJ

Karena itu terinspirasi oleh jawaban 05AB1E, jawaban yang diberikan dalam 05AB1E tampaknya cocok. :)

-1 byte terima kasih kepada @ Enigma dengan menghapus foreach dan melakukan ini secara implisit.

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

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)
Kevin Cruijssen
sumber
1
gв¹sèJuntuk menyimpan byte.
Emigna
@Emigna Terima kasih. Tidak percaya saya tidak memikirkan ¹sèdiri saya sekarang .. (Saya tahu mengubah ?ke Jakan memberikan hasil yang sama dalam kasus ini.)
Kevin Cruijssen
6

Java 8, 72 50 byte

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

-22 byte terima kasih kepada @ OlivierGrégoire dengan mengembalikan IntStreamalih - alih mencetak langsung.

Cobalah online .

Penjelasan:

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`
Kevin Cruijssen
sumber
2
a->n->n.toString(a.length).chars().map(c->a[c-48])(50 byte) karena "IO fleksibel"
Olivier Grégoire
String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";}(69 byte) rekursif, untuk bersenang-senang.
Olivier Grégoire
6

Python 3 , 49 byte

Tidak dapat berkomentar, jadi saya memposting jawaban Python 2 yang disesuaikan dengan Python 3.5.

f=lambda n,s:n and f(n//len(s),s)+s[n%len(s)]or''
Romzie
sumber
2
Selamat datang di PPCG! Jangan ragu untuk menyertakan tautan TIO untuk membantu menampilkan solusi Anda.
Jo King
5

Japt, 2 byte

Dapat mengambil input kedua sebagai array atau string. Gagal 2 uji kasus terakhir karena jumlahnya melebihi bilangan bulat maks JavaScript. Ganti sdengan ìuntuk menghasilkan array karakter sebagai gantinya.

sV

Cobalah

Shaggy
sumber
5

Haskell , 40 39 byte

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

Cobalah online!

Karena Inttipe Haskell terbatas 9223372036854775807, ini gagal untuk angka yang lebih besar.

-1 byte terima kasih kepada Laikoni .

Tidak disatukan

(!) :: 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)

Cobalah online!

ovs
sumber
Ide bagus untuk digunakan, cyclebukan mod! div n(length l)menghemat satu byte.
Laikoni
4

MATL , 2 byte

YA

Cobalah online!

Input adalah angka dan string.

Gagal melebihi angka 2^53, karena presisi titik apung.

Penjelasan

Apa yang YAtahu, builtin (konversi basis dengan simbol target yang ditentukan).

Luis Mendo
sumber
4

JavaScript (ES6), 48 byte

Mengambil input dalam sintaks currying (c)(n), di mana c adalah daftar karakter dan n adalah integer.

Hanya aman untuk n <2 53 .

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

Cobalah online!


JavaScript (ES6), 99 byte

Dengan dukungan untuk bilangan bulat besar

Mengambil input dalam sintaks currying (c)(a), di mana c adalah daftar karakter dan a adalah daftar angka desimal (sebagai bilangan bulat).

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]:''

Cobalah online!

Arnauld
sumber
4

x86 kode mesin 32-bit (bilangan bulat 32-bit): 17 byte.

(juga lihat versi lain di bawah ini, termasuk 16 byte untuk 32-bit atau 64-bit, dengan konvensi pemanggilan DF = 1.)

Caller meneruskan args dalam register, termasuk pointer ke akhir buffer output (seperti jawaban C saya ; lihat untuk pembenaran dan penjelasan algoritme.) Internal glibc _itoamelakukan ini , jadi tidak hanya dibuat untuk kode-golf. Register arg-passing dekat dengan Sistem V86 x86-64, kecuali kami memiliki arg di EAX bukan EDX.

Saat dikembalikan, EDI menunjuk ke byte pertama dari string C yang diakhiri 0 dalam buffer output. Register nilai pengembalian yang biasa adalah EAX / RAX, tetapi dalam bahasa assembly Anda dapat menggunakan konvensi panggilan apa pun yang nyaman untuk suatu fungsi. ( xchg eax,edipada akhirnya akan menambah 1 byte).

Penelepon dapat menghitung panjang eksplisit jika diinginkan, dari buffer_end - edi. Tapi saya tidak berpikir kita bisa membenarkan menghilangkan terminator kecuali fungsinya benar-benar mengembalikan pointer awal + akhir atau panjang pointer. Itu akan menghemat 3 byte dalam versi ini, tapi saya rasa itu tidak bisa dibenarkan.

  • EAX = n = angka untuk memecahkan kode. (Untuk idiv. Arg lainnya tidak operan implisit.)
  • EDI = akhir buffer output (versi 64-bit masih menggunakan dec edi, jadi harus dalam 4GiB rendah)
  • ESI / RSI = tabel pencarian, alias LUT. tidak musnah.
  • ECX = panjang tabel = basis. tidak musnah.

nasm -felf32 ascii-compress-base.asm -l /dev/stdout | cut -b -30,$((30+10))- (Diedit tangan untuk mengecilkan komentar, penomoran baris itu aneh.)

   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

Mengejutkan bahwa versi yang paling sederhana tanpa dasarnya pengorbanan kecepatan / ukuran adalah yang terkecil, tetapi std/ cldbiaya 2 byte untuk digunakan stosbdalam urutan menurun dan masih mengikuti konvensi pemanggilan DF = 0 yang umum. (Dan pengurangan STOS setelah penyimpanan, membiarkan pointer menunjuk satu byte terlalu rendah pada loop keluar, dikenakan biaya tambahan byte untuk bekerja.)

Versi:

Saya datang dengan 4 trik implementasi yang sangat berbeda (menggunakan movload / store sederhana (di atas), menggunakan lea/ movsb(rapi tapi tidak optimal), menggunakan xchg/ xlatb/ stosb/ xchg, dan yang memasuki loop dengan hack instruksi yang tumpang tindih. Lihat kode di bawah) . Yang terakhir membutuhkan trailing 0di tabel pencarian untuk menyalin sebagai terminator string output, jadi saya menghitungnya sebagai +1 byte. Bergantung pada 32/64-bit (1-byte incatau tidak), dan apakah kita dapat mengasumsikan set pemanggil DF = 1 ( stosbturun) atau apa pun, versi yang berbeda (terikat untuk) terpendek.

DF = 1 untuk disimpan dalam urutan menurun menjadikannya menang untuk xchg / stosb / xchg, tetapi pemanggil sering tidak menginginkannya; Rasanya seperti membongkar pekerjaan untuk penelepon dengan cara yang sulit dibenarkan. (Tidak seperti register arg-passing dan return-value kustom, yang biasanya tidak memerlukan biaya tambahan bagi pemanggil asm.) Namun dalam kode 64-bit, cld/ scasbberfungsi sebagai inc rdi, menghindari pemotongan pointer output ke 32-bit, jadi terkadang tidak nyaman untuk mempertahankan DF = 1 dalam fungsi 64-bit-clean. . (Pointer ke kode / data statis 32-bit di x86-64 non-PIE dapat dieksekusi di Linux, dan selalu di Linux x32 ABI, jadi versi x86-64 menggunakan pointer 32-bit dapat digunakan dalam beberapa kasus.) Bagaimanapun, interaksi ini membuatnya menarik untuk melihat berbagai kombinasi persyaratan.

  • IA32 dengan DF = 0 pada konvensi panggilan masuk / keluar: 17B ( nostring) .
  • IA32: 16B (dengan konvensi DF = 1: stosb_edx_argatau skew) ; atau dengan DF yang masuk = tidak peduli, biarkan set: 16 + 1Bstosb_decode_overlap atau 17Bstosb_edx_arg
  • x86-64 dengan pointer 64-bit, dan DF = 0 pada konvensi panggilan masuk / keluar: 17 + 1 byte ( stosb_decode_overlap) , 18B ( stosb_edx_argatau skew)
  • x86-64 dengan pointer 64-bit, penanganan DF lainnya: 16B (DF = 1 skew) , 17B ( nostringdengan DF = 1, menggunakan scasbbukan dec). 18B ( stosb_edx_argmempertahankan DF = 1 dengan 3-byte inc rdi).

    Atau jika kita membiarkan mengembalikan pointer ke 1 byte sebelum string, 15B ( stosb_edx_argtanpa incdi akhir). Semua siap untuk memanggil lagi dan memperluas string lain ke buffer dengan basis / tabel yang berbeda ... Tapi itu akan lebih masuk akal jika kita tidak menyimpan terminating 0juga, dan Anda mungkin meletakkan fungsi tubuh di dalam loop sehingga itu benar-benar sebuah masalah terpisah.

  • x86-64 dengan pointer output 32-bit, DF = 0 konvensi pemanggilan: tidak ada peningkatan lebih dari pointer output 64-bit, tetapi 18B ( nostring) terikat sekarang.

  • x86-64 dengan pointer output 32-bit: tidak ada peningkatan atas versi pointer 64-bit terbaik, jadi 16B (DF = 1 skew). Atau untuk mengatur DF = 1 dan membiarkannya, 17B untuk skewdengan stdtetapi tidak cld. Atau 17 + 1B untuk stosb_decode_overlapdengan inc edidi akhir, bukan cld/ scasb.

Dengan konvensi pemanggilan DF = 1: 16 byte (IA32 atau x86-64)

Membutuhkan DF = 1 pada input, biarkan diatur. Hampir tidak masuk akal , setidaknya berdasarkan fungsi masing-masing. Apakah hal yang sama seperti versi di atas, tetapi dengan xchg untuk mendapatkan sisa / keluar dari AL sebelum / sesudah XLATB (pencarian tabel dengan R / EBX sebagai basis) dan STOSB ( *output-- = al).

Dengan DF = 0 pada konvensi masuk / keluar yang normal, versi std/ cld/ scasbadalah 18 byte untuk kode 32 dan 64-bit, dan 64-bit bersih (berfungsi dengan pointer output 64-bit).

Perhatikan bahwa input arg berada di register yang berbeda, termasuk RBX untuk tabel (untuk xlatb). Perhatikan juga bahwa perulangan ini dimulai dengan menyimpan AL, dan diakhiri dengan karakter terakhir yang belum disimpan (karena itu movpada bagian akhir). Jadi loop "miring" relatif terhadap yang lain, maka namanya.

                            ;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

Versi non-miring serupa melampaui EDI / RDI dan kemudian memperbaikinya.

                            ; 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

Saya mencoba versi alternatif ini dengan lea esi, [rbx+rdx]/ movsbsebagai badan loop batin. (RSI diatur ulang setiap iterasi, tetapi RDI menurun). Tetapi tidak dapat menggunakan xor-zero / stos untuk terminator, jadi 1 byte lebih besar. (Dan itu tidak 64-bit bersih untuk tabel pencarian tanpa awalan REX pada LEA.)


LUT dengan panjang eksplisit dan 0 terminator: 16 + 1 byte (32-bit)

Versi ini menetapkan DF = 1 dan membiarkannya demikian. Saya menghitung byte LUT tambahan yang diperlukan sebagai bagian dari jumlah byte total.

Trik keren di sini adalah memiliki byte yang sama mendekode dua cara yang berbeda . Kami jatuh ke tengah-tengah loop dengan sisa = basis dan hasil bagi = nomor input, dan salin terminator 0 ke tempatnya.

Pada saat pertama kali melalui fungsi, 3 byte pertama dari loop dikonsumsi sebagai byte tinggi dari disp32 untuk LEA. LEA yang menyalin basis (modulus) ke EDX, idivmenghasilkan sisanya untuk iterasi selanjutnya.

Byte ke-2 idiv ebpadalah FD, yang merupakan opcode untuk stdinstruksi yang dibutuhkan fungsi ini. (Ini adalah penemuan yang beruntung. Saya telah melihat ini dengan yang divsebelumnya, yang membedakan dirinya dari idivmenggunakan /rbit dalam ModRM. Byte ke-2 div epbsebagai cmc, yang tidak berbahaya tetapi tidak membantu. Tetapi dengan idiv ebpdapatkah kita benar-benar menghapus stddari atas fungsi.)

Perhatikan register input berbeda sekali lagi: EBP untuk basis.

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

Trik decode yang tumpang tindih ini juga dapat digunakan dengan cmp eax, imm32: hanya dibutuhkan 1 byte untuk secara efektif melompat maju 4 byte, hanya flag clobbering. (Ini mengerikan untuk kinerja pada CPU yang menandai batas instruksi di L1i cache, BTW.)

Tapi di sini, kami menggunakan 3 byte untuk menyalin register dan melompat ke loop. Itu biasanya akan mengambil 2 + 2 (mov + jmp), dan akan membiarkan kita melompat ke loop tepat sebelum STOS daripada sebelum XLATB. Tetapi kemudian kita membutuhkan STD terpisah, dan itu tidak akan sangat menarik.

Cobalah online! (dengan _startpenelepon yang menggunakan sys_writehasil)

Cara terbaik untuk debugging untuk menjalankannya di bawah strace, atau hexdump output, sehingga Anda dapat melihat memverifikasi bahwa ada \0terminator di tempat yang tepat dan seterusnya. Tetapi Anda dapat melihat ini benar-benar bekerja, dan menghasilkan AAAAAACHOOinput

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

(Sebenarnya xxAAAAAACHOO\0x\0\0..., karena kita membuang dari 2 byte sebelumnya di buffer ke panjang yang tetap. Jadi kita dapat melihat bahwa fungsi menulis byte yang seharusnya dan tidak menginjak byte yang seharusnya tidak ada. pointer-awal yang diteruskan ke fungsi adalah karakter ke-2 terakhir x, yang diikuti oleh nol.)

Peter Cordes
sumber
3

Jelly , 4 byte

ṙ1ṃ@

Cobalah online!

secara harfiah adalah built-in untuk ini. Akun tiga byte lainnya untuk pengindeksan satu berbasis Jelly.

Tuan Xcoder
sumber
Karena penasaran, mengapa Jelly bahkan memiliki builtin " Base decompression; konversi x ke panjang basis (y) kemudian indeks menjadi y. "? Apakah itu untuk kasus yang sangat luar biasa di mana basis Anda semut untuk mengkonversi dan panjang string / integer / daftar sama? Ketika saya mencarinya, saya hanya dapat menemukan tiga jawaban menggunakannya: 1 ; 2 ; 3 . Agak builtin aneh di setiap hari tantangan kode-golf imo. : S
Kevin Cruijssen
3
@KevinCruijssen sangat berguna ketika Anda ingin, misalnya, untuk mengubah N menjadi heksadesimal menggunakan huruf heks alih-alih daftar angka.
Tn. Xcoder
@KevinCruijssen Ini adalah metode kompresi untuk string. Dalam contoh pertama string yang diinginkan adalah “sspspdspdspfdspfdsp”, tetapi dengan “çƥ÷£ḟ’ṃ“spdf”¤Anda menyimpan enam byte. Ini sangat berguna dengan angka dasar 250 Jelly
dylnan
3

Python 2 , 49 48 byte

-1 byte terima kasih kepada Jo King

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

Cobalah online!

Versi alternatif (tidak akan selesai untuk jumlah besar), 45 43 byte

-2 byte terima kasih kepada Jo King

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

Cobalah online!

tongkat
sumber
3

Arang , 3 1 byte

θη

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Sunting: Disimpan 2 byte berkat hanya @ ASCII. Versi sebelumnya sebelum builtin ditambahkan, 8 byte:

⭆↨θLη§ηι

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

    η       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
Neil
sumber
Sebenarnya itu seharusnya sudah bekerja tetapi ternyata saya sudah mengacaukan lagi> _>
ASCII-only
Juga, itu sebenarnya akan menjadi 1 byte : P (saat ini rusak, jadi saya tidak menggunakan angka dan array string sebagai argumen) (juga, saya bertanya-tanya bagaimana (tidak) input implisit yang berguna)
ASCII-only
@ ASCII-only Jangan Anda maksudkan "1 byte" (lihat output -vl Anda ;-) Juga, input implisit tampaknya hampir tidak berguna di Charcoal, kecuali untuk tantangan seperti ini.
Neil
1
@ ASCII-only Plural "byte" alih-alih "byte" tunggal adalah apa yang dimaksud Neil. ;) Adapun jawaban 1-byte Anda, mengapa dicoret θη? Tbh agak membingungkan. Mengapa tidak menghapusnya sepenuhnya dan pergi ?
Kevin Cruijssen
1
@Nit saya mengecek dan built-in telah ditambahkan sebelum pertanyaan diajukan, tetapi saya tidak menyadari karena ada bug.
Neil
3

D , 112 byte

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;}

Cobalah online!

Ini adalah port jawaban C ++ HatsuPointerKun

Gaya panggilan adalah u(ulong(n), to!(char[])(b)), di mana ndan badalah argumen kiri dan kanan

D hal-hal spesifik

Sayangnya, kita perlu mengimpor std.convuntuk melakukan konversi tipe apa pun di atas konversi tipe yang sangat mendasar.

Menggunakan sistem template golf, dan memberikan fungsi jenis yang diperlukan (itulah sebabnya menyebutnya bukan hanya adil u(n,b)), kita dapat mempersingkat kemunculan char[]dan ulongke1 byte masing-masing, ketika di dalam f fungsi.

D menginisialisasi tipe kami untuk kami, demikian C t;juga singkatanC t=cast(char[])([])

to!Cmengkonversi integer n%lke array karakter (menggunakan codepoint), dan ~merupakan gabungan

foreach(ref c;t)seperti for(... : ...)loop C ++ , tapi sedikit lebih lama. refseperti &, itu memperlakukan csebagai disalin-oleh-referensi (yaitu, kita dapat memodifikasi t). Untungnya, D menyimpulkan jenis ctanpa setiap jenis yang menunjukkan kata kunci.

Zacharý
sumber
3

C ++, 150 144 byte, uint64masukan

-6 byte terima kasih kepada Zacharý

#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;}

Menggunakan variabel untuk menyimpan ukuran akan meningkatkan bytecount sebesar 1

Untuk memanggil fungsi:

u(2740, "|_")

Pertama angkanya, kedua adalah string (char array)

Kasus uji:

std::cout << u(2740, "|_") << '\n' << u(698911, "chao") << '\n';
return 0;
HatsuPointerKun
sumber
1
3 byte untuk dicukur habis: Anda tidak perlu ruang setelahnya #include, Anda bisa mengubahnya ;;menjadi adil ;, dan '0'bisa saja48
Zacharý
1
Juga, loop sementara bisa menjadi forloop:for(;n;n/=b.size())t=std::to_string(n%b.size())+t;
Zacharý
@ceilingcat, saya lupa itu b.size()tidak berubah dalam loop itu.
Zacharý
@ceilingcat Itu akan meningkatkan bytecount oleh 1, alih-alih menurunkannya
HatsuPointerKun
2

Ranting, 66 byte

Dibuat macroyang harus importdiedit menjadi templat.

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

Nilai yang diharapkan:

Untuk argumen pertama ( n):

  • jumlah
  • tali

Untuk argumen kedua ( c):

  • Array angka
  • Array string

Bagaimana cara menggunakan:

  • Buat .twigfile
  • Menambahkan {% import 'file.twig' as uncompress %}
  • Panggil makro uncompress.d()

Tidak disatukan (tidak berfungsi):

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


Anda dapat menguji kode ini di: https://twigfiddle.com/54a0i9

Ismael Miguel
sumber
2

Pyth, 9 8 7 byte

s@LQjEl

Menyimpan satu byte berkat hakr14 dan terima kasih lain kepada Tn. Xcoder.
Coba di sini

Penjelasan

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.

sumber
Simpan satu byte dengan menggantinya m@Qddengan@LQ
hakr14
Simpan satu byte dengan mengganti vzdengan E.
Tn. Xcoder
2

C89, rentang terbatas ditandatangani int n, 64 53 byte

  • changelog: ambil char **outdan ubah, alih-alih mengambil dan mengembalikan achar *

Mengambil nomor sebagai int, tabel pencarian sebagai array + panjang.
Keluaran ditulis menjadi a char *outbuf. Penelepon melewati (dengan referensi) pointer ke ujung buffer. Fungsi memodifikasi penunjuk itu untuk menunjuk ke byte pertama dari string saat kembali.

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

Ini adalah C89 yang valid, dan berfungsi dengan benar bahkan jika optimasi diaktifkan. yaitu tidak bergantung pada -O0perilaku gcc ketika jatuh dari fungsi yang tidak kosong atau memiliki UB lainnya.

Melewati sebuah pointer ke ujung buffer adalah normal untuk fungsi string int> yang dioptimalkan, seperti internal glibc_itoa . Lihat jawaban ini untuk penjelasan terperinci tentang memecah bilangan bulat menjadi digit dengan loop div / mod seperti yang kami lakukan di sini, di C serta as x86-64. Jika pangkalan adalah kekuatan 2, Anda dapat menggeser / menutupi untuk mengekstraksi angka MSD terlebih dahulu, tetapi jika tidak satu-satunya pilihan yang baik adalah paling tidak signifikan-digit pertama (dengan modulo).

Cobalah online! . Versi tidak disatukan:

/* 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;
}

Dalam versi panjang-eksplisit ini, input adalah char table[]yang tidak memerlukan terminasi 0 byte, karena kita tidak pernah memperlakukannya sebagai string. Itu bisa menjadi int table[]untuk semua yang kita pedulikan. C tidak memiliki wadah yang mengetahui panjangnya sendiri, jadi panjang penunjuk + adalah cara normal untuk melewatkan array dengan ukuran. Jadi kami memilih itu daripada perlu strlen.

Ukuran buffer maksimum kira-kira sizeof(int)*CHAR_BIT + 1, jadi kecil dan konstan waktu kompilasi. (Kami menggunakan banyak ruang ini dengan basis = 2 dan semua bit diatur ke 1.) misalnya 33 byte untuk bilangan bulat 32 bit, termasuk 0terminator.


C89, ditandatangani int, tabel sebagai string C panjang implisit, 65 byte

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

Ini adalah hal yang sama tetapi inputnya adalah string panjang implisit sehingga kita harus menemukan panjangnya sendiri.

Peter Cordes
sumber
2

Utilitas inti Bash + , 49 byte

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

Cobalah online!

Komentar / penjelasan

Ini mengambil argumen baris perintah sebagai input (angka dalam basis 10, kemudian string tunggal dengan daftar karakter) dan output ke stdout. Karakter khusus seperti spasi, baris baru, dll dapat dimasukkan dalam notasi oktal (misalnya, \040untuk spasi), atau \nuntuk baris baru, \tuntuk tab, atau urutan pelarian lainnya yang echo -edan trmenafsirkannya secara identik.

Banyak byte di sini untuk menangani karakter khusus dan kasus uji yang lebih besar. Jika saya hanya perlu menangani karakter yang tidak mengerikan dan jumlahnya kecil (misalnya, test case pertama), 24 byte berikut akan melakukannya:

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

Ini menggunakan ekspansi parameter ${#2}untuk mendapatkan jumlah karakter dalam string, membangun program dc untuk melakukan konversi basis, dan kemudian mengirimkan nomor yang dikonversi melalui tr.

Ini tidak akan menangani baris baru atau spasi atau tab, jadi untuk menangani urutan pelarian tanpa mempengaruhi basis, saya menghitung jumlah karakter wc -csetelah menafsirkan lolos dengan echo -en. Ini memperluas program ke 38 byte:

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

Sayangnya, dc memiliki "fitur" yang mengganggu di mana jika mengeluarkan sejumlah besar, ia akan membungkusnya dengan garis miring + baris baru, sehingga kotak uji yang lebih besar memiliki output tambahan ini. Untuk menghapusnya, saya menyalurkan output dc tr -dc 0-9untuk menghapus karakter non-numerik. Dan di sanalah kita.

Sophia Lechner
sumber
Saya akan menyarankan dc -e${#2}o$1p|tr 0-9 "$2"untuk mengambil input secara harfiah alih-alih dalam bentuk \ escaped sehingga dapat menangani spasi, tetapi trtidak memiliki opsi untuk tidak memperlakukan -sebagai karakter rentang, misalnya. Jika input -belum di salah satu ujung string, itu rusak. Mungkin Anda bisa menggunakannya sed "y/0123456789/$2/". Tidak, saya kira tidak, GNU sedmembutuhkan kedua argumen untuk ymemiliki panjang yang sama, dan sepertinya tersedak pada baris baru.
Peter Cordes
2

APL (Dyalog Unicode) , 14 13 12 byte

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

Cobalah online!

Fungsi infix diam-diam; tidak dapat menangani test case terbesar karena representasi floating point.

Disimpan 1 2 byte berkat @ Adám!

13 byte ditambahkan untuk header: ⎕IO←0: I ndex O rigin = 0 dan ⎕FR←1287: F loat R epresentation = 128 bit. (Saya lupa bahwa ini tidak berlaku. )

Bagaimana?

⊢⌷⍨∘⊂⊥⍣¯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.
J. Sallé
sumber
2

Attache , 17 byte

{_[_2&ToBase!#_]}

Cobalah online!

Penjelasan

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

Kanvas , 7 byte

L┬{╵⁸@p

Coba di sini!

Implementasi lurus ke depan:

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

Set karakter input dapat berupa string juga asalkan tidak mengandung baris baru, karena Canvas tidak memiliki karakter baris baru & secara otomatis mengubahnya menjadi objek 2D.

dzaima
sumber
1

Stax , 6 5 byte

n%|E@

Jalankan dan debug itu

Penjelasan:

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
wastl
sumber
1

SOGL V0.12 , 10 byte

l;A─{IaWp}

Coba Di Sini!

Cukup lama, mengingat idenya cukup banyak diimplementasikan dalam bahasa: di sini , masuk

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

memberikan string terkompresi menggunakan metode ini.

dzaima
sumber
1

Stax , 2 byte

:B

Jalankan dan debug itu

:Badalah instruksi dalam keadaan tenang yang melakukan ini. Ini biasanya beroperasi pada "string" * bukannya array "string". Pada akhirnya, ini berarti bahwa output adalah array array karakter tunggal. Tetapi output secara implisit rata pula.

* Stax sebenarnya tidak memiliki tipe string. Teks diwakili oleh array integer dari codepoint.

rekursif
sumber
Huh, saya tidak pernah memperhatikan perintah ini ...
wastl
Ada banyak. Saya pernah menambahkan instruksi ke stax yang sudah ada, dan saya baru saja lupa. (array non-turun?)
rekursif
1

J , 12 byte

]{~#@]#.inv[

Bagaimana?

      #.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        

Cobalah online!

Galen Ivanov
sumber
1

C (gcc) , 110 byte

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;}

Cobalah online!

Deskripsi:

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
LambdaBeta
sumber
1
Jika Anda mulai dari akhir buffer dan bekerja mundur, Anda dapat menghindari sprintf. Versi C saya adalah 53 byte , dengan buffer output disediakan oleh pemanggil. Anda bisa melakukannya strcpydi akhir jika Anda ingin menyalin byte ke awal buffer.
Peter Cordes
Itu brilian. Saya tidak peduli apakah ini format I / O yang canggung. I / O yang canggung adalah C yang mengklaim ketenaran! Bagus sekali, saya sarankan memasukkannya ke dalam posting tips C.
LambdaBeta
Diposting jawaban pada Tips untuk bermain golf di C menjelaskan dan membenarkan teknik.
Peter Cordes
1

CJam , 11 byte

liq_,@\b\f=

Cobalah online! Mengambil input sebagai nomor, lalu baris baru, lalu karakter dalam seni ASCII.

Penjelasan

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
NinjaBearMonkey
sumber
Karena "IO Fleksibel", saya pikir Anda dapat menyingkirkannya liqdi awal, dan itu menghemat 3 byte!
Chromium
1

JavaScript, 39 byte

Solusi Port of Rod's Python .

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

Cobalah online

Shaggy
sumber
Hanya berfungsi nhingga 64-bit, bukan? (Python memiliki integer presisi arbitrer yang terpasang di doubledalamnya , tetapi angka JS secara alami merupakan float -prisi yang dapat dikonversi ke integer). Tampaknya tidak berfungsi untuk kasus uji yang lebih besar dalam pertanyaan, seperti 1928149325670647244912100789213626616560861130859431492905908574660758972167966. Oh, tetapi pertanyaannya memungkinkan jawaban seperti itu. Meski begitu, harus diperhatikan.
Peter Cordes
1

SimpleTemplate , 86 byte

Wow, ini adalah tantangan besar!

Ini menjadi sulit karena kurangnya akses langsung ke indeks tertentu ketika indeks adalah variabel.
Bug juga membuatnya lebih lama, membutuhkan untuk menyimpan nilai-nilai di dalam suatu variabel.

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

Nilai yang diharapkan:

Argumen pertama ( argv.0) dapat berupa:

  • Bilangan bulat
  • String dengan angka
  • Array bilangan bulat

Argumen kedua ( argv.1) dapat berupa:

  • Sebuah benang
  • Array

Bagaimana ini bekerja?

Cara kerjanya seperti ini:

  • Siklus melalui angka / string dilewatkan sebagai argumen pertama
  • Setel variabel Cmenjadi array yang berisi:
    • Nilai sebelumnya C
    • String "{@echoA."
    • Nilai loop
    • String "}"
  • Menggabungkan semuanya bersama-sama (menggunakan joinfungsi PHP )
    Ini menghasilkan, misalnya, Cberisi"{@echoA.0}{@echoA.1}..."
  • Mengevaluasi hasil C

Tidak Disatukan:

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

Anda dapat mencoba kode ini di: https://ideone.com/NEKl2q


Hasil yang optimal

Jika tidak ada bug, ini akan menjadi hasil terbaik, dengan memperhitungkan batasan (77 byte):

{@eachargv.0}{@setC C,"{@echoargv.1.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}
Ismael Miguel
sumber