text:
Insulate the Window Glass and Foil of your house
Introduction:
The best options for the glass of your house will:
1. Let through as little heat as possible in both directions (insulation-value Ug).
(2. Let through as much sunbeams as possible from the outside to the inside.)
(3. Let through as much light as possible from the outside to the inside.)
We only care about the first one for this challenge.
In addition, there are different types of glass changing the Ug: regular single glass; regular double glass; HR double glass; HR+ double glass; HR++ double glass; HR+++ double glass.
HR = High Rendement glass; regular double glass with have air between both layers, but HR will have a noble gas between both layers.
Sources (not very useful for most though, because they are in Dutch, but added them anyway): Insulate and save money and What is HR++ glass?
Challenge:
Input: A string indicating glass and window foil (below the possible input-strings are explained)
Output: (Calculate and) output the heat-transition Ug
Here a table with all glass options and the expected output Ug-values:
Glass (optional foil)    Ug-value    Description

|                        5.8         Single-layered regular glass
||                       2.7         Double-layered regular glass
| |                      1.85        HR glass
|+|                      1.45        HR+ glass
|++|                     1.2         HR++ glass
|+++|                    0.7         HR+++ glass
|r                       3.4         Single-layered regular glass with reflective foil
||r                      2.1         Double-layered regular glass with reflective foil
|f                       2.8         Single-layered regular glass with regular window-foil
||f                      2.0         Double-layered regular glass with regular window-foil

|g                       4.35        | with insulating curtain
||g                      2.025       || with insulating curtain
| |g                     1.3875      | | with insulating curtain
|+|g                     1.0875      |+| with insulating curtain
|++|g                    0.9         |++| with insulating curtain
|+++|g                   0.525       |+++| with insulating curtain
|rg                      2.55        |r with insulating curtain
||rg                     1.575       ||r with insulating curtain
|fg                      2.1         |f with insulating curtain
||fg                     1.5         ||f with insulating curtain

/                        8.7         Diagonal |
//                       4.05        Diagonal ||
/ /                      2.775       Diagonal | |
/+/                      2.175       Diagonal |+|
/++/                     1.8         Diagonal |++|
/+++/                    1.05        Diagonal |+++|
/r                       5.1         Diagonal |r
//r                      3.15        Diagonal ||r
/f                       4.2         Diagonal |f
//f                      3.0         Diagonal ||f

/g                       6.525       Diagonal | with insulating curtain
//g                      3.0375      Diagonal || with insulating curtain
/ /g                     2.08125     Diagonal | | with insulating curtain
/+/g                     1.63125     Diagonal |+| with insulating curtain
/++/g                    1.35        Diagonal |++| with insulating curtain
/+++/g                   0.7875      Diagonal |+++| with insulating curtain
/rg                      3.825       Diagonal |r with insulating  curtain
//rg                     2.3625      Diagonal ||r with insulating curtain
/fg                      3.15        Diagonal |f with insulating curtain
//fg                     2.25        Diagonal ||f with insulating curtain

Some things to note about the values: the first ten are all the different default values (taken from the two linked sources). Adding a g (insulating curtain) lowers that value by 25%. Having a / (diagonal window) increases that value by 50%.
Challenge rules:

You can ignore any floating point precision errors
You can use the default decimal output-format of your languages, so if 3.0 is output as 3 instead; or if 0.9 is output as 0.900 or .9 instead, it doesn't matter.
You'll only have to worry about the input-options given above. Inputting anything else may result in undefined behavior (weird outputs, errors, etc.)

General rules:

This is code-golf, so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
Default Loopholes are forbidden.
If possible, please add a link with a test for your code.
Also, please add an explanation of your answer.

One never has too much isolation during a (Dutch) heat wave.

@Giuseppe You're completely right. In Dutch it's "isoleren", hence the translation error. Dutch to English it's "isoleren" = "insulating" and "isolatie" = "isolation". Should be fixed now.

The order for diagonal/insulating curtain shouldn't matter, since they correspond to multiplication (i.e. Ug*1.5*0.75=Ug*0.75*1.5)

@boboquack You're indeed correct. Not sure why I added it in the first place.. Removed. Thanks.

Python 2, 172 147 128 117 112 99 bytes
lambda w:ord('8%06(*D0t0'[sum(map(ord,w.strip('g')))%77%24%13])*(2+('/'in w))*(4-('g'in w))/160.

Try it online!

Explanation:
Encodes the window as a sum of the ordinals of each char (without trailing g):
sum(map(ord,w[:(w+'g').find('g')]))

|      ->   124                /      ->   47
||     ->   248                //     ->   94
| |    ->   280                / /    ->   126
|+|    ->   291                /+/    ->   137
|++|   ->   334                /++/   ->   180
|+++|  ->   377                /+++/  ->   223
|r     ->   238                /r     ->   161
||r    ->   362                //r    ->   208
|f     ->   226                /f     ->   149
||f    ->   350                //f    ->   196

These are modded (%77%24%13), which gives values from 0 to 12):
sum(map(ord,w[:(w+'g').find('g')]))%77%24%13

|      ->   124   ->   10      /      ->   47    ->   10
||     ->   248   ->   4       //     ->   94    ->   4
| |    ->   280   ->   1       / /    ->   126   ->   1
|+|    ->   291   ->   12      /+/    ->   137   ->   12
|++|   ->   334   ->   2       /++/   ->   180   ->   2
|+++|  ->   377   ->   8       /+++/  ->   223   ->   8
|r     ->   238   ->   7       /r     ->   161   ->   7
||r    ->   362   ->   6       //r    ->   208   ->   6
|f     ->   226   ->   0       /f     ->   149   ->   0
||f    ->   350   ->   5       //f    ->   196   ->   5

The Ug values are multiplied by 20 and mapped to chars:
[0.7,    1.2,    1.45,   1.85,  2.0,  2.1,  2.7,  2.8,  3.4, 5.8]
[14,     24,     29,     37,    40,   42,   54,   56,   68,  116]
['\x0e', '\x18', '\x1d', '%',   '(',  '*',  '6',  '8',  'D', 't']

These chars are then ordered accordingly to the window-types, and padded with '0's. This new strign is used to look up the value based on the index.
'8%\x1806(*D\x0e0t0\x1d'#[sum(map(ord,w[:(w+'g').find('g')]))%77%24%13])

Lastly the given character is converted back into a number, and multiplied be the diagonal window and isolating curtain factors
*(2+('/'in w))*(4-('g'in w))/160.
equivalent to:
*2/2 or 3/2   * 4/4 or 3/4  /20

Saved

-5 bytes, thanks to ovs
-13 bytes, thanks to Lynn

-5 bytes by a shorter way to remove the (trailing) g.

w.strip('g') is even shorter.

