Số lượng bộ nhớ cache FIFO bỏ lỡ


35

Thử thách này thực sự đơn giản (và là tiền thân cho một thử thách khó khăn hơn!).

Đưa ra một loạt các truy cập tài nguyên (được biểu thị đơn giản bằng các số nguyên không âm) và một tham số n, trả về số lượng bộ nhớ cache mà nó sẽ giả sử bộ đệm của chúng tôi có dung lượng nvà sử dụng sơ đồ tống xuất trước xuất trước (FIFO) khi đầy .

Thí dụ:

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]

Vì vậy, trong ví dụ này đã có 9 lần bỏ lỡ. Có lẽ một ví dụ mã giúp giải thích nó tốt hơn. Trong 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

Một số thử nghiệm tiếp theo (trong đó có gợi ý về thử thách tiếp theo - có nhận thấy điều gì tò mò không?):

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

Mã ngắn nhất trong byte thắng.


15
Tôi đã xem xét tuyên bố cuối cùng notice anything curious?một lúc rồi ... và chỉ cần chú ý, việc tăng dung lượng bộ đệm không nhất thiết phải giảm số lần bỏ lỡ?!
JungHwan Min

@JungHwanMin Đúng! Trong thực tế, nó tệ hơn bao nhiêu có thể không bị ràng buộc.
orlp

Chúng ta có thể xuất số trong unary không?
dyl Nam

9
Được biết đến như sự bất thường của Bélády và FIFO là ví dụ kinh điển. Sự bất thường là không giới hạn .
virtualirfan

@dylnan Không, xin lỗi.
orlp

Câu trả lời:


11

JavaScript (ES6), 55 byte

Phương pháp # 1: bộ đệm ghi đè lên đầu vào

Đưa đầu vào theo cú pháp currying (cache_size)(list).

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

Hãy thử trực tuyến!

Làm sao?

Chúng tôi ghi đè mảng đầu vào a [] bằng bộ đệm, sử dụng một con trỏ riêng k được khởi tạo thành 0 .

Chúng tôi sử dụng a.indexOf(x, k > n && k - n) < kđể kiểm tra xem x có trong bộ đệm hay không.

Bộ đệm không thể phát triển nhanh hơn mảng ban đầu được duyệt qua, do đó, mỗi giá trị được đảm bảo được tìm thấy, trong hoặc ngoài cửa sổ bộ đệm (nghĩa là indexOf()sẽ không bao giờ trả về -1 ).

Một giá trị nằm trong bộ đệm nếu nó được tìm thấy tại một chỉ số giữa max (0, k - n)k - 1 (bao gồm cả hai giới hạn), trong trường hợp đó chúng tôi thực hiện [true] = x . Điều này chỉ ảnh hưởng đến một thuộc tính của đối tượng cơ bản đằng sau [] nhưng không làm thay đổi mảng a [] . Mặt khác, chúng tôi thực hiện một [k ++] = x .

Thí dụ

Dưới đây là các bước khác nhau cho đầu vào [1, 1, 2, 3, 3, 2, 1, 4]với kích thước bộ đệm là 2 :

  • viền đậm: con trỏ map ()
  • ngoặc: con trỏ bộ đệm k
  • màu cam: cửa sổ bộ đệm hiện tại
  • màu vàng: giá trị bộ đệm đã hết hạn

phương pháp số 1


JavaScript (ES6), 57 byte

Phương pháp # 2: bộ đệm được thêm vào cuối đầu vào

Đưa đầu vào theo cú pháp currying (cache_size)(list).

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

Hãy thử trực tuyến!

Làm sao?

Vì mảng đầu vào [] được đảm bảo chứa các số nguyên không âm, chúng tôi có thể nối thêm bộ đệm vào cuối [] một cách an toàn bằng cách sử dụng một bổ sung ~ x của mỗi giá trị x .

Chúng tôi sử dụng n * ~a.indexOf(~x, -n)để kiểm tra xem ~ x có được tìm thấy trong số n giá trị cuối cùng hay không . Bất cứ khi nào thử nghiệm này thất bại, chúng tôi sẽ thêm ~ x vào [] và tăng số lần bỏ lỡ k .

Thí dụ

Dưới đây là các bước khác nhau cho cùng một ví dụ như trên, sử dụng phương pháp này. Bởi vì các giá trị bộ đệm chỉ được gắn vào cuối mảng, không có con trỏ bộ đệm rõ ràng.

phương pháp số 2



9

Python 2 , 58 byte

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

Hãy thử trực tuyến!

Cảm ơn ovs cho 3 byte và xnor cho thêm 3 byte.


Bạn sẽ có thể lưu byte bằng cách đặt một tập hợp sau c+=, vì một số lý do, nó chuyển đổi thành một danh sách cho bạn.
xnor

(ah, có, c+={i}-set(c[-n:])công trình, cho dương nNhưng Tên mẫu chỉ ra rằng. c[-n:]là sai n == 0, vì vậy tôi không thể sử dụng +=, và vì thế mà lừa -. quá xấu)
Lynn

1
@Lynn À, tôi hiểu rồi. reducevẫn lưu byte : lambda n,a:len(reduce(lambda c,i:[i][i in c[:n]:]+c,a,[])).
xnor

7

R , 69 64 62 byte

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

Hãy thử trực tuyến!

Cảm ơn JayCe đã gợi ý một số cải tiến và DigEmAll cho một cặp vợ chồng khác!


