FIFO 캐시 누락 수


35

이 도전은 정말 간단하다 (그리고 더 어려운 도전의 선구자!).

자원 액세스 배열 (음이 아닌 정수로 간단히 표시됨)과 매개 변수가 주어지면 n캐시에 용량이 있다고 가정하고 캐시 n가 가득 찼을 때 FIFO (First-In-First-Out) 배출 체계를 사용 한다고 가정 할 때 캐시 누락 수를 리턴하십시오. .

예:

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]

이 예에서는 9 번의 누락이있었습니다. 코드 예제가 더 잘 설명하는 데 도움이 될 수 있습니다. 파이썬에서 :

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

몇 가지 추가 테스트 사례 (다음 도전에 대한 힌트가 포함되어 있습니다. 궁금한 점이 있습니까?) :

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

바이트 단위의 최단 코드가 이깁니다.


15
나는 notice anything curious?잠시 동안 마지막 진술 을 보고 있었고 ... 방금 캐시 용량을 늘리는 것이 반드시 누락 수를 줄이는 것은 아니라는 것을 알았습니다!
JungHwan Min

@JungHwanMin 맞습니다! 실제로, 얼마나 더 나빠질 수 있는지는 끝이 없습니다.
orlp

단항으로 숫자를 출력 할 수 있습니까?
dylnan

9
Bélády의 이상 현상 으로 알려져 있으며 FIFO가 대표적인 예입니다. 변칙은 끝이 없다 .
virtualirfan

@dylnan 아니요, 죄송합니다.
orlp

답변:


11

자바 스크립트 (ES6), 55 바이트

방법 # 1 : 캐시가 입력을 덮어 씁니다.

카레 구문으로 입력을 (cache_size)(list)받습니다.

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

온라인으로 사용해보십시오!

어떻게?

0으로 초기화 된 별도의 포인터 k를 사용하여 입력 배열 a [] 를 캐시로 덮어 씁니다 .

x 가 캐시에 a.indexOf(x, k > n && k - n) < k있는지 여부를 테스트 하는 데 사용 합니다.

캐시는 원래 배열을 수행하는 것보다 빠르게 커질 수 없으므로 캐시 창 안 또는 밖에서 각 값을 찾을 수 있습니다 (즉, -1을indexOf() 반환하지 않음 ).

max (0, k-n)k-1 (두 범위 포함) 사이의 인덱스에서 발견되면 값은 캐시 에 있으며,이 경우 a [true] = x 입니다. 이것은 a [] 뒤에 있는 기본 객체의 속성에만 영향을 미치지 만 배열 a []는 변경하지 않습니다 . 그렇지 않으면, 우리는 a [k ++] = x 합니다.

다음은 [1, 1, 2, 3, 3, 2, 1, 4]캐시 크기가 2 인 입력의 다른 단계입니다 .

  • 굵은 테두리 : map () 포인터
  • 괄호 : 캐시 포인터 k
  • 주황색 : 현재 캐시 창
  • 노란색 : 만료 된 캐시 값

방법 # 1


자바 스크립트 (ES6), 57 바이트

방법 # 2 : 입력 끝에 캐시가 추가됨

카레 구문으로 입력을 (cache_size)(list)받습니다.

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

온라인으로 사용해보십시오!

어떻게?

입력 배열 a [] 는 음이 아닌 정수를 포함하도록 보장되므로 각 값 x 의 1-complement ~ x 를 사용하여 a [] 끝에 캐시를 안전하게 추가 할 수 있습니다 .

마지막 n 값 중에서 ~ x 가 발견 n * ~a.indexOf(~x, -n)되는지 테스트 하는 데 사용 합니다. 이 테스트가 실패 할 때마다 ~ [ xa []에 추가 하고 미스 수 k를 증가시킵니다 .

아래는이 방법을 사용하는 위와 동일한 예제에 대한 다른 단계입니다. 캐시 값은 단순히 배열의 끝에 추가되기 때문에 명시적인 캐시 포인터가 없습니다.

방법 # 2



9

파이썬 2 , 58 바이트

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

온라인으로 사용해보십시오!

3 바이트에 대한 ovs와 3 개에 대한 xnor 덕분입니다.


c+=어떤 이유로 인해 목록을 변환하기 때문에 뒤에 세트를 넣어 바이트를 절약 할 수 있어야 합니다.
xnor

(예, 아, c+={i}-set(c[-n:])긍정적를위한 작품, n하지만 nimi가 지적했다. c[-n:]잘못이다 n == 0내가 사용할 수 있도록, +=따라서 그 트릭, 그리고 -. 너무 나쁜)

1
@Lynn 아, 알겠습니다. reduce여전히 바이트를 저장합니다 : lambda n,a:len(reduce(lambda c,i:[i][i in c[:n]:]+c,a,[])).
xnor

7

R , 69 64 62 바이트

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

온라인으로 사용해보십시오!

개선 사항을 제안한 JayCe와 다른 커플을위한 DigEmAll에 감사드립니다!


나는 생각 +의 앞에 F입니다 f(0,{})0을 반환 할?
JayCe

@JayCe yep, F사전 초기화 된 반환 값 과 함께 클래식 골프 .
주세페

1
작은 향상 . 또한 단항 출력이 허용되면 일부 바이트를 절약 할 수 있습니다.
JayCe

@JayCe가 더 많은 바이트를 찾았습니다!
주세페

1
@ JDL 네, 부끄러운 일 q이지만 여전히 좋은 생각입니다! 실제로 길이를 걱정하기 때문에 사용하는 NA것이 사용하는 것보다 좋지 {}않습니다 (캐시에서 실제로 요소를 표시하지 않습니다).
주세페

5

하스켈, 61 58 바이트

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

온라인으로 사용해보십시오!

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

편집 : @Lynn 덕분에 -3 바이트.


5

05AB1E , 17 16 바이트

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

온라인으로 사용해보십시오!

설명

)                   # 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 : 감사합니다! 바이트를 저장하는 동안 수정 :)
Emigna

