[Question]
  [
This is inspired by an [05AB1E answer](https://codegolf.stackexchange.com/a/114226/76162) by [Magic Octupus Urn](https://codegolf.stackexchange.com/users/59376/magic-octopus-urn).
Given two arguments, a positive integer and a string/list of characters:
1. Translate the number to base-n, where n is the length of the string.
2. For each character, replace every appearance of the index of that character in the base-n number with that character.
3. Print or return the new string.
### Examples:
```
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:
_===_
(.,.)
( : )
( : )
```
Rules:
* [IO is flexible](https://codegolf.meta.stackexchange.com/q/2447/76162).
	+ You can take the number in any base, as long as it is consistent between inputs
	+ The list of characters has to be 0-indexed though, where 0 is the first character and n-1 is the last
* Possible characters can be any printable ASCII, along with whitespace such as tabs and newlines
* The given list of characters will have a length in the range `2-10` inclusive. That is, the smallest base is binary and the largest is decimal (*no pesky letters here*)
* [Standard loopholes](https://codegolf.meta.stackexchange.com/q/1061/76162) are forbidden
* Feel free to answer even if your language can't handle the larger test cases.
As this is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), the shortest code for each language wins. (*I know all you golfing languages have one byte built-ins ready to go* ;)
  
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~7~~ 6 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
gв¹sèJ
```
Since it was inspired by an 05AB1E answer, an answer given in 05AB1E seems fitting. :)
-1 byte thanks to *@Emigna* by removing the foreach and doing this implicitly.
[Try it online](https://tio.run/##MzBNTDJM/f8//cKmskM7Kw@vsP//X0lJyYpLL95WQVNDB8jmMjYxMTM1MDYyMzUzMTW2MDQwNDUxNAIA) or [verify all test cases](https://tio.run/##Fcw9CsJAEAXgfk8RUimozMzOryDpvEZQEe3sBCHeRxsLCw8QL@CN1g08eDx4fCC7PR4Lb8dnOf3e1/F1@z66ch8/XU0Z@kTGkA7n3SVpeCCmtm2bNPTL2gmDHDkyiRooGzEHEgKYB2FWUkUVBVfEDC7Bud4pQKIuY1Uw8TBCtVCd7HVa9ZtmPltMfmZWgUzVYMmOgMJIfw).
**Explanation:**
```
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)
```
[Answer]
# [Python 3](https://docs.python.org/3.5/), 49 bytes
Cannot comment yet, so I post the Python 2 answer adapted to Python 3.5.
```
f=lambda n,s:n and f(n//len(s),s)+s[n%len(s)]or''
```
[Answer]
# Java 8, ~~72~~ 50 bytes
```
a->n->n.toString(a.length).chars().map(c->a[c-48])
```
-22 bytes thanks to *@OlivierGrégoire* by returning an `IntStream` instead of printing directly.
[Try it online](https://tio.run/##fVFNa@MwEL3nVwyGBQlsIcmybG23gbZsYQ97yjEJQavaiVNHNpbSJbT97amcuPSDUtBhNG/mvXkzW/2gk@3d/dE02jn4q2v7OAFwXvvawDagZO/rhlR7a3zdWnI7Br/MRvfzZfxtzQnbab8h1/X6j/Xluuzfdzjfl3pHAjI7RdMpVHAJR51MbXjEtyFf2zXSpCnt2m8wGWQdwoG1QyaZ6rlJRLHEx4tJGLvb/2vC2OP0D219B7vgCJ1Z5kvQeHAH4EvnUfS0imKIeC5ohC/e5YNGOyBSFYqxjxgs7NMqGVCmeMGESnkmcypFzoVQjDNK80JxlkouJZOZpIVkLKVFpkQayrmimQq/XEhJ86xQOWcyV1J@lPm5sGR1CRjFg1QqhMxoygOdyNKCUZYJxs8dz5O3e50cnwjOjsHFMEZ2dF4R3XXNAbmw3Juwy6u@1weE8Zi25X/46mrIhpKq7X9rsxn2Pjs4X@5Iu/ekC/y@QtEPE8UGjy4@441F0cK@Tvx8fAE).
**Explanation:**
```
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`
```
[Answer]
# Japt, 2 bytes
Can take the second input as an array or a string. Fails the last 2 test cases as the numbers exceed JavaScript's max integer. Replace `s` with `ì` to output an array of characters instead.
```
sV
```
[Try it](https://ethproductions.github.io/japt/?v=1.4.5&code=c1Y=&input=Njk4OTExClsiYyIsImgiLCJhIiwibyJd)
[Answer]
# [Haskell](https://www.haskell.org/), ~~40~~ 39 bytes
```
0!_=[]
n!l=cycle l!!n:div n(length l)!l
```
[Try it online!](https://tio.run/##y0gszk7Nyfn/30Ax3jY6litPMcc2uTI5J1UhR1Exzyols0whTyMnNS@9JEMhR1Mx539uYmaegq1CQWlJcEmRgoqCmaWFpaGholJyRmK@0n8A "Haskell – Try It Online")
As Haskell's `Int` type is limited to `9223372036854775807`, this fails for larger numbers.
-1 byte thanks to [Laikoni](https://codegolf.stackexchange.com/users/56433/laikoni).
## Ungolfed
```
(!) :: 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)
```
[Try it online!](https://tio.run/##dZA7a8MwFIV3/4qj0MGG2iRLaQzpkHYJlC4ZQ2hs@SYWkSUjyQn@9e61WujSatDjPr57jtrKX0nraUpFhrLEzgTkLzi8tpU7/t6SZAmBT2xwOAJ5jt0ZoSWYoavJQXksH3EnOKpkS03MkWkKbCtPkLyVoK4PI3xwylwSwzjNuATQFGDo/sGv1ODUqNuJY@YSWugMyiAO5LBqeCDqMdJrZnIzIEepCVqIufCvxc2OwuBM7JNsh6VJ27DMH9b7/g1FUSDyyihGaOB/3lzcO@rZ4mzWRoojH2C//8UOoR8CUmk7PrnGkRycVzfSYzZ1FbvagDP74PCAp/XzerUSC9ZmF9MX "Haskell – Try It Online")
[Answer]
# [MATL](https://github.com/lmendo/MATL), 2 bytes
```
YA
```
[Try it online!](https://tio.run/##y00syfn/P9Lx/38jcxMDLvWaeHUA "MATL – Try It Online")
Inputs are a number and a string.
Fails for numbers exceeding `2^53`, because of floating-point precision.
### Explanation
What do `YA` know, a builtin (base conversion with specified target symbols).
[Answer]
# JavaScript (ES6), 48 bytes
Takes input in currying syntax `(c)(n)`, where **c** is a list of characters and **n** is an integer.
Safe only for **n < 253**.
```
c=>n=>n.toString(c.length).replace(/./g,i=>c[i])
```
[Try it online!](https://tio.run/##XYpBCsIwEADvPiOnLNStFVF7SD/hsRQJa5pGwm5JQ0/@PcarMHOaedvdbpTCmo8sL1dmU8gMXMEsj5wCe00YHfu8ACa3RktOt9j6JpiBxjBBIeFNosMoXs96VB/VqKeaQJ9vlxPA4b9T7UvVVuX3Xft733UA5Qs "JavaScript (Node.js) – Try It Online")
---
# JavaScript (ES6), 99 bytes
### *With support for big integers*
Takes input in currying syntax `(c)(a)`, where **c** is a list of characters and **a** is a list of decimal digits (as integers).
```
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]:''
```
[Try it online!](https://tio.run/##hY7LTsMwEEX3fAWKhGITN/X4MY4rufwBPxAi5DyaFrVJ5BZW@fdgXl2w6eJYmpHP3PvmP/y5CYfpshrGtlt2bmnctnfEs8lxVrsmP3ZDf9mz4Dh1W1j7cqqeeuLzk58IadkhbklwbRYegbPWhXU9cxYeXM3a@bCa5nnKMtZSyiaaNWWoNmm6NONwHo9dfhx7siNlMicseU0qSso8z1NhFE@r74Dn91PdBUrp3X@lico@4iPjVUVbWICb8n2UXob4/ASzZHW9AFYUoKwUGg1HZYRSFgRwbgorQKJABNTICwSQvNBWyfhdWK5tnIxC5EYX1ghAYxFvVtn8Vcl/q7jIVz8aIRF2rSaVQs2liPFKywI4aAXif8LyCQ "JavaScript (Node.js) – Try It Online")
[Answer]
# x86 32-bit machine code (32-bit integers): 17 bytes.
(also see other versions below, including 16 bytes for 32-bit or 64-bit, with a DF=1 calling convention.)
Caller passes args in registers, including a pointer to the *end* of an output buffer (like [my C answer](https://codegolf.stackexchange.com/questions/166708/ascii-art-uncompression-from-a-base-n-number/166831#166831); see it for justification and explanation of the algorithm.) [glibc's internal `_itoa` does this](https://code.woboq.org/userspace/glibc/sysdeps/generic/_itoa.h.html#39), so it's not just contrived for code-golf. The arg-passing registers are close to x86-64 System V, except we have an arg in EAX instead of EDX.
On return, EDI points to the first byte of a 0-terminated C string in the output buffer. The usual return-value register is EAX/RAX, but in assembly language you can use whatever calling convention is convenient for a function. (`xchg eax,edi` at the end would add 1 byte).
The caller can calculate an explicit length if it wants, from `buffer_end - edi`. But I don't think we can justify omitting the terminator unless the function actually returns both start+end pointers or pointer+length. That would save 3 bytes in this version, but I don't think it's justifiable.
* EAX = n = number to decode. (For `idiv`. The other args aren't implicit operands.)
* EDI = end of output buffer (64-bit version still uses `dec edi`, so must be in the low 4GiB)
* ESI/RSI = lookup table, aka LUT. not clobbered.
* ECX = length of table = base. not clobbered.
`nasm -felf32 ascii-compress-base.asm -l /dev/stdout | cut -b -30,$((30+10))-` (Hand edited to shrink comments, line numbering is weird.)
```
   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
```
It's surprising that the simplest version with basically no speed/size tradeoffs is the smallest, but `std`/`cld` cost 2 bytes to use `stosb` to go in descending order and still follow the common DF=0 calling convention. (And STOS decrements *after* storing, leaving the pointer pointing one byte too low on loop exit, costing us extra bytes to work around.)
# Versions:
I came up with 4 significantly different implementation tricks (using simple `mov` load/store (above), using `lea`/`movsb` (neat but not optimal), using `xchg`/`xlatb`/`stosb`/`xchg`, and one that enters the loop with an overlapping-instruction hack. See code below). The last needs a trailing `0` in the lookup table to copy as the output string terminator, so I'm counting that as +1 byte. Depending on 32/64-bit (1-byte `inc` or not), and whether we can assume the caller sets DF=1 (`stosb` descending) or whatever, different versions are (tied for) shortest.
DF=1 to store in descending order makes it a win to xchg / stosb / xchg, but the caller often won't want that; It feels like offloading work to the caller in a hard-to-justify way. (Unlike custom arg-passing and return-value registers, which typically don't cost an asm caller any extra work.) But in 64-bit code, `cld` / `scasb` works as `inc rdi`, avoiding truncating the output pointer to 32-bit, so it's sometimes inconvenient to preserve DF=1 in 64-bit-clean functions. . (Pointers to static code/data are 32-bit in x86-64 non-PIE executables on Linux, and always in the Linux x32 ABI, so an x86-64 version using 32-bit pointers is usable in some cases.) Anyway, this interaction makes it interesting to look at different combinations of requirements.
* **IA32 with a DF=0 on entry/exit calling convention: 17B (`nostring`)**.
* IA32: **16B (with a DF=1 convention: `stosb_edx_arg` or `skew`)**; or with incoming DF=dontcare, leaving it set: **16+1B `stosb_decode_overlap`** or 17B `stosb_edx_arg`
* **x86-64 with 64-bit pointers, and a DF=0 on entry/exit calling convention: 17+1 bytes (`stosb_decode_overlap`)**, 18B (`stosb_edx_arg` or `skew`)
* x86-64 with 64-bit pointers, other DF handling: **16B (DF=1 `skew`)**, 17B (`nostring` with DF=1, using `scasb` instead of `dec`). 18B (`stosb_edx_arg` preserving DF=1 with 3-byte `inc rdi`).
Or if we allow returning a pointer to 1 byte before the string, **15B** (`stosb_edx_arg` without the `inc` at the end). **All set to call again and expand another string into the buffer with different base / table...** But that would make more sense if we didn't store a terminating `0` either, and you might put the function body inside a loop so that's really a separate problem.
* x86-64 with 32-bit output pointer, DF=0 calling convention: no improvement over 64-bit output pointer, but 18B (`nostring`) ties now.
* x86-64 with 32-bit output pointer: no improvement over the best 64-bit pointer versions, so 16B (DF=1 `skew`). Or to set DF=1 and leave it, 17B for `skew` with `std` but not `cld`. Or 17+1B for `stosb_decode_overlap` with `inc edi` at the end instead of `cld`/`scasb`.
---
# With a DF=1 calling convention: 16 bytes (IA32 or x86-64)
Requires DF=1 on input, leaves it set. [Barely plausible](https://codegolf.stackexchange.com/questions/132981/tips-for-golfing-in-x86-x64-machine-code/165020#165020), at least on a per-function basis. Does the same thing as the above version, but with xchg to get the remainder in/out of AL before/after XLATB (table lookup with R/EBX as base) and STOSB (`*output-- = al`).
With a normal DF=0 on entry/exit convention, **the `std` / `cld`/`scasb` version is 18 bytes for 32 and 64-bit code, and is 64-bit clean** (works with a 64-bit output pointer).
Note that the input args are in different registers, including RBX for the table (for `xlatb`). Also note that this loop starts by storing AL, and ends with the last char not stored yet (hence the `mov` at the end). So the loop is "skewed" relative to the others, hence the name.
```
                            ;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
```
A similar non-skewed version overshoots EDI/RDI and then fixes it up.
```
                            ; 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
```
I tried an alternate version of this with `lea esi, [rbx+rdx]` / `movsb` as the inner loop body. (RSI is reset every iteration, but RDI decrements). But it can't use xor-zero / stos for the terminator, so it's 1 byte larger. (And it's not 64-bit clean for the lookup table without a REX prefix on the LEA.)
---
# LUT with explicit length *and* a 0 terminator: 16+1 bytes (32-bit)
This version sets DF=1 and leaves it that way. I'm counting the extra LUT byte required as part of the total byte count.
The cool trick here is **having the same bytes decode two different ways**. We fall into the middle of the loop with remainder = base and quotient= input number, and copy the 0 terminator into place.
On the first time through the function, the first 3 bytes of the loop are consumed as the high bytes of a disp32 for an LEA. That LEA copies the base (modulus) to EDX, `idiv` produces the remainder for later iterations.
The 2nd byte of `idiv ebp` is `FD`, which is the opcode for the `std` instruction that this function needs to work. (This was a lucky discovery. I had been looking at this with `div` earlier, which distinguishes itself from `idiv` using the `/r` bits in ModRM. The 2nd byte of `div epb` decodes as `cmc`, which is harmless but not helpful. But with `idiv ebp` can we actually remove the `std` from the top of the function.)
Note the input registers are difference once again: EBP for the base.
```
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
```
This overlapping decode trick can also be used with `cmp eax, imm32`: it only takes 1 byte to effectively jump forward 4 bytes, only clobbering flags. (This is terrible for performance on CPUs that mark instruction boundaries in L1i cache, BTW.)
But here, we're using 3 bytes to copy a register and jump into the loop. That would normally take 2+2 (mov + jmp), and would let us jump into the loop right before the STOS instead of before the XLATB. But then we'd need a separate STD, and it wouldn't be very interesting.
[Try it online! (with a `_start` caller that uses `sys_write` on the result)](https://tio.run/##zVlrbxpLEv3OryhFGxliwGB7vYkRH0Ls3IuUxJHt3M0q10I9Mw10PA8yPWMgu/vbs6eqZ2Bw8ONubrRryfIMVFfX45yq6rayVkdeuGzFykbfvj01YxPENBqdfbh8/@Fy9Prs/O3Ly9GoSTocH@zXeoPh5QXh4WmgxybWlAaGdGDW7xbvtvKuFqTVYv3u4d2rvPt49yvvAd4DvOs4MONajfDT69EkTDwV0jM1znT6jLKpplB5OiSTUZRA0mhLxpKKSS9mOjWRjjMsGGuV5aleqT85fV0f57Efq0g3qHw6LvWXH9RqLKisb8zIT6JZqq0dxYnNUhNPGrUeLDLxLM9saV@Mdzp9@ZH6FOeRp1PKEgq0nwS6FDljkfOTIUTgGyVjSvIMOsjLx2MsoHqUW7xplguTOaLcKNcOZe0Frw2T5DqfUaa8cKV6ILu/4t1DHU@yKWt3EmxqqhGD2B7TLDEx4lcaAhM5kDZTacYrFHVa@Doyscp0QM5b0eAjPHDKHvfo9ORjP1Qw1J@qtMk@9zu1tug4Fnui5Ib/0OAfl6f0Cfi4ahIkYPfsmLb89ChI/ikr/eDLdoEuecsMhk6TlM3Ppkgz0SJJGSpN/NIeBeZGlBg88F@AalMJxPrx0wF/pfC0N6htmBuETVgL9O4yBq@cYSEi@ubD5Sesu6r1WMxmgYu69ZX15BFpFg2gwXeWt1pFkov3LAXCEF1LR4ctD@AtUmI3bCmihu3Xmp4Vivr42FkOLaIX7jSZYvz8Of4q8hLuyup/z6cm1PW40XNrAQkkzXwF9AOP/kItcims1VABkC4VmklM3aNtPICV1mv8ecjfBPng4y2Qiwd1HykHNVS8hO2TJpZm1Hgk/kv0splN4LdJ7IhOb5CGk9dUt4qfuqLlYF/SgpoCHo5proHOeCdrPAzxItIwdCej3OpxHoZs7CxUvgZmjRQoKFSpdiJgFy386YS9mk91qlFkrYtaCTNBGd1BG@AOez@WWn@QHW08vg7VxFIeu@IZtB12Qq0c3q1hyniLXSFMr4xdCWlK4nBZxmubFwD1WauFpA0dwX4U1H54R9C4WrtY3Yv9sue8fDP85d0d4LdZYr0RojVS6aTBqhfPj1pHh3SxtL8htROaKcuZdRAtSm9BgD@LEGNUvkWoMm@ThCf3kfCHOOKUVMlxjG5x8rrfJT@Jb9BrTRLTPMlDtA2wifYHVAcHJO5cF01sM63EVWRpTzLU2KbVV2HYKoxBDwI9K1pB0brNTBhSrPHlxeWJi/Lw3St4P6SCyKXiosQKl@cGHt8C6LHzYHMHgCIFyqAbtAyYyFTq36gB3H1uAxWsdTvHSSYmwkjOVRkq@MacX4esWAVIFSx2qrkmFKplGPrvGFzbqmwtr1bygZMXcYbVNqoq7oXShpny6JIqvFqbv5XcDtTCcHW7ZxV9e12ozM2euCblluapwU5jqT9A1sX1MlTXuifzSqTiHNZYtbT8vtxB4azUqO8qRjFEMhRdl76vWPS4TOzuPtAkH1EiHPtGyY1OQzX7OTPjA4WiuTHPoaDXxyZF/A0PUX4y45mZpxtPWX1FypbKyzVJeqvDDt4zBiD98wdNqWb1fqchI2aTVkUIQUm31B5QK5lbxw6mRv3i8lUDLkMYLdcXhrNvrt/yKUKAKxxntmIuo@HJ8Lcdy/Xi/O0G13urqa9gfZX0vc8RmlI7SCTxBdj2oVbIAm/FJFCmz8PA17bjGx7jr@2iUFV@nPAMwn7ktx3P@whmF58Yn7@pY@4O5hgiWoH28glGSobXd7uatSYuS33qLMaMAdZnM7@wE7juLDwl40uvHG2YnGSi6GBfykRmyeHmQJRbyTkfwIRbsgpqoOfwebPUVihkbenRYRPK0CLJXpuZ5VTJ@rlaMjI4arBrgOREZjLNGIhzDRnEuvVVp8keAlyjO396Rc2SCq/C/oCVhgmaDV46PHPxHEKfcbjCMVEaqIiaaBYa32StAskOhWUCiyFHQvEpmCdpAI92OaCu6jmPnwfs8Yu/uvGvR8mM2dtkCKURf8jVn1U5Pak32w2MnR3sX8FjPuNJtpAbsgmdvMHT4P2b3U7BsgIdLmoM3CZ3gaZgltNbwsfVDEcv65zj@G5DQ5MwM/nTYonlWLModzvQhFvWH29E3uyBRtQrmZvEAhrUsixdNrcayEQUs2ASYlTWyCaF5loXxBXfyRUifM19pD5GewC/ImXQCVC3fn7vKxl//MNdcFvLeugiRjIQf3/w7BVDkHL2rk40iNdbhEgOPLdmrMpsFidpBGdRXDuYhsvDyAOtsnpVc2fLXNU3D6d5XruLQ732Fc9Xc87cl9yk2t3foKJxXxIPHuq113q@rbf@f03Y@AQVIQ9z@3PuYzruHmZ1LbNqXhtXFrd612OOjW403VoK/nc3Nj@V1Y/j55ZDKANjb1AeRW/d5KiwJKeUCXfggIyWvCt0Qpeqkml30uibkGAkL40aZl6Vh3zKDCu7Sq8BSKsf@fhIoBhXjvCpHODl46vq0R4243MQBmTZffH8qrCdy/UKYoxZBqvjE6rLxVSc8lDNY02LolSzSAlhPvp0uAc4/GN0cD7zPEB33LVWfdhIN6cPipkZhBHbYgYsWh9qESxCi9ly3qpesyHnTQ5BdQtukHwbXdLmHgu3Tfm1u6VRp4S5cmGOThAE/HmlMFXYTX8vJ1Y5k3IMpboJWG5UmGsuFROdFdfdGGMy2phiiquruYqz1bVNzxnGVbIIYDrhLPK1iHM498rk7xcxlmNYvUHjNImQWlRFXSlRMMKfav9absnQrXBu85M0zWeY5HSUpMvaHQNb6fIKMovF5a@no4vL8@G7X37vLHiPmH7vsCDvcthxk@dd@kxbt@@HXftxHbXClvKcWOHUYec2HA/d/qN35yMJ1QaW8H236NNcTTAtdtbFgZd3V2WZhfm/IqU0y5YVY2lHemGyeqdR3l@8HAwr3blAM3M5fYzN3Xts5tw7q7CtwwttQKHb5JyMisbF6hsCg9raFeioxo733D9wPX/Em7Izo0maoNk6XO3lNt3DLBPmgd5TNtrLYwPyjY4O29MttqxD4rQgMKsRxGpfToPtNAlUpmrFv3XcCdXdbKMwwtEvOe3/DbGRb45lLHnyr9GTIqwrmaMXz190uxtSr359efak3FCahZRVEedCvf7HDJ@t2Nwn6/P0k/JWyFs@qp6sHaq64ypzzf05psxEfOvV6fCOO4sdFySkyGKhKxeRjH6AjlZ2ueYt08Rxsb2iltMGxon9tW//AQ "Assembly (nasm, x64, Linux) – Try It Online")
It's best for debugging to run it under `strace`, or hexdump the output, so you can see verify that there's a `\0` terminator in the right place and so on. But you can see this actually work, and produce `AAAAAACHOO` for an input of 
```
num  equ 698911
table:  db "CHAO"
%endif
    tablen equ $ - table
    db 0  ; "terminator" needed by ascii_compress_stosb_decode_overlap
```
(Actually `xxAAAAAACHOO\0x\0\0...`, because we're dumping from 2 bytes earlier in the buffer out to a fixed length. So we can see that the function wrote the bytes it was supposed to and *didn't* step on any bytes it shouldn't have. The start-pointer passed to the function was the 2nd-last `x` character, which was followed by zeros.)
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 4 bytes
```
ṙ1ṃ@
```
[Try it online!](https://tio.run/##DYoxCgJRDAWvIr92IclPXpLOe6hYbSOLvWDnKTzKHmdPElPMwMA81217Vx37j4/9e6mq6ziN87i9Wp/m0SzjXpwSrDnF4AR1UU0WJvJI4QkBGAYKME8KS529S5JllytAbpEuDE/gDw "Jelly – Try It Online")
`ṃ` is literally a built-in for this. The other three bytes account for Jelly's one-based indexing.
[Answer]
# [Python 2](https://docs.python.org/2/), ~~49~~ 48 bytes
-1 byte thanks to Jo King
```
f=lambda n,s:n and f(n/len(s),s)+s[n%len(s)]or''
```
[Try it online!](https://tio.run/##PZDdasMwDIXv@xQmMJJQb7P8I9uBPMCu9gCpKena0ELnhDi9GOzdMzmFXegDHdnSkaaf5TpGua5De@@/T@eeRZ6ayPp4ZkMV3@@XWKWap3qfuvjyzMI4l@W6XNKS2q6TVgvOuuK34MWxCIF36J0HyNoXaVeKnmLcauClA@2VNGgFaiu19iBBCOu8BIUSEdCgcAighDNeK3ouvTCeMqsRhTXOWwloPWIewqj5IRKeDnjxuk1SWqMRSlI3bZQDAUaDpA9lU3JWHmLmW8Yxo81gGXVGlcHLEMJuGOd8FHaLbNu52bFpvsWFFR9xeiwNzafyv/j5WDaVLO3pgvl02d76Bw "Python 2 – Try It Online")
### Alternative version (won't finish for large numbers), ~~45~~ 43 bytes
-2 bytes thanks to Jo King
```
f=lambda n,s:s*n and f(n/len(s),s)+(s*n)[n]
```
[Try it online!](https://tio.run/##PY9LasMwEIb3OYUQhNiN2mr0GEkGH6CrHsA2xm1iEkjHxlIWhdzdlbPobv4Hw//Nv@kykVrXsb4NP1@ngZGIVXwhNtCJjQW9385UxFLE8lhku2yoW9M5plg3jXJGCsYfPe9Eg8EHgCy/L8O0GdoYtFIrtGis9iDBGlCCHaqW3vqalYU45BoE5cEErSw6icYpYwIokNL5oECjQoT8QnoE0NLbYHSuqyBtyMoZROmsD04BuoCYB7CWHv0r77rdOC0bD7sSe26udmxerpQY/6D5nirGBQm@X/g@/ief9/SMWuLHzL@B83yvfw "Python 2 – Try It Online")
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), ~~3~~ 1 bytes
```
⍘~~θη~~
```
[Try it online!](https://tio.run/##S85ILErOT8z5/z@gKDOvRMMpsTg1uATITNfQ1LT@/z/a2MTEzNTA2MjM1MzE1NjC0MDQ1MTQSEchWt1KXUdBPSYPROqBiHgQYQsiFECEJojQABE66rGx/3XLcgA "Charcoal – Try It Online") Link is to verbose version of code. Edit: Saved 2 bytes thanks to @ASCII-only. Previous version before the builtin was added, 8 bytes:
```
⭆↨θＬη§ηι
```
[Try it online!](https://tio.run/##FcXBCsIwDADQX8mtCURZ13aI4kFvgoLgcQ4ps6yDUXUW8e@rubzXRz/3Dz@Vcp7HlPGS/w0n/8S9fwd8MRxDGnLESMSwy4d0D1@MDCMRbUppjbWNq0zduMY6s9KVdlbXDK1aKwZ1TeJSuAlbAQQSUGDVdWXxmX4 "Charcoal – Try It Online") Link is to verbose version of code. Explanation:
```
    η       Second input
   Ｌ        Length
  θ         First input
 ↨          Base convert to array
⭆           Map over values and join
      η     Second input
       ι    Current value
     §      Index into list
            Implicitly print result
```
[Answer]
# [D](https://dlang.org/), 112 bytes
```
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;}
```
[Try it online!](https://tio.run/##Vc7BagIxEAbgs/sUo1CYgXVbi1gl7CknoUdvIiWbjd1ATCQ7sQe7ffVtKi3Uw1zm//hn2nG0p3OIDD23lQ7@IiQklOWWcAu@lNDQVQKLY4h54eqmcsa/cye88I@1I645TCX6B0dfN2WU7jCaI2jBpOtmr@fL9UFEwyn6XDSMKnEA1etOxR53hDvQBFf4E2GKP9H@QKhJwFAUl2BbOCnrMbti8u/hPDaIYvIRLRvnMeHzy/IpvZYw@3ybVb9HiO7IarPeLBY3lONwx4bxGw "D – Try It Online")
This is a port of [HatsuPointerKun's C++ answer](https://codegolf.stackexchange.com/a/166852/55550)
The calling style is `u(ulong(n), to!(char[])(b))`, where `n` and `b` are the left and right arguments
## D specific stuff
Sadly, we need to import `std.conv` to do any type conversions above **very** basic type conversion.
Using the golfy template system, and giving the function the required types (which is why calling it is not just `u(n,b)`), we can shorten occurrences of `char[]` and `ulong` to `1` byte each, when inside f the function.
D initializes our types for us, so `C t;` is short for `C t=cast(char[])([])`
`to!C` converts the integer `n%l` to a character array (using codepoints), and `~` is concatenation
`foreach(ref c;t)` is like C++'s `for(... : ...)` loop, but a little longer. `ref` is like `&`, it treats `c` as copied-by-reference (i.e., we can modify `t`). Luckily, D infers the type of `c` without *any* keyword denoting type.
[Answer]
## C++, ~~150~~ 144 bytes, `uint64` input
-6 bytes thanks to 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;}
```
Using a variable to store the size would increase the bytecount by 1
To call the function :
```
u(2740, "|_")
```
First the number, second is the string ( char array )
Test cases :
```
std::cout << u(2740, "|_") << '\n' << u(698911, "chao") << '\n';
return 0;
```
[Answer]
# Twig, 66 bytes
Created a `macro` that must be `import`ed into a template.
```
{%macro d(n,c)%}{%for N in n|split%}{{c[N]}}{%endfor%}{%endmacro%}
```
---
## Values expected:
For the first arguments (`n`):
* number
* string
For the second argument (`c`):
* Array of numbers
* Array of strings
---
## How to use:
* Create a `.twig` file
* Add `{% import 'file.twig' as uncompress %}`
* Call the macro `uncompress.d()`
## Ungolfed (non-functional):
```
{% macro d(numbers, chars) %}
    {% for number in numbers|split %}
        {{ chars[number] }}
    {% endfor %}
{% endmacro %}
```
---
---
You can test this code on: <https://twigfiddle.com/54a0i9>
[Answer]
# Pyth, ~~9~~ ~~8~~ 7 bytes
```
s@LQjEl
```
Saved a byte thanks to hakr14 and another thanks to Mr. Xcoder.  
[Try it here](http://pyth.herokuapp.com/?code=s%40LQjEl&input=%5B%22+%22%2C%22%5Cn%22%2C%22%7C%22%2C%22_%22%2C%22-%22%5D%0A1928149325670647244912100789213626616560861130859431492905908574660758972167966&debug=0)
### Explanation
```
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.
```
[Answer]
# C89, limited-range signed `int n`, ~~64~~ 53 bytes
* changelog: take a `char **out` and modify it, instead of taking and returning a `char *`
Takes the number as an `int`, the lookup table as an array + length.  
Output is written into a `char *outbuf`. Caller passes (by reference) a pointer to the end of the buffer. Function modifies that pointer to point to the first byte of the string on return.
```
g(n,I,B,O)char*I,**O;{for(**O=0;n;n/=B)*--*O=I[n%B];}
```
This is valid C89, and works correctly even with optimization enabled. i.e. doesn't depend on gcc `-O0` behaviour when falling off the end of a non-void function or have any other UB.
Passing a pointer to the end of a buffer is normal for an optimized int->string function, such as [glibc's internal `_itoa`](https://code.woboq.org/userspace/glibc/sysdeps/generic/_itoa.h.html#39). See [this answer](https://stackoverflow.com/questions/13166064/how-do-i-print-an-integer-in-assembly-level-programming-without-printf-from-the/46301894#46301894) for a detailed explanation of breaking an integer into digits with a div / mod loop like we're doing here, in C as well as x86-64 asm. If the base is a power of 2, you can shift/mask to extract digits MSD first, but otherwise the only good option is least-significant-digit first (with modulo).
[Try it online!](https://tio.run/##lVRNb5tAEL3zK0aJ0gCF2E6rKJi6B/fQ@uRjD6kVLbDgVWGX7i5J3Mh/vXQG8FdaNSoHaz0fb2bevN00LNK0bQtXBotgHiy9dM20vwh8fxk/50q7eJiNYxnL0Wzu@WGIfxd38mK@irftPM67vNOs@cxYXXLpLrz4FQTHGflQTIE/1aVIhQ0xrbBrKJX63tRgWVLyAAZjzYzhGTADTCq75hqYLhzwIZ@CqP4FQCmATQlJ8SPHORc5jOHkw0YaWagyxxIPXBuhZBeKdiEtSJgB1gTZVAnXVJWsc7Qa8ZODymGB54QZTj6iA3yyCFk3tu/j4PCXO89INZYCcJLdfMkGNM@nFI0fdsGl1Zsp1Aor4tBWdY2UzFiMtV3tASVp8pzrq6PUJ2Gn8DI1F/oolyzjEN2VkMxiAz1R2N8pbMfcgxLZnqf7v6rGeXaoej8pISiD06JjR/PnU5Ibww26gaNh84hr5fDIyQpDMpalzAPWOD7d2773bpah6WGKIZl0uJOgs0tFLe4xB0USXK1V1qQcJv0MDLcDVlSoo4ynmle4D0I@qrXjd9cprbdHjp2tc85lJnKHVCfTssk4fDA2E@pq/fHUVIrkpY1mIJtDaquYkC4dUC1pMDCM54e7lTew3km1qbA@s0q4nXOy8uKjlfSKnEHnu17FzsGHPeOu76JoFcOfH1LDUtuwchAEyvRHI3pCQBi8c8V94koPsfHoYhveiA79a3Cg/bXPhygivEQUqH3VFGtaHy7h5n2YCEsz8oJuv8y6CwfXV/@B/ZVDpuSlxV@8HhZ3g1qsNU8FqTEm2ec4JmlQyXLTCdGIQmIUkUtPAgFVvDLcuj1jAVw@XQbYtvdCmSgMgxKn9jOeNEVxJMn9BenFgjBvo9t4eJt60RKHQf9QBPAGg3CR57ykN2bYNRJLT1D/3naBw66Lk1z0HgF0cqSgGuVlc/fswnyTZwH0/s6juW20xJvmbNv2JrqNJpP20xe2/JXmJStMGy7ftSFKdpbeRr8B "C (gcc) – Try It Online"). Ungolfed version:
```
/* 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;
}
```
In this explicit-length version, the input is a `char table[]` which does *not* need a terminating 0 byte, because we never treat it as a string. It could be an `int table[]` for all we care. C doesn't have containers that know their own length, so pointer+length is the normal way to pass an array with a size. So we choose that instead of needing to `strlen`.
The maximum buffer size is approximately `sizeof(int)*CHAR_BIT + 1`, so it's small and compile-time constant. (We use this much space with base=2 and all the bits set to 1.) e.g. 33 bytes for 32 bit integers, including the `0` terminator.
---
# C89, signed `int`, table as an implicit-length C string, 65 bytes
```
B;f(n,I,O)char*I,**O;{B=strlen(I);for(**O=0;n;n/=B)*--*O=I[n%B];}
```
This is the same thing but the input is an implicit-length string so we have to find the length ourselves.
[Answer]
# [Bash + core utilities](https://www.gnu.org/software/bash/), 49 bytes
```
dc -e`echo -en $2|wc -c`o$1p|tr -dc 0-9|tr 0-9 $2
```
[Try it online!](https://tio.run/##FYpLDsIwDAWvkkW3kWzHeY7vUolCqNRViwCJTe@emtW8zzzun22MZ095Xda@HcE9TXL@YunLMfHr/L5TDoGy/2Mg/jEGuzRWL1JhBDVRdRYmsubCBQIwKqiBuVCrriV0caoezRQgq81NGObAmElp3s9bvgA "Bash – Try It Online")
# Comments/explanation
This takes command-line arguments as input (the number in base 10, then a single string with the list of characters) and outputs to stdout. Special characters like space, newline, etc may be entered in octal notation (for example, `\040` for a space), or `\n` for a newline, `\t` for tab, or any other escape sequence that `echo -e` and `tr` interpret identically.
A lot of the bytes here are to handle special characters and larger test cases. If I only have to handle non-terrible characters and the numbers are small (for example, the first test case), the following 24 bytes will do it:
```
dc -e${#2}o$1p|tr 0-9 $2
```
This uses parameter expansion `${#2}` to get the number of characters in the string, builds a dc program to do the base conversion, and then sends the converted number through `tr`.
This won't handle newlines or spaces or tabs, though, so to deal with escape sequences without affecting the base, I do a character count `wc -c` after interpreting the escapes with `echo -en`. This expands the program to 38 bytes:
```
dc -e`echo -en $2|wc -c`o$1p|tr 0-9 $2
```
Unfortunately, dc has an annoying "feature" where if it's outputting a large number, it will line wrap it with a slash+newline sequence, so the larger test cases have this extra output. To remove it, I pipe dc's output through `tr -dc 0-9` to remove non-numeric characters. And there we are.
[Answer]
# [APL (Dyalog Unicode)](https://www.dyalog.com/), ~~14 13~~ 12 bytes
```
⊢⌷⍨∘⊂⊥⍣¯1⍨∘≢
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT///qG@qp/@jtgkGXECWWxCQZWhkYf7/UdeiRz3bH/WueNQx41FX06OupY96Fx9abwgV6Vz0Pw2o9FFvH0R/V/Oh9caP2iYCecFBzkAyxMMz@L@RuYmBQpoCkOsV7O@nrlQTr6TOZWZpYWloiCycnJGYD5QwNjExMzUwNjIzNTMxNbYwNDA0NTE0QlZoFZOnF2@roKmho6QOAA "APL (Dyalog Unicode) – Try It Online")
Infix tacit function; can't handle the largest test case because of floating point representation.
Saved ~~1~~ 2 bytes thanks to @Adám!
~~13 bytes added for the headers: `⎕IO←0`: **I**ndex **O**rigin = 0 and `⎕FR←1287`: **F**loat **R**epresentation = 128 bits.~~ (I'd forgotten that this [doesn't apply.](https://codegolf.meta.stackexchange.com/a/14232/43319))
### How?
```
⊢⌷⍨∘⊂⊥⍣¯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.
```
[Answer]
# [Attache](https://github.com/ConorOBrien-Foxx/Attache), 17 bytes
```
{_[_2&ToBase!#_]}
```
[Try it online!](https://tio.run/##RY7BTsMwDIbvfYoQ0AQioNhJnGTSpAluHBCH3UoUVaVlk1A30d7GePXisMMs@ZNs//bvZpqadtvNvViuxHzMdcbFZv/UjN3VdU6n@bXrPsb65nBoP1NVvX3vhmnTjdMzC8b6@NXf59P6Zb8b1ovfXom6Ehw1equ5kD9SySxTUuc2xRAByqDlwZaz4dxfBBAxgI0GHXlN1qO1ERC09iEiGEIiIEc6EIDRwUVrWI5Ru8iVt0TauxA9AvlIVJwEO7wPjPMvSj5c7Iy15LRBPmmdCaDBWcCytZRK/K8J@ViQC1YFouCu4LZA8bUqpfkP "Attache – Try It Online")
## Explanation
```
{_[_2&ToBase!#_]}
{               }  ?? anonymous lambda; input: _ = dictionary, _2 = encoded
   _2&ToBase       ?? convert _2 to base
            !#_    ?? ... Size[_]
 _[            ]   ?? and take those members from the dictionary
```
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 1 byte
```
τ
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCLPhCIsIiIsIlwiOlxcbi5fPSApKCxcIlxuMzQ0NjUwMzI2NTY0NTM4MTAxNTQxMiJd)
# [05AB1E](https://github.com/Adriandmen/05AB1E), 3 bytes
```
ÅвJ
```
[Try it online!](https://tio.run/##yy9OTMpM/f//cOuFTV7//yspKVlx6cXbKmhq6ADZXMYmJmamBsZGZqZmJqbGFoYGhqYmhkYA "05AB1E – Try It Online")
[Answer]
# [Canvas](https://github.com/dzaima/Canvas), 7 [bytes](https://github.com/dzaima/Canvas/blob/master/files/chartable.md)
```
Ｌ┬｛╵⁸＠ｐ
```
[Try it here!](https://dzaima.github.io/Canvas/?u=JXVGRjJDJXUyNTJDJXVGRjVCJXUyNTc1JXUyMDc4JXVGRjIwJXVGRjUw,i=JTVCJTIyJTIwJTIyJTJDJTIyJTVDbiUyMiUyQyUyMiU3QyUyMiUyQyUyMl8lMjIlMkMlMjItJTIyJTVEJTBBMTkyODE0OTMyNTY3MDY0NzI0NDkxMjEwMDc4OTIxMzYyNjYxNjU2MDg2MTEzMDg1OTQzMTQ5MjkwNTkwODU3NDY2MDc1ODk3MjE2Nzk2Ng__,v=3)
Straight forward implementation:
```
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
```
The input character set can be a string too as long as it doesn't contain a newline, because Canvas doesn't have a newline character & automatically converts it to a 2D object.
[Answer]
# [Stax](https://github.com/tomtheisen/stax), ~~6~~ 5 bytes
```
n%|E@
```
[Run and debug it](https://staxlang.xyz/#c=n%25%7CE%40&i=%22%7C_%22+2740%0A%22chao%22+698911%0A%22+%5Cn%7C_-%22+1928149325670647244912100789213626616560861130859431492905908574660758972167966%0A%22%3A%5Cn._%3D+%29%28,%22+3446503265645381015412&m=2)
Explanation:
```
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
```
[Answer]
# [SOGL V0.12](https://github.com/dzaima/SOGLOnline), 10 [bytes](https://github.com/dzaima/SOGL/blob/master/chartable.md)
```
l;A─{IaWp}
```
[Try it Here!](https://dzaima.github.io/SOGLOnline/?code=bCUzQkEldTI1MDAlN0JJYVdwJTdEZiUwQS4lMkMldTIxOTJm,inputs=MTkyODE0OTMyNTY3MDY0NzI0NDkxMjEwMDc4OTIxMzYyNjYxNjU2MDg2MTEzMDg1OTQzMTQ5MjkwNTkwODU3NDY2MDc1ODk3MjE2Nzk2NiUwQSUyMiUyMCU1Q24lN0NfLSUyMg__,v=0.12)
Pretty long, considering the idea is pretty much implemented in the language: [here](https://dzaima.github.io/SOGLOnline/compression/index.html), entering 
```
¶    __   __    ¶   |  |_|  |   ¶___|       |___¶-   -   -   -  ¶ - - - - - - - ¶- - - - - - - -¶_______________¶
```
gives out a compressed string using this method.
[Answer]
# [Ruby](https://www.ruby-lang.org/), 31 bytes
```
->n,b{n.to_s(b.size).tr"0-9",b}
```
[Try it online!](https://tio.run/##NY7BbsIwDIbvfYooF2BKq9hxnBiJvUhXoXYa2g4riJbDoDx752rd4bPk3/5/@3rrfubTYS5fe9c9@mo8H4dtVw1f949dNV6tL8W67jnXNSbyztR2ss4ebdO4wtQsWQAW9V3VT6VVzusUBDOQBIycPFNCIgEE71MWhMDIDBzZZwYIPkehoOsoPop2iZh9ilkSAidhXs4YjX/rtfx94Wy53gpEHH1AzaMYMniIBLhY9v@WarUclCVnp2wVpxFN9d1ezGNqXTcVxpjLbRzMqdb2ZbNpimcx/wI "Ruby – Try It Online")
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 2 bytes
```
:B
```
[Run and debug it](https://staxlang.xyz/#c=%3AB&i=1928149325670647244912100789213626616560861130859431492905908574660758972167966,+[%22+%22,%22%5Cn%22,%22%7C%22,%22_%22,%22-%22]%0A&a=1)
`:B` is an instruction in stax that does this. It would normally operate on a "string"\* instead of an array of "strings". In the end, this means that the output is an array of single character arrays. But output implicitly flattens anyway.
\*Stax doesn't actually have a string type. Text is represented by integer arrays of codepoints.
[Answer]
# [J](http://jsoftware.com/), 12 bytes
```
]{~#@]#.inv[
```
## How?
```
      #.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        
```
[Try it online!](https://tio.run/##NY3LCsJADEX3/Yqgi1GoQ5LJZCaFguAfuBUpIpbqQheCCD5@vdbX8h4u5xz69lx7QKgA@/XtOZ6vx35/vKz6aTHy4NraOyjhUUF7LordtjsBJ0Fowd0b9wVq2YjeaNttTg6@NIhoxMAaVWLIhBSF@Pq@Va6ExbIE55sappPy5yHjTGKBoyZUSSxixISYsjEFZVUabJiVKGCOJmG4s2G0YSVRxRSzJSZNpvpJwT91b2YO@hc "J – Try It Online")
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 49 bytes
```
Outer[Part,{#},#2~IntegerDigits~Tr[1^#]+1,1]<>""&
```
[Try it online!](https://tio.run/##JY4xT8MwEIV3/4rIkapWGPCd7bMNFGVgYaIDWwhVVKVthgbJmCmkfz3YZLhPuvfe6d2ljefu0sb@0M7H7Xp@@4ldqHdtiGIsJ1Hi9XWI3akLL/2pj9/X91DDZ9ncgIDm6Znz1bx5ZLvQD7E@VlUpOOPN6r4aGRtH/ssF3/NJFGi1nESWDkk6p2nTfGWLvPMAi1kk8WNIWA4Fv80J8OhAe4WGrCRtUWsPCFJa5xEUIRGQIekIQElnvFYpjl4anzariaQ1zlsEsp5oqXrgovjvKvhdxj5jm1FkbDLWGSK/oLQmIxWmGm2UAwlGA06MTfMf "Wolfram Language (Mathematica) – Try It Online")
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 110 bytes
```
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;}
```
[Try it online!](https://tio.run/##LZDRasMwDEXf8xUmELCCxpo9lAbhr8hjaoJnksbQucVKW4/Sb/firHoQF46udJH9OFmbkp1NENy3rcYud3I0yYgDZFAP9HSKl3AevRyAalZ1p3b0mN15lBH4GpxfJtlhWdmKSxz6WDmNDLia7PVXMnaA8VM5iorpldZx8WOcl1mYcLIotgT1qu@9huJZiLUy/TY8CiXMcnFyo40G2ui/w86ZZvClqdjAO05Z8dGXKCaZd@QLAO@JMC634MWOildK@/bQNk1@weUP "C (gcc) – Try It Online")
Description:
```
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
```
[Answer]
# [CJam](https://sourceforge.net/p/cjam), 11 bytes
```
liq_,@\b\f=
```
[Try it online!](https://tio.run/##DcoxCgJRDATQfk/hARQy@ckkUwgeZGFRQVC0sPfu3y0fvPvr@pnz/fxux8t6Wx/nOSFvhIYnyxjlEYLDrFqOQSfBpDWBYZ2KsXeXpXZVkFbZKgdL5HJYftvpDw "CJam – Try It Online") Takes input as the number, then a newline, then the characters in the ASCII art.
## Explanation
```
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
```
[Answer]
# JavaScript, 39 bytes
Port of [Rod's Python solution](https://codegolf.stackexchange.com/a/166718/58974).
```
s=>g=n=>n?g(n/(l=s.length)|0)+s[n%l]:""
```
[Try it online](https://tio.run/##BcFRCoMwDADQuxQGCUOnP2MK0YMMP0ptqxISMWVfu3t97/A/b@Haz9KIrrEmqkZTJqFJ5gzyAiZrOUouG/47fNpXHryMztWgYsqxZc2QwIXNq0N4D5@h7xHrDQ)
]