การแคชที่เหมาะสมที่สุด


14

คุณจะได้รับลำดับของการร้องขอหน่วยความจำและขนาดแคช คุณต้องส่งคืนจำนวนแคชที่น้อยที่สุดที่เป็นไปได้ภายใต้กลยุทธ์การแทนที่แคชใด ๆ

กลยุทธ์ที่ดีที่สุดคืออัลกอริทึมของ Beladyซึ่งคุณสามารถใช้ได้หากคุณต้องการ


ระบบแคชทำงานดังนี้แคชเริ่มว่างเปล่า คำขอหน่วยความจำเข้ามาหากคำขอขอชิ้นส่วนของข้อมูลในแคชทั้งหมดเป็นอย่างดี ถ้าไม่คุณจะได้รับแคช ณ จุดนี้คุณสามารถแทรกข้อมูลที่ถูกร้องขอลงในแคชเพื่อใช้ในอนาคต หากแคชเต็มและคุณต้องการแทรกข้อมูลใหม่คุณต้องขับไล่ข้อมูลที่เคยอยู่ในแคชก่อนหน้านี้ คุณไม่สามารถแทรกข้อมูลที่ไม่ได้อยู่ในแคช

เป้าหมายของคุณคือค้นหาจำนวนแคชที่น้อยที่สุดเท่าที่จะเป็นไปได้สำหรับลำดับการร้องขอหน่วยความจำและขนาดแคชที่กำหนด


คุณจะได้รับขนาดแคชจำนวนเต็มบวกและลำดับคำขอหน่วยความจำซึ่งเป็นรายการของโทเค็น โทเค็นเหล่านี้สามารถเป็นโทเค็นแบบใดก็ได้ที่คุณต้องการตราบใดที่มีโทเค็นที่แตกต่างกันอย่างน้อย 256 ตัวเป็นไปได้ (ไบต์นั้นใช้ได้ ตัวอย่างเช่น ints, สตริง, รายการทั้งหมดเป็นเรื่องปกติ ขอคำชี้แจงหากจำเป็น


กรณีทดสอบ:

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

6

ดูวิกิพีเดียสำหรับนโยบายการเปลี่ยนที่ประสบความสำเร็จ

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

3

เพียงหลีกเลี่ยงการเพิ่ม2ลงในแคช

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

9

วิธีการหนึ่งเพื่อให้บรรลุนี้โดยไม่เคยขี้บ่น0และ2และขี้บ่น1โดยเร็วที่สุดเท่าที่เป็นไปได้หลังการใช้งานเป็นครั้งสุดท้าย


เกณฑ์การให้คะแนน: นี่คือรหัสกอล์ฟ ไบต์ที่น้อยที่สุดจะเป็นผู้ชนะ


เราสามารถสรุปได้ว่ารายการมีโทเค็นอย่างน้อย 2 รายการหรือไม่
Arnauld

@Arnauld ฉันจะปฏิเสธไม่ได้แม้ว่าจะมีวิธีแก้ปัญหาเพียง 1 ข้อเท่านั้นแน่นอนว่าคำตอบคือ 1 เสมอ
isaacg

คำตอบ:


4

JavaScript (ES6), 128 ไบต์

(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

ลองออนไลน์!

แสดงความคิดเห็น

นี่คือการใช้อัลกอริทึมของ 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 ไบต์

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
}

ลองออนไลน์!

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 ไบต์โดยไม่มีการเยื้อง, การขึ้นบรรทัดใหม่, ช่องว่าง, ความคิดเห็น:

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 ไบต์

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

ลองออนไลน์!

คำอธิบาย

ทำงานโดยใช้กำลังดุร้าย: พยายามใช้แคชกับทุกกลยุทธ์และให้ผลลัพธ์ที่ดีที่สุด

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.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.