Liczba braków pamięci podręcznej FIFO


35

To wyzwanie jest naprawdę proste (i jest prekursorem trudniejszego!).

Biorąc pod uwagę tablicę dostępu do zasobów (po prostu oznaczoną nieujemnymi liczbami całkowitymi) i parametr n, zwróć liczbę braków pamięci podręcznej, które miałoby przy założeniu, że nasza pamięć podręczna ma pojemność ni korzysta ze schematu wyrzucania FIFO, gdy jest pełna .

Przykład:

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]

Tak więc w tym przykładzie było 9 nieudanych prób. Może przykład kodu pomaga lepiej to wyjaśnić. W Pythonie:

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

Kilka dalszych przypadków testowych (które zawierają wskazówkę do następnego wyzwania - czy zauważyłeś coś ciekawego?):

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

Najkrótszy kod w bajtach wygrywa.


15
notice anything curious?Przez chwilę patrzyłem na ostatnie zdanie ... i właśnie zauważyłem, że zwiększenie pojemności pamięci podręcznej niekoniecznie zmniejsza liczbę braków ?!
JungHwan Min

@JungHwanMin Correct! W rzeczywistości to, o ile gorzej może być, jest nieograniczone.
orlp

Czy możemy podać liczbę pojedynczą?
dylnan

9
Klasyczny przykład znany jako anomalia Bélády'ego i FIFO. Anomalia jest nieograniczona .
virtualirfan

@dylnan Nie, przepraszam.
lub

Odpowiedzi:


11

JavaScript (ES6), 55 bajtów

Metoda nr 1: pamięć podręczna zastępuje dane wejściowe

Pobiera dane wejściowe w składni curry (cache_size)(list).

n=>a=>a.map(x=>a[a.indexOf(x,k>n&&k-n)<k||k++]=x,k=0)|k

Wypróbuj online!

W jaki sposób?

Nadpisujemy tablicę wejściową a [] pamięcią podręczną, używając osobnego wskaźnika k zainicjowanego na 0 .

Używamy a.indexOf(x, k > n && k - n) < kdo testowania, czy x jest w pamięci podręcznej.

Pamięć podręczna nie może rosnąć szybciej niż przeglądana jest oryginalna tablica, więc gwarantuje się, że każda wartość zostanie znaleziona w oknie pamięci podręcznej lub poza nim (tzn. indexOf()Nigdy nie zwróci -1 ).

Wartość znajduje się w pamięci podręcznej, jeśli zostanie znaleziona przy indeksie między max (0, k - n) i k - 1 (obie granice włącznie), w którym to przypadku wykonujemy [prawda] = x . Wpływa to tylko na właściwość obiektu leżącego za [], ale nie zmienia tablicy a [] . W przeciwnym razie robimy [k ++] = x .

Przykład

Poniżej znajdują się różne kroki dla danych wejściowych [1, 1, 2, 3, 3, 2, 1, 4]o wielkości pamięci podręcznej 2 :

  • pogrubione ramki: wskaźnik map ()
  • nawiasy: wskaźnik pamięci podręcznej k
  • pomarańczowy: bieżące okno pamięci podręcznej
  • żółty: wygasły wartości pamięci podręcznej

method #1


JavaScript (ES6), 57 bajtów

Metoda nr 2: pamięć podręczna jest dodawana na końcu danych wejściowych

Pobiera dane wejściowe w składni curry (cache_size)(list).

n=>a=>a.map(x=>n*~a.indexOf(~x,-n)||a.push(~x)&k++,k=0)|k

Wypróbuj online!

W jaki sposób?

Ponieważ tablica wejściowa a [] zawiera nieujemne liczby całkowite, możemy bezpiecznie dołączyć pamięć podręczną na końcu [] , stosując uzupełnienie ~ x każdej wartości x .

Używamy n * ~a.indexOf(~x, -n)do sprawdzenia, czy ~ x znajduje się wśród ostatnich n wartości. Ilekroć ten test się nie powiedzie, dołączamy ~ x do [] i zwiększamy liczbę braków k .

Przykład

Poniżej znajdują się różne kroki dla tego samego przykładu jak powyżej, przy użyciu tej metody. Ponieważ wartości pamięci podręcznej są po prostu dołączane na końcu tablicy, nie ma wyraźnego wskaźnika pamięci podręcznej.

method #2



9

Python 2 , 58 bajtów

lambda n,a:len(reduce(lambda c,i:[i][i in c[:n]:]+c,a,[]))

Wypróbuj online!

Dzięki ovs za 3 bajty i xnor za 3 kolejne.


Powinieneś być w stanie zapisać bajty, umieszczając po nim zestaw c+=, ponieważ z jakiegoś powodu konwertuje się on na listę dla ciebie.
xnor

(ach, tak, c+={i}-set(c[-n:])działa pozytywnien . Ale wskazali, że c[-n:]jest to niewłaściwe n == 0, więc nie mogę użyć +=, a więc ta sztuczka - szkoda.)
Lynn

1
@ Lynn Ah, rozumiem. reducenadal zapisuje bajtów: lambda n,a:len(reduce(lambda c,i:[i][i in c[:n]:]+c,a,[])).
xnor

7

R , 69 64 62 bajtów

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

Wypróbuj online!

Dzięki JayCe za zasugerowanie ulepszeń, a DigEmAll dla kolejnej pary!


Wydaje mi się, że z +przodu Fjest za f(0,{})0?
JayCe

@JayCe tak, klasyczny golf w tandemie ze Fwstępnie zainicjalizowaną wartością zwrotu.
Giuseppe,

