FIFO önbellek özlüyor sayısı


35

Bu zorluk gerçekten basittir (ve daha zor olanın öncüsüdür!).

Bir dizi kaynak erişimi (yalnızca negatif olmayan tamsayılarla belirtilir) ve bir parametre nverildiğinde, önbelleğimizin kapasiteye sahip olduğunu nve ilk dolduğunda ilk giren ilk (FIFO) ejeksiyon şemasını kullandığını varsayarsa, önbellek sayısını geri döndürür. .

Örnek:

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]

Yani bu örnekte 9 özledim. Belki bir kod örneği daha iyi açıklamaya yardımcı olur. Python'da:

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

Bazı ileri test sınavları (bir sonraki yarışmaya ilişkin bir ipucu içeren - meraklı bir şey farkettiniz mi?):

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

Bayt cinsinden en kısa kod kazanır.


15
notice anything curious?Bir süredir son ifadeye bakıyordum ... ve farkettim ki, önbellek kapasitesini arttırmak, özlüyor sayılarınızı düşürmek zorunda değil mi ?!
JungHwan Min 11:18

@JungHwanMin Doğru! Aslında, ne kadar kötüye gidebileceği sınırsızdır.
orlp

Sayıyı unary olarak verebilir miyiz?
dylnan

9
Bélády'nin anomalisi olarak bilinen ve FIFO klasik örnektir. Anomali sınırsızdır .
virtualirfan

@dylnan Hayır, özür dilerim.
orlp

Yanıtlar:


11

JavaScript (ES6), 55 bayt

Yöntem # 1: önbellek girdinin üzerine yazar.

Körleme sözdiziminde girdi alır (cache_size)(list).

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

Çevrimiçi deneyin!

Nasıl?

0 ile başlatılan ayrı bir işaretçi k kullanarak, ön dizideki a [] giriş dizisinin üzerine yazıyoruz .

X'in önbellekte a.indexOf(x, k > n && k - n) < kolup olmadığını test etmek için kullanıyoruz .

Önbellek, orijinal dizinin içinden geçirilenden daha hızlı büyüyemez, bu nedenle her değerin, önbellek penceresinin içinde veya ötesinde bulunacağı garanti edilir (yani indexOf(), asla -1 döndürmez ).

Maksimum (0, k - n) ve k - 1 (her iki sınır dahil) arasında bir dizinde bulunursa önbellekte bir değer bulunur, bu durumda [true] = x yaparız . Bu yalnızca ardında yatan nesnenin bir özelliği etkiler bir [] , ancak değiştirmeyen dizi a [] . Aksi takdirde, bir [k ++] = x yaparız .

Örnek

Aşağıda [1, 1, 2, 3, 3, 2, 1, 4]önbellek boyutu 2 olan giriş için farklı adımlar verilmiştir :

  • kalın kenarlıklar: map () pointer
  • parantez: önbellek işaretçisi k
  • turuncu: geçerli önbellek penceresi
  • sarı: süresi dolmuş önbellek değerleri

Yöntem 1


JavaScript (ES6), 57 bayt

Yöntem # 2: önbellek girişin sonuna eklenir

Körleme sözdiziminde girdi alır (cache_size)(list).

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

Çevrimiçi deneyin!

Nasıl?

Giriş dizisi a [] ' nın negatif olmayan tamsayı içerdiği garanti edildiğinden , her bir x değerinin bir-tamamlayıcısını ~ x kullanarak [] sonunda önbelleği güvenle ekleyebiliriz .

Son x değerleri arasında ~ xn * ~a.indexOf(~x, -n) bulunup bulunmadığını test etmek için kullanıyoruz . Bu test başarısız zaman, biz ekleme ~ x için bir [] ve kaçırdığı sayısını artırmak k .

Örnek

Aşağıda, bu yöntemi kullanarak, yukarıdaki ile aynı örnek için farklı adımlar verilmiştir. Önbellek değerleri yalnızca dizinin sonuna eklendiğinden, açık bir önbellek işaretçisi yoktur.

yöntem # 2



9

Python 2 , 58 bayt

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

Çevrimiçi deneyin!

3 byte için ovs ve 3 tane daha için xnor sayesinde.


Herhangi bir c+=nedenden dolayı sizin için bir listeye dönüştüğü için bir küme koyarak baytları kaydedebilmelisiniz .
xnor

(ah, evet, c+={i}-set(c[-n:])işe nyarar , olumlu . Ama nimi c[-n:]bunun yanlış olduğunu belirtti n == 0, bu yüzden kullanamam +=ve dolayısıyla bu numarayı - çok kötü.)
Lynn

1
@ Lynn Ah, anlıyorum. reduceHala bayt kaydeder: lambda n,a:len(reduce(lambda c,i:[i][i in c[:n]:]+c,a,[])).
xnor