You can replace the \x sequences with actual low-ASCII chars for 99 bytes.

@Lynn I didn't know about the strip thing, thanks

Java (JDK 10), 110 bytes
s->"8%06(*D0t0".charAt(s.split("g")[0].chars().sum()%77%24%13)*(s.charAt(0)%2+2)*(s.endsWith("g")?3:4)/160d

Try it online!
Credits

Port of TFeld's Python 2 answer.
-1 byte thanks to Kevin Cruijssen.

-1 byte changing s.matches("/.*") to s.charAt(0)==47.

JavaScript (ES6), 111 109 bytes
s=>'_FQLKIe%f:}'.charCodeAt((g=c=>~-s.split(c).length)(/\W/)+3*g` `+6*g`r`+8*g`f`)*5%117/(g`g`?8:g`|`?6:4)*.3

Try it online!
How?
We define the helper function g() as:
g = c => ~-s.split(c).length

split() takes either a string or a regular expression as input. Hence, so does g().
We define:
- N = g(/\W/) = number of non-alphanumeric characters
- S = g(' ')  = number of spaces
- R = g('r')  = number of "r"
- F = g('f')  = number of "f"
- G = g('g')  = number of "g"
- P = g('|')  = number of "|"

The formula n = N + 3S + 6R + 8F gives a unique identifier in [1..10] for all default values:
 input   | N | S | R | F | n
---------+---+---+---+---+----
 "|"     | 1 | 0 | 0 | 0 | 1
 "||"    | 2 | 0 | 0 | 0 | 2       NB: because 'g' characters are ignored in this formula
 "| |"   | 3 | 1 | 0 | 0 | 6           and because a '/' is counted the same way as a '|',
 "|+|"   | 3 | 0 | 0 | 0 | 3           the 2 other sets of inputs give the same results.
 "|++|"  | 4 | 0 | 0 | 0 | 4
 "|+++|" | 5 | 0 | 0 | 0 | 5
 "|r"    | 1 | 0 | 1 | 0 | 7
 "||r"   | 2 | 0 | 1 | 0 | 8
 "|f"    | 1 | 0 | 0 | 1 | 9
 "||f"   | 2 | 0 | 0 | 1 | 10

We use this identifier to pick the corresponding entry from the following 1-indexed array, which contains the default values multiplied by 20:
[116, 54, 29, 24, 14, 37, 68, 42, 56, 40]

This array is encoded as the string "FQLKIe%f:}". For each character, we multiply the ASCII code by 5 and apply a modulo 117:
 char | code | * 5 | mod 117
------+------+-----+---------
 'F'  |   70 | 350 |   116
 'Q'  |   81 | 405 |    54
 'L'  |   76 | 380 |    29
 'K'  |   75 | 375 |    24
 'I'  |   73 | 365 |    14
 'e'  |  101 | 505 |    37
 '%'  |   37 | 185 |    68
 'f'  |  102 | 510 |    42
 ':'  |   58 | 290 |    56
 '}'  |  125 | 625 |    40

Finally, we divide this value by:

80 / 3 if G is non-zero
60 / 3 if P is non-zero
40 / 3 otherwise

Excel & CSV, 194 bytes
,"=HLOOKUP(SUBSTITUTE(SUBSTITUTE(A1,""g"",),""/"",""|""),2:3,2,)*IF(CODE(A1)=47,1.5,1)*IF(RIGHT(A1,1)=""g"",0.75,1)"
|,||,| |,|+|,|++|,|+++|,|r,||r,|f,||f
5.8,2.7,1.85,1.45,1.2,0.7,3.4,2.1,2.8,2

Input entered before the first ,n and saved as CSV.
When opened in Excel, Cell B1 displays result.
Sample usage:
/+++/g,"=HLOOKUP(SUBSTITUTE(SUBSTITUTE(A1,""g"",),""/"",""|""),2:3,2,)*IF(CODE(A1)=47,1.5,1)*IF(RIGHT(A1,1)=""g"",0.75,1)"
|,||,| |,|+|,|++|,|+++|,|r,||r,|f,||f
5.8,2.7,1.85,1.45,1.2,0.7,3.4,2.1,2.8,2

Opens as:
/+++/g  0.7875
|       ||      | |     |+|     |++|    |+++|   |r      ||r     |f      ||f
5.8     2.7     1.85    1.45    1.2     0.7     3.4     2.1     2.8     2


text:
Decode My String (Brackets)
Taken from StackOverflow Question
Challenge
Given an encoded string in format n[s] where n is the amount of times s will be repeated, your task is to output the corresponding decoded string.

n will always be a positive number
s can not contain empty spaces
strings only contains letters from the alphabet
s length can be >= 1
encoded format is number [ string ]
string can have nested encoded string number [ number [ string ] ]
return the same string if not encoded

Examples
2[a]                 => aa
3[2[a]]              => aaaaaa
2[b3[a]]             => baaabaaa
3[a]5[r3[c]2[b]]a    => aaarcccbbrcccbbrcccbbrcccbbrcccbba
a                    => a  // Not Encoded
3                    => 3  // Not Encoded
3a3[b]               => 3abbb
10[b20[a]]           => baaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaa
3[hello]             => hellohellohello

Other test cases
a[a] => a[a]
a1[a] => aa
3[] =>    // Nothing because are 3 empty string
2[2][a] => 2[2][a]

This is my own submission.

f=i=>(r=/(\d+)\[([a-z]*)\]/g).test(l=i.replace(r,(m,n,s)=>s.repeat(n)))?f(l):l

console.log(f("2[a]"))
console.log(f("3[2[a]]"))
console.log(f("2[b3[a]]"))
console.log(f("3[a]5[r3[c]2[b]]a"))
console.log(f("a"))
console.log(f("3"))
console.log(f("3a3[b]"))
console.log(f("10[b20[a]]"))
console.log(f("3[hello]"))

If more test cases needed please tell me.

Usually, someone who suggests a challenge, first tries putting it on the sandbox and doesn't answer it before a few days...

Can the string consist of multiple characters?

@JonathanFrech Yes. string length is >= 1

New test case: a[a].

Numbers can apparently be part of the strings, so what about: 12[a]? aaaaaaaaaaaa or 1aa? And why?

Other test case: 3[]

New test case: 2[2][a]

@StewieGriffin n will always be a positive number so 12[a] => aaaaaaaaaaaa

Why is 2[2][a] returned as unmodified string? Shouldn't it go 2[2][a] -> 22[a] -> aaaaaaaaaaaaaaaaaaaaaa? Or can string only contain lower case alphabet?

@JungHwanMin no because an encoded string follows the format number [ string ], in the case of 2[2][a] it has the format number [ number ]  so it is assumed as is not encoded and return the same string if not encoded

