Armazenamento em cache ideal


14

Você receberá uma sequência de solicitações de memória e um tamanho de cache. Você deve retornar o menor número possível de falhas de cache em qualquer estratégia de substituição de cache.

Uma estratégia ideal é o algoritmo de Belady , que você pode usar se quiser.


Um sistema de armazenamento em cache funciona da seguinte maneira: O cache começa vazio. Pedidos de memória são recebidos. Se o pedido solicitar alguns dados no cache, tudo estará bem. Caso contrário, ocorrerá uma falta de cache. Nesse ponto, você pode inserir os dados solicitados no cache para uso futuro. Se o cache estava cheio e você deseja inserir novos dados, você deve remover os dados que estavam anteriormente no cache. Você nunca pode inserir dados que não estavam apenas no cache.

Seu objetivo é encontrar o número mínimo possível de falhas de cache para uma determinada sequência de solicitação de memória e tamanho de cache.


Você receberá o tamanho do cache, um número inteiro positivo e a sequência de solicitação de memória, que é uma lista de tokens. Esses tokens podem ser qualquer tipo de tokens que você quiser, desde que sejam possíveis pelo menos 256 tokens diferentes (bytes são bons, bools não). Por exemplo, ints, strings, lists estão bem. Peça esclarecimentos, se necessário.


Casos de teste:

3
[5, 0, 1, 2, 0, 3, 1, 2, 5, 2]

6

Consulte a Wikipedia para obter uma política de substituição que atinja isso.

2
[0, 1, 2, 0, 1, 0, 1]

3

Simplesmente evite adicionar 2ao cache.

3
[0, 1, 2, 1, 4, 3, 1, 0, 2, 3, 4, 5, 0, 2, 3, 4]

9

Uma maneira de conseguir isso é através da não expulsão 0e 2, e expulsar 1o mais rapidamente possível após a sua última utilização.


Pontuação: Este é o código de golfe. Menos bytes ganha.


Podemos supor que a lista contenha pelo menos 2 tokens?
Arnauld

@Arnauld eu vou dizer não, mas se há apenas 1 solução, a resposta é, naturalmente, sempre 1.
isaacg

Respostas:


4

JavaScript (ES6), 128 bytes

Toma entrada como (size)(list).

s=>a=>a.map((x,i)=>c.includes(x)?0:c[e++,[x,...c].map(m=(x,j)=>(k=[...a,x].indexOf(x,i+1))<m||(p=j,m=k)),i<s?i:p-1]=x,e=c=[])&&e

Experimente online!

Comentado

Esta é uma implementação do algoritmo de Belady.

s => a =>                      // s = cache size; a[] = token list
  a.map((x, i) =>              // for each token x at position i in a[]:
    c.includes(x) ?            //   if x is currently stored in the cache:
      0                        //     do nothing
    :                          //   else:
      c[                       //     update the cache:
        e++,                   //       increment the number of errors (cache misses)
        [x, ...c]              //       we want to find which value among x and all current
                               //       cache values will be needed for the longest time in
                               //       the future (or not needed anymore at all)
        .map(m =               //       initialize m to a non-numeric value
                 (x, j) =>     //       for each x at position j in this array:
          ( k = [...a, x]      //         k = position of x in the array made of all values
            .indexOf(x, i + 1) //         of a[] followed by x, starting at i + 1
          ) < m                //         if it's greater than or equal to m, or m is
          || (p = j, m = k)    //         still non-numeric: set p to j and m to k
        ),                     //       end of inner map()
        i < s ?                //       if i is less than the cache size:
          i                    //         just fill the cache by using the next cache slot
        :                      //       else:
          p - 1                //         use the slot that was found above
                               //         special case: if p = 0, x was the best candidate
                               //         and we're going to store it at c[-1], which is
                               //         simply ignored (it will not trigger c.includes(x))
      ] = x,                   //     store x at this position
      e = c = []               //     start with e = [] (coerced to 0) and c = []
  ) && e                       // end of outer map; return e

4

Perl 5 , 193 bytes

sub g{
  my($i,$m,$s,@a,%c)=(-1,0,@_);
  for(@a){
    $i++;
    next if $c{$_}++ || ++$m && keys%c <= $s;
    my($x,$d);
    for $k (sort keys %c){  #find which to delete, the one furtherst away
      my $n=0;
      ++$n && /^$k$/ && last for @a[$i+1..$#a];
      ($x,$d)=($n,$k) if $n>$x
    }
    delete $c{$d}
  }
  $m
}

Experimente online!

print g(3,  5, 0, 1, 2, 0, 3, 1, 2, 5, 2),"\n";                     # 6
print g(2,  0, 1, 2, 0, 1, 0, 1),"\n";                              # 3
print g(3,  0, 1, 2, 1, 4, 3, 1, 0, 2, 3, 4, 5, 0, 2, 3, 4),"\n";   # 9

193 bytes sem recuo, novas linhas, espaços, comentários:

sub g{my($i,$m,$s,@a,%c)=(-1,0,@_);for(@a){$i++;next if$c{$_}++||++$m&&keys%c<=$s;my($x,$d);for$k(sort keys%c){my$n=0;++$n&&/^$k$/&&last for@a[$i+1..$#a];($x,$d)=($n,$k)if$n>$x}delete$c{$d}}$m}


1

Haskell , 82 bytes

f n|let(d:t)#c=1-sum[1|elem d c]+minimum[t#take n e|e<-scanr(:)(d:c)c];_#_=0=(#[])

Experimente online!

Explicação

Funciona com força bruta: todas as estratégias de cache são tentadas e o melhor resultado é retornado.

f n            Define a function f on argument n (cache size) and a list (implicit).
 |let(d:t)#c=  Define binary helper function #.
               Arguments are list with head d (current data) and tail t (remaining data), and list c (cache).
 1-            It returns 1 minus
 sum[1|        1 if
 elem d c]+    d is in the cache, plus
 minimum[      minimum of
 t#            recursive calls to # with list t
 take n e|     and cache being the first n values of e, where
 e<-           e is drawn from
 scanr(:)  c]  the prefixes of c
 (d:c)         with d and c tacked to the end.
 ;_#_=0        If the first list is empty, return 0.
 =(#[])        f then calls # with the list argument and empty cache.

0

Perl 6 , 146 bytes

->\a,\b {$_=set();$!=0;for b.kv ->\i,\v {$_{v}&&next;++$!;vb[i^..*]||next;$_∖=.keys.max({(grep $_,:k,b[i^..*])[0]//Inf})if $_>=a;$_∪=v};$!}

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.