7

R , 69 64 62 bayt

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

Çevrimiçi deneyin!

Bazı iyileştirmeler önerdiğiniz için JayCe'ye ve başka bir çift için DigEmAll'a teşekkürler!


Sanırım +önünde 0 dönmek Fiçin f(0,{})?
JayCe

@JayCe evet, Fönceden başlatılmış bir dönüş değeri olarak sırayla klasik bir golf .
Giuseppe

1
küçük bir gelişme . Ayrıca, unary çıkış kabul edilirse, muhtemelen bazı baytları kaydedebilirsiniz.
JayCe

@JayCe biraz daha bayt buldu!
Giuseppe,

1
@JDL evet, qama yine de güzel bir fikir hakkında bir utanç ! Kullanmak NA, kullanmaktan daha az iyidir {}çünkü aslında buradaki uzunluğu önemsiyorum (ve aslında önbellek öğelerini açmıyorum).
Giuseppe

5

Haskell, 61 58 bayt

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

Çevrimiçi deneyin!

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

Düzenleme: @Lynn sayesinde -3 bayt.


5

05AB1E , 17 16 bayt

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

Çevrimiçi deneyin!

açıklama

)                   # 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: Teşekkürler! Bir bayt kaydedilirken düzeltildi :)
Emigna

5

Kotlin , 82 69 bayt

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

Bir şekilde girişi alır IntArray, değil tipik List<Int>(a problem olmamalı hangi.) Bu, "bir önbellek geçmişi oluşturmak ve uzunluğunu saymak" yaklaşımını kullanır.

Çevrimiçi deneyin!

açıklama

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

Boş bir liste oluşturma

Kotlin'in koleksiyon hazırlayıcıları yoktur, ancak yeni koleksiyonlar oluşturmak için bazı işlevleri vardır.

Boş yaratmanın doğru yolu List<Int>basitçe:

List<Int>()

ancak boyutu kötüye kullanırsak daha kısadır ve başlatıcı bunu yapmayı ister:

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

Jeneratör lambda değeri 0 döndürdüğünden, Kotlin bu listenin türünü girer List<Int>ve 0'ın boyutu bu listenin boş olduğu anlamına gelir.


4

Perl 6 , 48 bayt

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

Dene

{  # 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 bayt

Önbellek boyutu ( int) ve erişim listesini (değiştirilebilir java.util.List<Integer>) alan ve döndüren bir köreli lambda 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;}

Çevrimiçi Deneyin

Ungolfed

Bu s, önbellek için giriş listesindeki ilk (en fazla) alanı kullanır .

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

Teşekkür

  • nimi sayesinde bugfix

4

Pyth ,  16 15 18 14  13 bayt

İsaacg sayesinde 1 byte kaydedildi .

luaW-H>QGGHEY

Test odası!

Bu zorluk Pyth'in uyapısına çok uygun .

Nasıl çalışır

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?}H<GQG+HG1'e göre yener
isaacg

@isaacg Teşekkürler! Başlangıçta vardı +G*]H!}H>QG, ama golf yaparken gerçekten düşünmedim W... Güzel!
Bay Xcoder

Tam olarak ne yapar u?
dylnan

@ dylnan u, intial value operatörüne sahip bir azalmadır . Tıpkı ƒ
Jelly'inki


2

Japt, 16 bayt

;£A¯V øX ªAiXÃAl

Dene


açıklama

                     :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 bayt

Çözüm:

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

Örnekler:

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

Açıklama:

İç işlev için y önbellek, z istek ve x önbellek boyutudur.

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

Notlar:

Bunların hepsini yapmanın daha güzel bir yolu olabilir, ancak akla gelen ilk yol budur.

İşlev, 36 bayt için bu şekilde çalıştırılabilir :

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

Alternatif - durumunu depolamak için global bir değişken kullanma (çok K benzeri değil), 42 bayt :

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

1

Brain-Flak , 172 bayt

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

Çevrimiçi deneyin!

# 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

Jöle , 18 bayt

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

Çevrimiçi deneyin!

Listeyi ilk argüman ve önbellek kapasitesini ikinci argüman olarak alır.

Ṗɼṛ;ɼ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

C (gcc) , 112 110 108 bayt

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

Çevrimiçi deneyin!

Biraz daha az golf oynadı

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 bayt

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

Çevrimiçi deneyin!

Açıklama:

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

Öner wmemset(c,-1,x)yerine n=m=0;for(i=0;i<x;++i)c[i]=-1, n=m=i=s=0yerine i=s=0, for(j=x;j--;)yerine for(j=0;j<x;++j)ve s||(c[n++]=_[i],m++,n%=x);yerineif(!s){c[n++]=_[i];m++;n%=x;}
ceilingcat



0

Pas , 129 bayt

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

Çevrimiçi deneyin!

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.