A number can be a string. e.g. "22" is a string.

May we use uppercase instead of lowercase?

@JungHwanMin Sorry, I have to specify string can only contain letters from the alphabet. My bad

@Adám Yes.....,

@LuisfelipeDejesusMunoz Your spec doesn't say that the letters are single-case.

Would 8s (as an example) be valid input?

@Shaggy 8s is a valid input, but not an encoded string. It will output 8s

Will the input ever contain unmatched square brackets? e.g., 8s].

@Shaggy. No.....

This looks mostly good, but the 3[] test case is unclear to me: if the length of s is guaranteed to be at least 1, why is there a test case that has an s of length 0?

Very similar

@ETHproductions Ah, that's the one. I knew I did a similar challenge before, but couldn't remember which. But that's indeed the one I was thinking of.

@ETHproductions It's not very similar: it's a dupe... What does the fact that the number is after change? I can't close-vote anymore since I close-voted the first round.

QuadR, 17 + ≡ flag = 28 bytes
\d+\[\pL*]
∊(⍎⍵M∩⎕D)⍴⊂⍵M∩⎕A

Try it online!
Find:
 \d+\[\pL*] find digit(s) followed by bracketed Letters
Replace with:
⎕A uppercase Alphabet
 ⍵M∩ intersection of Match and that
 ⊂ enclose (to treat as a whole)
 (…)⍴ reshape to length:
  ⎕D Digits
  ⍵M∩ intersection of Match and that
  ⍎ execute (converts text to number)
 ∊ ϵnlist (flatten)

This is equivalent to the Dyalog APL function:
'\d+\[\pL*]'⎕R{∊(⍎⍵.Match∩⎕D)⍴⊂⍵.Match∩⎕A}⍣≡

Perl 6,  44  36 bytes
{({S{(\d+)\[(<:L>*)\]}=$1 x$0}...*eq*).tail}

Test it
Nil while s{(\d+)\[(<:L>*)\]}=$1 x$0

Test it (with -p)
Expanded:
Nil                   # silence warning by using Nil rather than 0

while                 # do the above while the following is truish

  s {                 # string replace (implicitly on $_)

    ( \d+ )           # capture a series of digits into $0
    \[
      ( <:L>* )       # capture letters
    \]

  } = $1 x $0         # replace it with the string repeated by the number