1
mała poprawa . Również jeśli jednoargumentowe wyjście jest akceptowane, prawdopodobnie możesz zapisać niektóre bajty.
JayCe

@JayCe znalazł więcej bajtów!
Giuseppe

1
@JDL tak, szkoda tego, qale wciąż fajny pomysł! Używanie NAjest mniej dobre niż używanie, {}ponieważ tak naprawdę zależy mi na długości (i tak naprawdę nie wyskakuję z pamięci podręcznej elementów).
Giuseppe,

5

Haskell, 61 58 bajtów

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

Wypróbuj 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

Edycja: -3 bajty dzięki @Lynn.


5

05AB1E , 17 16 bajtów

)svDyå_i¼y¸ìI£]¾

Wypróbuj online!

Wyjaśnienie

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

@nimi: Dzięki! Naprawiono podczas zapisywania bajtu :)
Emigna

5

Kotlin , 82 69 bajtów

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

Staje jako wejście IntArray, nie typoweList<Int> (co nie powinno być problemem.) Ta wykorzystuje podejście „zbudować historię cache i liczyć jej długość”.

Wypróbuj online!

Wyjaśnienie

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

Tworzenie pustej listy

Kotlin nie ma literałów kolekcji, ale ma pewne funkcje do tworzenia nowych kolekcji.

Właściwym sposobem utworzenia pustego List<Int>jest po prostu:

List<Int>()

ale jest krótszy, jeśli nadużywamy rozmiaru i argumentów inicjalizatora, aby to zrobić:

List(0){0}
List(0)       // List of size 0
       { 0 }  // with generator returning 0

Ponieważ generator lambda zwraca 0, Kotlin określa typ tej listy jako List<Int>, a rozmiar 0 oznacza, że ​​ta lista jest pusta.


4

Perl 6 , 48 bajtów

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

Sprawdź to

{  # 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)
}

4

Java 8, 96 bajtów

Curried lambda biorąc rozmiar pamięci podręcznej ( int) i listę dostępu (zmienną java.util.List<Integer>) i zwracając 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;}

Wypróbuj online

Bez golfa

Wykorzystuje pierwsze (maksymalnie) smiejsca na liście danych wejściowych dla pamięci podręcznej.

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

Podziękowanie

  • naprawiające błędy dzięki Nimi

4

Pyth ,  16 15 18 14  13 bajtów

Oszczędność 1 bajtu dzięki isaacg .

luaW-H>QGGHEY

Zestaw testowy!

To wyzwanie bardzo dobrze pasuje do Pytha u struktury .

Jak to działa

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>QGGHuderzeń ?}H<GQG+HGo 1
isaacg

@isaacg Thanks! Początkowo miałem +G*]H!}H>QG, ale kiedy grałem w golfa, naprawdę nie myślałem o W... Fajnie!
Pan Xcoder,

Co dokładnie robi u?
dylnan

@dylnan ujest operatorem redukcji z wartością początkową . Podobnie jak Jelly'sƒ
Mr. Xcoder,


2

Japt, 16 bajtów

;£A¯V øX ªAiXÃAl

Spróbuj


Wyjaśnienie

                     :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

1

K4 , 42 40 bajtów

Rozwiązanie:

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

Przykłady:

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

Wyjaśnienie:

Dla funkcji wewnętrznej y jest pamięcią podręczną, z jest żądaniem, a x jest wielkością pamięci podręcznej.

{*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

Uwagi:

Jest prawdopodobnie lepszy sposób, aby to wszystko zrobić, ale to pierwszy sposób, jaki przyszedł mi do głowy.

Funkcję można uruchomić w następujący sposób dla 36 bajtów :

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

Alternatywnie - użycie zmiennej globalnej do przechowywania stanu (niezbyt podobny do K), 42 bajty :

{m::0;(){$[z in y;y;[m+:1;x#z,y]]}[x]\y;m}

1

Brain-Flak , 172 bajty

(([{}]<>)<{({}(()))}{}>)<>([]){{}<>((({})<{({}()<<>(({})<({}<>({}<>))>)<>>)}{}>)<<>(({})([{}]<>{<>(){[()](<{}>)}{}<><({}()<<>({}<>)>)>}{})){(<{}{}>)}{}>)<>([])}{}<>({}[]<>)

Wypróbuj 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)
<>({}[]<>)

1

Galaretka , 18 bajtów

Ṗɼṛ;ɼe®Uḣ⁴¤C$¡€ṛLɼ

Wypróbuj online!

Traktuje listę jako pierwszy argument, a pojemność pamięci podręcznej jako drugi 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

1

Rubinowy , 43 40 bajtów

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

Wypróbuj online!

Dzięki histocrat za golenie 3 bajtów.


1
Niezła odpowiedź! Możesz zapisać kilka bajtów, inicjując r jako część listy argumentów: ->s,a,*rco zapewnia także dodatkową funkcję, że osoba dzwoniąca może
zalać

Och, i podobnie rzucić xw tablicę:.count{|*x|
histocrat

1

C (gcc) , 112 110 108 bajtów

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

Wypróbuj online!

Nieco mniej golfa

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

0

C (gcc) , 156 bajtów

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

Wypróbuj online!

Opis:

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

Proponuję wmemset(c,-1,x)zamiast n=m=0;for(i=0;i<x;++i)c[i]=-1, n=m=i=s=0zamiast i=s=0, for(j=x;j--;)zamiast for(j=0;j<x;++j), a s||(c[n++]=_[i],m++,n%=x);zamiastif(!s){c[n++]=_[i];m++;n%=x;}
ceilingcat



0

Rdza , 129 bajtów

|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()}

Wypróbuj online!

Bez golfa

|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()
    }
}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.