Bộ nhớ đệm tối ưu


14

Bạn sẽ được cung cấp một chuỗi các yêu cầu bộ nhớ và kích thước bộ đệm. Bạn phải trả lại số lần nhớ cache ít nhất có thể theo bất kỳ chiến lược thay thế bộ đệm nào.

Một chiến lược tối ưu là thuật toán của Belotti , mà bạn có thể sử dụng nếu muốn.


Một hệ thống bộ đệm hoạt động như sau: Bộ đệm bắt đầu trống. Yêu cầu bộ nhớ đến. Nếu yêu cầu yêu cầu một phần dữ liệu trong bộ đệm, tất cả đều ổn. Nếu không, bạn phải chịu một lỗi nhớ cache. Tại thời điểm này, bạn có thể chèn dữ liệu được yêu cầu vào bộ đệm để sử dụng trong tương lai. Nếu bộ đệm đã đầy và bạn muốn chèn dữ liệu mới, bạn phải xóa dữ liệu trước đó trong bộ đệm. Bạn không bao giờ có thể chèn dữ liệu không chỉ trong bộ đệm.

Mục tiêu của bạn là tìm ra số lượng bộ nhớ cache tối thiểu có thể có cho một chuỗi yêu cầu bộ nhớ nhất định và kích thước bộ đệm.


Bạn sẽ được cung cấp kích thước bộ đệm, số nguyên dương và chuỗi yêu cầu bộ nhớ, là danh sách các mã thông báo. Các mã thông báo này có thể là bất kỳ loại mã thông báo nào bạn thích, miễn là có ít nhất 256 mã thông báo khác nhau (byte là tốt, bool thì không). Ví dụ, ints, chuỗi, danh sách đều ổn. Yêu cầu làm rõ nếu cần.


Các trường hợp thử nghiệm:

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

6

Xem wikipedia để biết chính sách thay thế đạt được điều này.

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

3

Đơn giản chỉ cần tránh thêm 2vào bộ đệm.

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

9

Một cách để đạt được điều này là không bao giờ đuổi 02và đuổi 1càng sớm càng tốt sau lần sử dụng cuối cùng.


Ghi điểm: Đây là mã golf. Ít byte nhất sẽ thắng.


Chúng tôi có thể giả định rằng danh sách chứa ít nhất 2 mã thông báo không?
Arnauld

@Arnauld Tôi sẽ nói không, mặc dù nếu chỉ có 1 giải pháp, câu trả lời tất nhiên luôn là 1.
isaacg

Câu trả lời:


4

JavaScript (ES6), 128 byte

Đưa đầu vào là (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

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

Đã bình luận

Đây là một triển khai thuật toán của Beligar.

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 byte

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
}

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

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 byte mà không thụt lề, dòng mới, dấu cách, nhận xét:

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 byte

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

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

Giải trình

Hoạt động bằng sức mạnh vũ phu: tất cả các chiến lược bộ nhớ cache đã được thử và kết quả tốt nhất được trả về.

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.

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.