Retina, 24 bytes
+`(\d+)\[(\p{L}*)]
$1*$2

Try it online!
Updated to support additional test cases. -1 thanks to @Adám!

Fails on "3[]" and "aaaaaaaaaaaaaaaaaaaaaa". (Should give "" and "2[2][a]".) Replacing \w+ with \p{L}* fixes these.

I think you can remove the \ before ].

I don't know retina, but is changing \p{L} to \w valid?

@tsh That would be invalid for 2[2][a]

@tsh I had that before (when that test case didn't exist) and as Mr. Xcoder correctly points out, that test case invalidates it...

Perl 5, 36 bytes
0while s/(\d+)\[([a-z]*)]/$2x$1/e

Japt v2.0a0, 19 bytes
e/(\d+).(\l+)]/@ZpY

Try it

"[11a]" produces "[1a"

@recursive, according to the spec, that wouldn't be valid input; square brackets can only contain letters.

"2[2][a]" is given as a test case.  I interpret that to mean that the pattern should apply iff the square braces only contain letters.

Stax, 21 bytes
è/g1┘+α╣m?╣t╥ó⌂ß─"H║à

Run and debug it

ReRegex, 83 bytes
#import base
(\d+)\[([a-z]+)]/Au<$1>,$2,B/_,([a-z]+),/,$1,$1/A,.*?,(.*?)B/$1/#input

ReRegex is a language designed around regex. Sadly, it doesn't really understand numbers. So repeating the string is the hardest part of this.
Try it online!

Red, 158 bytes
func[s][b: charset[not"[]"]d: charset"0123456789"until[r: on
parse s[to remove[copy n any d"["copy t any b"]"](insert/dup
c: copy""t do n r: off)insert c]r]s]

Try it online!
More readable:
f: func [ s ] [
    b: charset [ not "[]" ]
    d: charset "0123456789"
    until [
        r: on
        parse s [
            to remove [ copy n some d "[" copy t any b "]" ]
                ( insert/dup c: copy "" t do n
                r: off )
            insert c ]
        r
    ]
    s
]

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Number of FIFO cache misses
This challenge is really simple (and a precursor to a more difficult one!).
Given an array of resource accesses (simply denoted by nonnegative integers) and a parameter n, return the number of cache misses it would have assuming our cache has capacity n and uses a first-in-first-out (FIFO) ejection scheme when it is full.
Example:
4, [0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 0, 1, 2, 3]
0 = not in cache (miss), insert, cache is now [0]
1 = not in cache (miss), insert, cache is now [0, 1]
2 = not in cache (miss), insert, cache is now [0, 1, 2]
3 = not in cache (miss), insert, cache is now [0, 1, 2, 3]
0 = in cache (hit), cache unchanged
1 = in cache (hit), cache unchanged
2 = in cache (hit), cache unchanged
3 = in cache (hit), cache unchanged
4 = not in cache (miss), insert and eject oldest, cache is now [1, 2, 3, 4]
0 = not in cache (miss), insert and eject oldest, cache is now [2, 3, 4, 0]
0 = in cache (hit), cache unchanged
1 = not in cache (miss), insert and eject oldest, cache is now [3, 4, 0, 1]
2 = not in cache (miss), insert and eject oldest, cache is now [4, 0, 1, 2]
3 = not in cache (miss), insert and eject oldest, cache is now [0, 1, 2, 3]

So in this example there were 9 misses. Maybe a code example helps explain it better. In Python:
def num_misses(n, arr):
    misses = 0
    cache = []
    for access in arr:
        if access not in cache:
            misses += 1
            cache.append(access)
            if len(cache) > n:
                cache.pop(0)
    return misses

Some further testcases (which contains a hint towards the next challenge - notice anything curious?):
0, [] -> 0
0, [1, 2, 3, 4, 1, 2, 3, 4] -> 8
2, [0, 0, 0, 0, 0, 0, 0] -> 1
3, [3, 2, 1, 0, 3, 2, 4, 3, 2, 1, 0, 4] -> 9
4, [3, 2, 1, 0, 3, 2, 4, 3, 2, 1, 0, 4] -> 10

Shortest code in bytes wins.

I was looking at the last statement notice anything curious? for a while now... and just noticed, increasing the cache capacity doesn't necessarily decrease the number of misses?!

@JungHwanMin Correct! In fact, how much worse it can get is unbounded.

Can we output the number in unary?

Known as Bélády's anomaly and FIFO is the classic example. The anomaly is unbounded.

@dylnan No, sorry.

Suggested test case: 0, [1, 1, 2, 3, 4, 1, 2, 3, 4] -> 9

JavaScript (ES6), 55 bytes
Method #1: the cache overwrites the input
Takes input in currying syntax (cache_size)(list).
n=>a=>a.map(x=>a[a.indexOf(x,k>n&&k-n)<k||k++]=x,k=0)|k

Try it online!
How?
We overwrite the input array a[ ] with the cache, using a separate pointer k initialized to 0.
We use a.indexOf(x, k > n && k - n) < k to test whether x is in the cache.
The cache can't grow faster than the original array is walked through, so each value is guaranteed to be found, either within or beyond the cache window (i.e. indexOf() will never return -1).
A value is in the cache if it is found at an index between max(0, k - n) and k - 1 (both bounds included), in which case we do a[true] = x. This only affects a property of the underlying object behind a[ ] but does not alter the array a[ ]. Otherwise, we do a[k++] = x.
Example
Below are the different steps for the input [1, 1, 2, 3, 3, 2, 1, 4] with a cache size of 2:

bold borders: map() pointer
brackets: cache pointer k
orange: current cache window
yellow: expired cache values

JavaScript (ES6), 57 bytes
Method #2: the cache is appended at the end of the input
Takes input in currying syntax (cache_size)(list).
n=>a=>a.map(x=>n*~a.indexOf(~x,-n)||a.push(~x)&k++,k=0)|k

Try it online!
How?
Because the input array a[ ] is guaranteed to contain non-negative integers, we can safely append the cache at the end of a[ ] by using the one-complement ~x of each value x.
We use n * ~a.indexOf(~x, -n) to test whether ~x is found among the last n values. Whenever this test fails, we append ~x to a[ ] and increment the number of misses k.
Example
Below are the different steps for the same example as above, using this method. Because cache values are simply appended at the end of the array, there is no explicit cache pointer.

Haskell, 50 bytes
f n=length.foldl(\r x->[x|all(/=x)$take n r]++r)[]

Try it online!
Based on Lynn's method of storing the whole cache history and taking its length. Unary output would be a bit shorter:
Haskell, 47 bytes
n?l=1<$foldl(\r x->[x|all(/=x)$take n r]++r)[]l

Try it online!

Python 2, 58 bytes
lambda n,a:len(reduce(lambda c,i:[i][i in c[:n]:]+c,a,[]))

Try it online!
Thanks to ovs for 3 bytes, and xnor for 3 more.

You should be able to save bytes by putting a set after c+=, since for some reason it converts to a list for you.

(ah, yes, c+={i}-set(c[-n:]) works, for positive n. But nimi pointed out that c[-n:] is wrong for n == 0, so I can’t use +=, and hence that trick – too bad.)

@Lynn Ah, I see. reduce still saves bytes: lambda n,a:len(reduce(lambda c,i:[i][i in c[:n]:]+c,a,[])).

R, 69 64 62 bytes
function(n,A,K={}){for(i in A)K=c(i[!i%in%K[0:n]],K);sum(K|1)}

Try it online!
Thanks to JayCe for suggesting some improvements, and DigEmAll for another couple!

I guess the + in front of Fis for f(0,{}) to return 0?

@JayCe yep, a classic golf in tandem with F as a pre-initialized return value.

a small improvemement. Also if unary output is accepted you can probably save some bytes.

@JayCe found some more bytes!

I tried to Reduce but it's 61 bytes before taking the length function(n,A)Reduce(function(K,i)c(if(!i%in%K[0:n])i,K),A,{})

Didn't know {} was a synonym for NULL — will have to remember that! Mind you, you could have initialised K as NA. It's a shame you can't initialise it as q but functions can't be subsetted; you'd have needed to use c(q) instead (which would also break the sum(K|1) trick).

@JDL yeah, a shame about the q but still a nice idea! Using NA is less good than using {} since I actually care about the length here (and I'm not actually popping elements from the cache).

Fair point, I'd missed that detail.

Saved 2 bytes : Try it online!

@digEmAll that's almost right, but it'll fail for n=0,A=c(1,1) which should have 2 cache misses; luckily using 0:n as the index saves it at a cost of 0 bytes!

@Giuseppe: yup! forgot the n=0 case ;)

05AB1E, 17 16 bytes
)svDyå_i¼y¸ìI£]¾

Try it online!
Explanation
)                   # wrap the stack in a list
 sv                 # for each item y in input list
   D                # duplicate current list
    yå_i            # if y is not contained in the current list
        ¼           # increment counter
         y¸ì        # prepend y to the current list
            I£      # keep the first input elements
              ]¾    # end loop and push counter

Haskell, 61 58 bytes
n!a|let(a:b)#c|elem a c=b#c|1<2=1+b#take n(a:c);_#_=0=a#[]

Try it online!
n!a|      =a#[]     -- take input 'n' and a list 'a'
                    -- and call # with the initial list and an empty cache
 let                -- bind function '#':
  (a:b)#c           -- if there's at least one element 'a' left in the list
     |elem a c=b#c  --  and it's in the cache, go on with the same cache
                    --  and the remainder of the list
     |1<2=          -- else (i.e. cache miss)
          1+        --  add one to the recursive call of
       b#           --  the remainder of the list and
       take n(a:c)  --  the first n elements of 'a' prepended to the cach
 _#_=0              -- if there's no element in the list, return 0

Edit:  -3 bytes thanks to @Lynn.

Kotlin, 82 69 bytes
{a,n->a.fold(List(0){0}){c,v->if(v!in c.takeLast(n))c+v else c}.size}

Takes input as an IntArray, not the typical List<Int> (which shouldn't be a problem.) This uses the approach of "build a cache history and count its length".
Try it online!
Explanation
{ a, n ->                         // lambda where a is accesses and n is cache size
    a.fold(List(0){0}) { c, v ->  // fold on empty list
        if(v !in c.takeLast(n))   // if resource is not in last n cache inserts
            c + v                 // insert to cache list
        else
            c                     // return cache as is
    }.size                        // length of cache list is number of inserts
}

Creating an empty list
Kotlin does not have collection literals, but it does have some functions to create new collections.
The proper way to create an empty List<Int> is simply:
List<Int>()

but it is shorter if we abuse the size and initializer args to do this:
List(0){0}
List(0)       // List of size 0
       { 0 }  // with generator returning 0

Because the generator lambda returns 0, Kotlin infers the type of this list as List<Int>, and the size of 0 means this list is empty.

Pyth,  16 15 18 14  13 bytes
Saved 1 byte thanks to isaacg.
luaW-H>QGGHEY

Test suite!
This challenge is very well suited to Pyth's u structure.
How it works
luaW-H>QGGHEY     Full program. Q = the cache length, E = the list.
 u         E      Reduce E with G = current value and H = corresponding element
            Y     With starting value Y, which is preinitialised to [] (empty list).
   W              Conditional application. If...
    -H            ... Filtering H on absence of...
      >QG         ... The last Q elements of G...
                  ... Yields a truthy value (that is, H is not in G[-Q:]), then...
  a      GH       ... Append H to G.
                  ... Otherwise, return G unchanged (do not append H at all).
l                  Get the length of the result.

aW-H>QGGH beats ?}H<GQG+HG by 1

@isaacg Thanks! I initially had +G*]H!}H>QG, but when I golfed it I really haven't thought of W... Nice!

What exactly does u do?

@dylnan u is a reduce with intial value operator. Just like Jelly's ƒ

Java 8, 96 bytes
A curried lambda taking a cache size (int) and access list (mutable java.util.List<Integer>) and returning an int.
s->a->{int w=0,m=0,i;for(int r:a)m+=(i=a.indexOf(r))<w&i<s?0:s<1?1:1+0*a.set(w++%s,r);return m;}

Try It Online
Ungolfed
This uses the first (up to) s slots in the input list for the cache.
s ->
    a -> {
        int
            w = 0,
            m = 0,
            i
        ;
        for (int r : a)
            m +=
                (i = a.indexOf(r)) < w & i < s ?
                    0
                    s < 1 ?
                        1
                        : 1 + 0*a.set(w++ % s, r)
            ;
        return m;
    }

Acknowledgments

bugfix thanks to nimi

Perl 6, 48 bytes
{my@c;$_∈@c.tail($^n)||push @c,$_ for @^o;+@c}

Test it
{  # bare block with placeholder params $n,@o

  my @c; # cache

      $_ ∈ @c.tail($^n) # is the current value in the last bit of the cache
    ||
      push @c, $_       # if not add it to the cache

  for                   # do this for all of

    @^o;                # the input array

  +@c                   # numify the cache (the count)
}

Wolfram Language (Mathematica), 60 59 bytes
Tr[k={};n=#;k~Take~UpTo@n~FreeQ~#&&k~PrependTo~#&/@#2;1^k]&

Try it online!
Using pattern-matching, 60 bytes
Length[#2//.{p___,a_,q___,a_,r___}/;Tr[1^{q}]<#:>{p,a,q,r}]&

I really like this one better, but it's 1 byte longer...
Try it online!

Japt, 16 bytes
;£A¯V øX ªAiXÃAl

Try it

Explanation
                     :Implicit input of array U and integer V
 £                   :Map over each X in U
; A                  :  Initially the empty array
   ¯V                :  Slice to the Vth element
      øX             :  Contains X?
         ª           :  Logical OR
          AiX        :  Prepend X to A
             Ã       :End map
              Al     :Length of A

Ruby, 43 40 bytes
->s,a,*r{a.count{|*x|r!=r=(r|x).pop(s)}}

Try it online!
Thanks histocrat for shaving 3 bytes.

Nice answer! You can save a couple bytes by initializing r as part of the argument list: ->s,a,*r which also provides the bonus feature that the caller can prime the cache by passing extra arguments :)

Oh, and similarly to cast x into an array: .count{|*x|

K4, 42 40 bytes
Solution:
{*1+/1_{r,,(y;x#z,y)r:~z in y:*|y}[x]\y}

Examples:
q)k)f:{*1+/1_{r,,(y;x#z,y)r:~z in y:*|y}[x]\y}
q)f[0;1 2 3 4 1 2 3 4]
8
q)f[2;0 0 0 0 0 0 0]
1
q)f[3;3 2 1 0 3 2 4 3 2 1 0 4]
9
q)f[4;3 2 1 0 3 2 4 3 2 1 0 4]
10

Explanation:
For the inner function, y is the cache, z is the request and x is the cache size.
{*1+/1_{r,,(y;x#z,y)r:~z in y:*|y}[x]\y} / the solution
{                                      } / lambda taking 2 args
       {                         }       / lambda taking 3 args
                                  [x]\y  / iterate over lambda with each y
                              *|y        / last (reverse, first) y
                            y:           / assign to y
                       z in              / is z in y?
                      ~                  / not
                    r:                   / assign result to r (true=1,false=0)
           ( ;     )                     / 2-element list
                z,y                      / join request to cache
              x#                         / take x from cache (limit size)
            y                            / (else) return cache unchanged
          ,                              / enlist this result
        r,                               / join with r
     1_                                  / drop the first result
  1+/                                    / sum up (starting from 1)
 *                                       / take the first result

Notes:
There is probably a nicer way to do all of this, but this is the first way that came to mind.
The function can be ran like this for 36 bytes:
q)k)*1+/1_{r,,(y;x#z,y)r:~z in y:*|y}[4]\3 2 1 0 3 2 4 3 2 1 0 4
10

Alternative - using a global variable to store state (not very K-like), 42 bytes:
{m::0;(){$[z in y;y;[m+:1;x#z,y]]}[x]\y;m}

C (gcc), 112 110 108 bytes
f(x,y,z)int*y;{int*i=y+z,b[x],m=0;for(wmemset(b,z=-1,x);i-y;y++)wmemchr(b,*y,x)?:++m*x?b[z=++z%x]=*y:0;x=m;}

Try it online!
Slightly less golfed
f(x,y,z)int*y;{
 int*i=y+z,b[x],m=0;
 for(wmemset(b,z=-1,x);i-y;y++)
  wmemchr(b,*y,x)?:
   ++m*
   x?
    b[z=++z%x]=*y
   :
    0;
 x=m;
}

Brain-Flak, 172 bytes
(([{}]<>)<{({}(()))}{}>)<>([]){{}<>((({})<{({}()<<>(({})<({}<>({}<>))>)<>>)}{}>)<<>(({})([{}]<>{<>(){[()](<{}>)}{}<><({}()<<>({}<>)>)>}{})){(<{}{}>)}{}>)<>([])}{}<>({}[]<>)

Try it online!
# Initialize cache with n -1s (represented as 1s)
(([{}]<>)<{({}(()))}{}>)<>

# For each number in input
([]){{}

    # Keep n on third stack
    <>((({})<

        # For last n cache entries, compute difference between entry and new value
        {({}()<<>(({})<({}<>({}<>))>)<>>)}{}

    >)<

        # Get negation of current entry and...
        <>(({})([{}]<>

            {

                # Count cache hits (total will be 1 or 0)
                <>(){[()](<{}>)}{}

                # while moving entries back to right stack
                <><({}()<<>({}<>)>)>

            }{}

        ))

        # If cache hit, don't add to cache
        {(<{}{}>)}{}

    >)

<>([])}{}

# Compute cache history length minus cache size (to account for the initial -1s)
<>({}[]<>)

Jelly, 18 bytes
Ṗɼṛ;ɼe®Uḣ⁴¤C$¡€ṛLɼ

Try it online!
Takes the list as the first argument and cache capacity as second argument.
Ṗɼṛ;ɼe®Uḣ⁴¤C$¡€ṛLɼ
 ɼ                 Apply to the register:
Ṗ                  Pop. This initializes the register to the empty list.
  ṛ                Right argument. Yields the list of addresses.
              €    For each element in the list
             ¡     If{
     e                 the element is in
          ¤            nilad{
      ®                      the register
       U                     reversed
        ḣ                    first...
         ⁴                   (cache depth) number of elements
                             }
           C           Complement. 1 <-> 0. Easier to type this than "not".
            $          Combines everything up to `e` into a monad
                      }
                    Then{
    ɼ                    Apply to the register and store the result
   ;                     Append the element
                        }
                ṛ   Right argument:
                  ɼ Apply to the register:
                 L  Length

C (gcc), 156 bytes
s,n,m,i,j;f(x,_)int*_;{int c[x];n=m=0;for(i=0;i<x;++i)c[i]=-1;for(i=s=0;_[i]>=0;++i,s=0){for(j=0;j<x;++j)s|=(c[j]==_[i]);if(!s){c[n++]=_[i];m++;n%=x;}}x=m;}

Try it online!
Description:
s,n,m,i,j;                       // Variable declaration
f(x,_)int*_;{                    // F takes X (the cache size) and _ (-1-terminated data)
    int c[x];                    // declare the cache
    n=m=0;                       // next queue insert pos = 0, misses = 0
    for(i=0;i<x;++i)c[i]=-1;     // initialize the cache to -1 (invalid data)
    for(i=s=0;_[i]>=0;++i,s=0){  // for each datum in _ (resetting s to 0 each time)
        for(j=0;j<x;++j)         // for each datum in cache
            s|=(c[j]==_[i]);     // set s if item found
        if(!s){                  // if no item found
            c[n++]=_[i];         // add it to the cache at position n
            m++;                 // add a mis
            n%=x;                // move to next n position (with n++)
        }} x=m;}                 // 'return' m by assigning to first argument

Suggest wmemset(c,-1,x) instead of n=m=0;for(i=0;i<x;++i)c[i]=-1, n=m=i=s=0 instead of i=s=0, for(j=x;j--;) instead of for(j=0;j<x;++j), and s||(c[n++]=_[i],m++,n%=x); instead of if(!s){c[n++]=_[i];m++;n%=x;}

JavaScript (Node.js), 44 bytes
n=>a=>a.map(y=t=>y[t]+n>p||(y[t]=++p),p=0)|p

Try it online!

Jelly, 17 bytes
Ṗœ|Ṛḣ⁴$Ṛʋ\-;⁸e"ċ0

Try it online!
Full program.
Argument 1: stack (Python 3 list of integers)
Argument 2: n (Python 3 integer)

Rust, 129 bytes
|l:&[_],s|if s>0{let(mut c,mut m)=(vec![-1;s],0);for n in l.iter(){if!c.contains(n){c.remove(0);c.push(*n);m+=1;}}m}else{l.len()}

Try it online!
Ungolfed
|l: &[isize], s: usize| {
    if s > 0 {
        let mut c = vec![-1; s];
        let mut m = 0;
        for n in l.iter() {
            if !c.contains(n) {
                c.remove(0);
                c.push(*n);
                m += 1;
            }
        }
        m
    } else {
        l.len()
    }
}

Stax, 15 bytes
Ç═╛¢s▲▬╓í±°☻÷hi

Run and debug it

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
ASCII art uncompression from a base-n number
This is inspired by an 05AB1E answer by Magic Octupus Urn.
Given two arguments, a positive integer and a string/list of characters:

Translate the number to base-n, where n is the length of the string.
For each character, replace every appearance of the index of that character in the base-n number with that character.
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.

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 are forbidden
Feel free to answer even if your language can't handle the larger test cases.

As this is code-golf, the shortest code for each language wins. (I know all you golfing languages have one byte built-ins ready to go ;)

Sandbox (deleted)

D'awwh, I feel honored. 05AB1E [tag:ascii-art] was my favorite awhile back.

you can create a new challenge: find the permutation of characters in the array to minimize the number :)

05AB1E, 7 6 bytes
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 or verify all test cases.
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)

gв¹sèJ to save a byte.

@Emigna Thanks. Can't believe I hadn't thought about ¹sè myself now.. (I knew changing the ? to a J would give the same output in this case.)

Python 3, 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''

Welcome to PPCG! Feel free to include a TIO link to help showcase your solution.

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

a->n->n.toString(a.length).chars().map(c->a[c-48]) (50 bytes) since "IO is flexible"

String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";} (69 bytes) recursive one, for the fun.

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

Haskell, 40 39 bytes
0!_=[]
n!l=cycle l!!n:div n(length l)!l

Try it online!
As Haskell's Int type is limited to 9223372036854775807, this fails for larger numbers.
-1 byte thanks to 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!

Nice idea to use cycle instead of mod! div n(length l) saves a byte.

MATL, 2 bytes
YA

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

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!

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!

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; see it for justification and explanation of the algorithm.)  glibc's internal _itoa does this, 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, 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)
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.)

Jelly, 4 bytes
ṙ1ṃ@

Try it online!
ṃ is literally a built-in for this. The other three bytes account for Jelly's one-based indexing.

Out of curiosity, why does Jelly even have the builtin ṃ "Base decompression; convert x to base length(y) then index into y."? Is it for the very exceptional cases where the base you ant to convert to and length of a string/integer/list are equal? When I search for it, I can only find three answers using it: 1; 2; 3. Kinda a weird builtin in every day code-golf challenges imo. :S

@KevinCruijssen it's very useful when you want, for example, to convert N to hexadecimal using hex letters instead of a list of numbers.

@KevinCruijssen It's a compression method for strings. In the first example the string desired is “sspspdspdspfdspfdsp”, but with “çƥ÷£ḟ’ṃ“spdf”¤ you save six bytes. It's especially useful with Jelly's base 250 numbers

Python 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!
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!

Charcoal, 3 1 bytes
⍘θη
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! 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

Actually it's supposed to already work but evidently I've messed up yet again >_>

Also, it would actually be 1 byte :P (it's currently broken though, so i'm not using number and string array as arguments) (also, i wonder how (un)useful implicit input is)

@ASCII-only Don't you mean "1 bytes" (see your -vl output ;-) Also, implicit input would seem to be almost useless in Charcoal, except for challenges like this.

:D

@ASCII-only Still "1 bytes" though :P

@ASCII-only Plural "bytes" instead of singular "byte" is what Neil means. ;) As for your 1-byte answer, why the crossed-out θη? Looks a bit confusing tbh. Why not just remove it completely and leave ⍘?

(also yeah crap i meant to fix that as well but forgot >_> i guess i'll fix it later. it works fine in the post generator but not here)

Doesn't this answer not count since the built-in was added after the question?

@Nit I double-checked and the built-in had been added before the question was asked, but I hadn't realised because it had a bug.

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;

3 bytes to shave off: You don't need the space after #include, you can change ;; to just ;, and '0' can just be 48

Also, the while loop could be a for loop: for(;n;n/=b.size())t=std::to_string(n%b.size())+t;

@ceilingcat, I forgot that b.size() doesn't change in that loop.

@ceilingcat That would increase the bytecount by 1, instead of lowering it

D, 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!
This is a port of HatsuPointerKun's C++ answer
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.

I golfed your TIO bits :P

APL (Dyalog Unicode), 14 13 12 bytes
⊢⌷⍨∘⊂⊥⍣¯1⍨∘≢

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: Index Origin = 0 and ⎕FR←1287: Float Representation = 128 bits. (I'd forgotten that this doesn't apply.)
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.

Pyth, 9 8 7 bytes
s@LQjEl

Saved a byte thanks to hakr14 and another thanks to Mr. Xcoder.
Try it here
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.

Save a byte by replacing m@Qd with @LQ

Save a byte by replacing vz with E.

Twig, 66 bytes
Created a macro that must be imported 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

Attache, 17 bytes
{_[_2&ToBase!#_]}

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

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.  See this answer 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!.  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.

Bash + core utilities, 49 bytes
dc -e`echo -en $2|wc -c`o$1p|tr -dc 0-9|tr 0-9 $2

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.

I was going to suggest dc -e${#2}o$1p|tr 0-9 "$2" to take the input literally instead of in \escaped form so it can handle spaces, but tr doesn't have an option to not treat - as a range character, for example.  If the input has - not at one end of the string, it breaks.  Perhaps you can use sed "y/0123456789/$2/".  No I guess not, GNU sed requires both args to y to be the same length, and it seems to choke on newline.

Vyxal, 1 byte
τ

Try it Online!
05AB1E, 3 bytes
ÅвJ

Try it online!

Stax, 6 5 bytes
n%|E@

Run and debug it
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

Canvas, 7 bytes
Ｌ┬｛╵⁸＠ｐ

Try it here!
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.

SOGL V0.12, 10 bytes
l;A─{IaWp}

Try it Here!
Pretty long, considering the idea is pretty much implemented in the language: here, entering
¶    __   __    ¶   |  |_|  |   ¶___|       |___¶-   -   -   -  ¶ - - - - - - - ¶- - - - - - - -¶_______________¶

gives out a compressed string using this method.

Ruby, 31 bytes
->n,b{n.to_s(b.size).tr"0-9",b}

Try it online!

Stax, 2 bytes
:B

Run and debug it
: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.

Huh, I never noticed this command ...

There are a lot.  I once added an instruction to stax that already existed, and I had just forgotten about. (array is non-descending?)

J, 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!

Powershell, 88 87 bytes
$n,$a=$args;$d=0;for(;$n-ne0){$n=[bigint]::DivRem($n,$a.count,[ref]$d);$s=$a[$d]+$s};$s

implicit using a .NET class BigInteger.
Test script:
$f = {
    $n,$a=$args;$d=0;for(;$n-ne0){$n=[bigint]::DivRem($n,$a.count,[ref]$d);$s=$a[$d]+$s};$s
}

@(
    @{
        n        = [bigint]::Parse("2740")
        ascii    = @("|", "_")
        expected = "_|_|_|__|_||"
    }
    @{
        n        = [bigint]::Parse("698911")
        ascii    = @("c", "h", "a", "o")
        expected = "aaaaaachoo"
    }
    @{
        n        = [bigint]::Parse("1928149325670647244912100789213626616560861130859431492905908574660758972167966")
        ascii    = @(" ", "`r`n", "|", "_", "-")
        expected = @"

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

"@
    }
    @{
        n        = [bigint]::Parse("3446503265645381015412")
        ascii    = @(":", "`r`n", ".", "_", "=", " ", ")", "(", ",")
        expected = @"
_===_
(.,.)
( : )
( : )
"@
    }
) | % {
    $r = &$f $_.n $_.ascii
    $r -eq $_.expected
    $r
}

output:
True
_|_|_|__|_||
True
aaaaaachoo
True

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

True
_===_
(.,.)
( : )
( : )

Explanation
$n,$a=$args                # let $n is first argument (expected [bigint])
                           # let $a is second argument (expected char array)
$d=0                       # define variable $d to use as reference value
for(;$n-ne0){              # while bigint $n not equals 0
    $n=[bigint]::DivRem($n,$a.count,[ref]$d);
                           # .NET function DivRem returns the quotient of the division
                           # and place remainder to $d
                           # https://msdn.microsoft.com/en-us/library/system.numerics.biginteger.divrem
    $s=$a[$d]+$s           # add a char to the string
}
$s                         # return string

Wolfram Language (Mathematica), 49 bytes
Outer[Part,{#},#2~IntegerDigits~Tr[1^#]+1,1]<>""&

Try it online!

C (gcc), 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!
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

If you start at the end of a buffer and work backwards, you can avoid sprintf.  My C version is 53 bytes, with the output buffer provided by the caller.  You could do one strcpy at the end if you want to copy the bytes to the start of a buffer.

That is brilliant. I don't care if its an awkward I/O format. Awkward I/O is C claim to fame! Well done, I'd recommend putting that into the C tips post.

Posted an answer on Tips for golfing in C explaining and justifying the technique.

CJam, 11 bytes
liq_,@\b\f=

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

Since "IO is Flexible", I think you can get rid of the liq at the beginning, and that saves you 3 bytes!

JavaScript, 39 bytes
Port of Rod's Python solution.
s=>g=n=>n?g(n/(l=s.length)|0)+s[n%l]:""

Try it online

Only works for n up to 64-bit, right?  (Python has arbitrary-precision integers built in, but JS numbers are naturally double-precision floats that can be converted to integer). Doesn't seem to work for the larger test cases in the question, like 1928149325670647244912100789213626616560861130859431492905908574660758972167966.  Oh, but the question allows answers like that.  Still, should be noted.

SimpleTemplate, 86 bytes
Wow, this was a huge challenge!
This was made hard due to the lack of direct access to specific indexes when the index is a variable.
A bug also made it longer, requiring to store the values inside a variable.
{@setA argv.1}{@eachargv.0}{@setC C,"{@echoA.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}

Values expected:
The first argument (argv.0) can be:

An integer
A string with numbers
An array of integers

The second argument (argv.1) can be:

A string
An array

How this works?
It works this way:

Cycles through the number/string passed as the first argument
Sets the variable C to be an array containing:

The previous value C
The string "{@echoA."
The value of the loop
The string "}"

Joins everything together (using PHP's join function)
This results in, for example, C containing "{@echoA.0}{@echoA.1}..."
Evaluates the result of C

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

You can try this code on: https://ideone.com/NEKl2q

Optimal result
If there weren't bugs, this would be the best result, accounting for the limitations (77 bytes):
{@eachargv.0}{@setC C,"{@echoargv.1.",_,"}"}{@calljoin intoC"",C}{@/}{@evalC}

Perl 6, 32 bytes
{$^a.base($^b).comb>>.&{$b[$_]}}

Try it online!
Anonymous code block that take an integer and a list of characters and returns a list of characters.
Explanation:
{                              }  #Anonymous code block
 $^a.base($^b)                    #Convert number to base (len(list))
              .comb               #Convert number to list of characters
                   >>             #Map each character to
                     .&{$b[$_]}   #To the index of that character in the list


text:
Pair and sort from two integer lists
You are given two arbitrary integer lists, e.g. [-10, 99, -6, 43], [100, 32, 44]. You are to pick one integer from each list and sum them up, then sort the best pairs ordered by the absolute distance to 100 in ascending order. Paired up integers from each list shall not be repeated in the output.
For instance, we have

Pair
Calculation
Absolute distance from 100

(-10, 100)
100 - (-10 + 100)
= 10

(-10, 32)
100 - (-10 + 32 )
= 78

(-10, 44)
100 - (-10 + 44 )
= 66

(99, 100)
100 - (99 + 100 )
= 99

(99, 32 )
100 - (99 + 32  )
= 31

(99, 44 )
100 - (99 + 44  )
= 43

(-6, 100)
100 - (-6 + 100 )
= 6

(-6, 32 )
100 - (-6 + 32  )
= 74

(-6, 44 )
100 - (-6 + 44  )
= 62

(43, 100)
100 - (43 + 100 )
= 43

(43, 32 )
100 - (43 + 32  )
= 25

(43, 44 )
100 - (43 + 44  )
= 13

After pairing with the first item -10, it is tempted to pick the pair (-10, 100) as the best pair as it has the least distance to 100. But further checking down the list, (-6, 100) in fact has a lesser distance to 100, hence it should be the best pair picked. After picking the pair, they are removed from their lists, leaving us

Pair
Calculation
Absolute distance from 100

(-10, 32)
100 - (-10 + 32)
= 78

(-10, 44)
100 - (-10 + 44)
= 66

(99, 32 )
100 - (99 + 32 )
= 31

(99, 44 )
100 - (99 + 44 )
= 43

(43, 32 )
100 - (43 + 32 )
= 25

(43, 44 )
100 - (43 + 44 )
= 13

Then next pair to pick will be (43, 44). Notice that the distance to 100 is 13 for this pair, which is higher than the pair (-10, 100), but only because 100 has been paired with -6 and hence the pair (-10, 100) is gone. Moving on, we have these remaining

Pair
Calculation
Absolute distance from 100

(-10, 32) :
100 - (-10 + 32)
= 78

(99, 32 ) :
100 - (99 + 32 )
= 31

And finally (99, 32) is picked. Hence the output (-6, 100), (43, 44), (99, 32). Ignore the rest that have nothing to pair up.
Note: when there is a tie, just pick any pair, without worrying the consequence to the remaining candidates.
The challenge here is to complete the task with the least number of comparisons operating on the inputs. i.e. if all comparison result has to come from a function comp(a, b), then the least number of call to this function wins. Looping control etc. are not included. Three way comparison is essentially 2 operations. General purpose code only and no special purpose optimisation is required. Favour code that can verify the number of comparison calls, however, when using build in functions, please explain their complexity for us to examine.

Welcome to PPCG! / Can you clarify if 3-way comparison is counted as 1 or 2 steps?

I assume that the only operation that you can do on the numbers are comparing them (instead of, say, use them to index into arrays, or hash them? Is addition or multiplication allowed?)

In summary: This is a nice challenge idea, but in the current form it's too unclear. You can sandbox the challenge before posting to main.

@user202729 haha thanks. First time poster, tried my best. Points noted and updated in the question. Cheers. Enjoy!

The least number of comparisons over what space of possible inputs? That is, I could write a function that gives correct answers for all inputs, does a provably minimum number of comparisons on this example input, but does way more comparisons than necessary on other inputs.

How is comp defined regarding builtin functions? Let's say I calculate the absolute differences as you did, and then take the minimum of the list (with a builtin, not manually). How many comp does minimum count as? (1? or the size of the list since the builtin compares each under the hood?)

Python O(mn log mn)
The best pairs can be found computing the distances of all the possible pairs, and iteratively choosing the best pair among those remaining after filtering out the already chosen items.
A simple implementation is shown in the following code:
def find_nearest_pairs_to_100(l, m):
    pair_list = sorted([((i, j), abs(100 - i - j)) for i in l for j in m], key=lambda x: x[1])
    chosen_pairs = []
    while pair_list:
        best_pair = pair_list[0][0]
        chosen_pairs.append(best_pair)
        pair_list = [(p, s) for (p, s) in pair_list if p[0] != best_pair[0] and p[1] != best_pair[1]]
    return chosen_pairs

The find_nearest_pairs_to_100 function takes the two lists in input and returns an ordered list with the chosen pairs.
The sorted function in Python is based on Timsort algorithm, that requires O(n log n) comparisons in the worst case (where n is the length of the list).
In this case the length of the list is the cardinality of the Cartesian product of the two input lists, i.e. mn (with n > m). Therefore, the total cost of this implementation is of O(mn log mn) comparisons, excluding the other comparison operations needed for filtering.
Including comparisons for filtering, at each iteration, in the worst case, all the items of the list are checked against the elements of the chosen pair; the length the pair_list is mn at the first iteration, (n-1)(m-1) at the second, (n-2)(m-2) at the third, and n-m+1 at the last step. So the total number of comparisons for filtering is O(n^3).
If you like golfing, it is a golfed version (163 bytes) of the previous one (a little bit different):
f=lambda l,m:l and m and[[k]+f(l.remove(k[0])or l,m.remove(k[1])or m)for k in sorted([[[[i,j]],abs(100-i-j)]for i in l for j in m],key=lambda x:x[1])[0][0]][0]or[]

Thank you! Really nice submission and good explanation, I have learnt a lot here. Just that for the selection part, you may want to update that a little bit as the current code will exclude potential pairs with same integer value of picked pairs but from a different input list. i.e. when the two input lists both contain some equal integers.

@user1589188 You're right, I've updated the code.