5

코 틀린 , 82 69 바이트

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

int로서 입력을 받아 IntArray, 하지 전형적인 List<Int>(문제가 안되는). 이것은 "캐시 히스토리를 구축하고, 그 길이를 계산"의 방법을 사용한다.

온라인으로 사용해보십시오!

설명

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

빈 목록 만들기

Kotlin에는 컬렉션 리터럴이 없지만 새 컬렉션을 만드는 기능이 있습니다.

빈을 만드는 올바른 방법 List<Int>은 다음과 같습니다.

List<Int>()

그러나 크기와 이니셜 라이저 인수를 남용하면이 작업이 더 짧습니다.

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

생성기 람다는 0을 반환하므로 Kotlin은이 목록의 유형을로 추정하고 List<Int>0의 크기는이 목록이 비어 있음을 의미합니다.


4

펄 6 , 48 바이트

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

그것을 테스트

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

자바 8, 96 바이트

캐시 크기 ( int) 및 액세스 목록 (변경 가능 java.util.List<Integer>)을 가져 와서을 반환하는 카레 람다 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;}

온라인으로 사용해보십시오

언 골프

s캐시에 대한 입력 목록 의 첫 번째 (최대) 슬롯을 사용합니다.

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

감사의 말

  • 에 버그 수정 덕분에 nimi

4

Pyth ,  16 15 18 14  13 바이트

isaacg 덕분에 1 바이트를 절약했습니다 .

luaW-H>QGGHEY

테스트 스위트!

이 과제는 Pyth의 u구조에 매우 적합합니다 .

작동 원리

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
isaacg에

@isaacg 감사합니다! 나는 처음에 +G*]H!}H>QG그것을 가지고 있었지만 골프를 쳤을 때 나는 정말로 생각하지 못했습니다 W... 좋은!
Mr. Xcoder

정확히 무엇을 u합니까?
dylnan

@dylnan u은 초기 값 연산자를 사용한 축소입니다. 젤리처럼ƒ
Mr. Xcoder


2

apt, 16 바이트

;£A¯V øX ªAiXÃAl

시도 해봐


설명

                     :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 바이트

해결책:

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

예 :

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

설명:

내부 함수의 경우 y는 캐시이고 z는 요청이며 x는 캐시 크기입니다.

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

노트:

이 모든 작업을 수행하는 더 좋은 방법이있을 수 있지만 이것이 가장 먼저 떠오른 방법입니다.

이 함수는 36 바이트 동안 다음 과 같이 실행될 수 있습니다 .

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

대안-전역 변수를 사용하여 상태 (K와 같지 않음), 42 바이트 저장 :

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

1

Brain-Flak , 172 바이트

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

온라인으로 사용해보십시오!

# 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

젤리 , 18 바이트

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

온라인으로 사용해보십시오!

목록을 첫 번째 인수로 사용하고 캐시 용량을 두 번째 인수로 사용합니다.

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

루비 , 43 40 바이트

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

온라인으로 사용해보십시오!

3 바이트를 면도 해 주셔서 감사합니다.


1
좋은 대답입니다! 당신은 인수 목록의 일환으로 초기화 R로 몇 바이트를 저장할 수 있습니다 ->s,a,*r또한 보너스 기능을 제공하는 호출 할 수있는 여분의 인수 :) 전달하여 주요 캐시
histocrat을

아, 그리고 비슷하게 x배열 로 캐스팅 :.count{|*x|
histocrat

1

C (GCC) , 112 (110) 108 바이트

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

온라인으로 사용해보십시오!

약간 덜 골프

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 바이트

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

온라인으로 사용해보십시오!

기술:

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

제안 wmemset(c,-1,x)대신 n=m=0;for(i=0;i<x;++i)c[i]=-1, n=m=i=s=0대신 i=s=0, for(j=x;j--;)대신 for(j=0;j<x;++j)하고, s||(c[n++]=_[i],m++,n%=x);대신if(!s){c[n++]=_[i];m++;n%=x;}
ceilingcat



0

, 129 바이트

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

온라인으로 사용해보십시오!

언 골프

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.