Tôi đoán +phía trước Ff(0,{})để trả về 0?
JayCe

@JayCe yep, một sân golf cổ điển song song với Fgiá trị trả lại được khởi tạo trước.
Giuseppe

1
một ngẫu hứng nhỏ . Ngoài ra nếu đầu ra unary được chấp nhận, bạn có thể lưu một số byte.
JayCe

@JayCe tìm thấy thêm một số byte!
Giuseppe

1
@JDL vâng, một sự xấu hổ về qnhưng vẫn là một ý tưởng tốt đẹp! Sử dụng NAít tốt hơn so với sử dụng {}vì tôi thực sự quan tâm đến độ dài ở đây (và tôi không thực sự bật các yếu tố từ bộ đệm).
Giuseppe

5

Haskell, 61 58 byte

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

Hãy thử trực tuyến!

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

Chỉnh sửa: -3 byte nhờ @Lynn.


5

05AB1E , 17 16 byte

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

Hãy thử trực tuyến!

Giải trình

)                   # 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: Cảm ơn! Đã sửa trong khi lưu một byte :)
Emigna

5

Kotlin , 82 69 byte

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

Lấy đầu vào là một IntArray, không phải là điển hình List<Int>(không nên là một vấn đề.) Điều này sử dụng phương pháp "xây dựng lịch sử bộ đệm và đếm chiều dài của nó".

Hãy thử trực tuyến!

Giải trình

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

Tạo một danh sách trống

Kotlin không có bộ sưu tập chữ, nhưng nó có một số chức năng để tạo bộ sưu tập mới.

Cách thích hợp để tạo một khoảng trống List<Int>đơn giản là:

List<Int>()

nhưng nó ngắn hơn nếu chúng ta lạm dụng kích thước và trình khởi tạo lập luận để làm điều này:

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

Vì trình tạo lambda trả về 0, nên Kotlin nhập vào loại danh sách này List<Int>và kích thước của 0 có nghĩa là danh sách này trống.


4

Perl 6 , 48 byte

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

Kiểm tra nó

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

Một lambda bị quấy rối lấy một kích thước bộ đệm ( int) và danh sách truy cập (có thể thay đổi java.util.List<Integer>) và trả lại một 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;}

Dùng thử trực tuyến

Ung dung

Điều này sử dụng các skhe (tối đa) đầu tiên trong danh sách đầu vào cho bộ đệm.

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

Lời cảm ơn

  • sửa lỗi nhờ nimi

4

Pyth ,  16 15 18 14  13 byte

Đã lưu 1 byte nhờ isaacg .

luaW-H>QGGHEY

Bộ thử nghiệm!

Thử thách này rất phù hợp với ucấu trúc của Pyth .

Làm thế nào nó hoạt động

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>QGGHnhịp đập ?}H<GQG+HGcủa 1
isaacg

@isaacg Cảm ơn! Ban đầu tôi đã có +G*]H!}H>QG, nhưng khi tôi chơi golf, tôi thực sự không nghĩ đến W... Hay !
Ông Xcoder

Chính xác thì ulàm gì?
dyl Nam

@dylnan ulà một giảm với toán tử giá trị intial . Giống như Jellyƒ
Ông Xcoder


2

Japt, 16 byte

;£A¯V øX ªAiXÃAl

Thử nó


Giải trình

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

Dung dịch:

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

Ví dụ:

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

Giải trình:

Đối với hàm bên trong, y là bộ đệm, z là yêu cầu và x là kích thước bộ đệm.

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

Ghi chú:

Có lẽ có một cách tốt hơn để làm tất cả những điều này, nhưng đây là cách đầu tiên xuất hiện trong tâm trí.

Hàm này có thể được chạy như thế này trong 36 byte :

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

Thay thế - sử dụng biến toàn cục để lưu trữ trạng thái (không giống K), 42 byte :

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

1

Brain-Flak , 172 byte

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

Hãy thử trực tuyến!

# 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

Thạch , 18 byte

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

Hãy thử trực tuyến!

Lấy danh sách làm đối số thứ nhất và dung lượng bộ đệm làm đối số thứ hai.

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

Ruby , 43 40 byte

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

Hãy thử trực tuyến!

Cảm ơn histocrat đã cạo 3 byte.


1
Câu trả lời tốt đẹp! Bạn có thể lưu một vài byte bằng cách khởi tạo r như một phần của danh sách đối số: ->s,a,*rcũng cung cấp tính năng phần thưởng mà người gọi có thể tạo bộ nhớ cache bằng cách chuyển các đối số phụ :)
histocrat

Ồ, và tương tự như đúc xthành một mảng:.count{|*x|
lịch sử

1

C (gcc) , 112 110 108 byte

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

Hãy thử trực tuyến!

Hơi ít chơi golf

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 byte

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

Hãy thử trực tuyến!

Sự miêu tả:

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

Đề xuất wmemset(c,-1,x)thay vì n=m=0;for(i=0;i<x;++i)c[i]=-1, n=m=i=s=0thay vì i=s=0, for(j=x;j--;)thay vì for(j=0;j<x;++j), và s||(c[n++]=_[i],m++,n%=x);thay vìif(!s){c[n++]=_[i];m++;n%=x;}
trần nhà



0

Rust , 129 byte

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

Hãy thử trực tuyến!

Ung dung

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.