Bellek Ayırıcı


11

Yeni bir ezoterik programlama dili tasarlıyorsunuz ve eklemeye karar verdiğiniz bir özellik dinamik bir bellek ayırıcıdır. Diliniz, kullanıcının program alanı için özel olarak ayrılmış bir sanal adres alanı belirtir. Bu, herhangi bir dahili durum için bellek ayırıcı tarafından kullanılan adres alanından ayrıdır.

Uygulamanızı dağıtmanın maliyetini azaltmaya yardımcı olmak için kodun boyutu mümkün olduğunca küçük olmalıdır.

Arayüz

Üç işlev sağlamalısınız: başlatma, tahsis etme ve dağıtma.

Başlatma

Bu işlev tek bir pozitif tamsayı parametresi alır N. Bu, bir kullanıcının programının Nadres alanında, N-1bellek ayıracak baytların bulunduğu baytlar olduğu anlamına gelir . Adres 0"null" olarak ayrılmıştır.

Herhangi bir tahsis / ayrılma çağrısından önce bu işlevin tam olarak bir kez çağrılması garanti edilir.

Bu işlevin, kullanıcı programının sanal adres alanı için herhangi bir fiziksel bellek ayırmasına gerek olmadığını unutmayın; temel olarak içi boş bir bellek ayırıcısının "görünümünü ve hissini" yaratıyorsunuz.

ayırmak

Ayırma işlevi, ayrılacak bellek bayt sayısının bir isteğini almalıdır. Girişin pozitif olduğu garanti edilir.

İşlevinizin, ayrılmış bloğun başına bir tamsayı adresi döndürmesi veya 0istenen boyutta bitişik bir blok olmadığını belirtmesi gerekir. Adres alanının herhangi bir yerinde kullanılabilir boyutta bitişik bir blok varsa, ayırmanız gerekir!

Ayrılan iki bloğun çakışmamasını sağlamalısınız.

ayırması

Deallocate işlevi tahsis edilmiş bir bloğun başlangıcının adresini almalı ve isteğe bağlı olarak verilen bloğun boyutunu da alabilir.

Ayrılan bellek yeniden tahsis için kullanılabilir. Girilen adresin geçerli bir adres olduğu varsayılmaktadır.

Örnek Python uygulaması

Dahili durumu izlemek için herhangi bir yöntem seçebileceğinizi unutmayın; bu örnekte class örneği bunu izler.

class myallocator:
    def __init__(self, N):
        # address 0 is special, it's always reserved for null
        # address N is technically outside the address space, so use that as a
        # marker
        self.addrs = [0, N]
        self.sizes = [1, 0]

    def allocate(self, size):
        for i,a1,s1,a2 in zip(range(len(self.addrs)),
                                 self.addrs[:-1], self.sizes[:-1],
                                 self.addrs[1:]):
            if(a2 - (a1+s1) >= size):
                # enough available space, take it
                self.addrs.insert(i+1, a1+s1)
                self.sizes.insert(i+1, size)
                return a1+s1
        # no contiguous spaces large enough to take our block
        return 0

    def deallocate(self, addr, size=0):
        # your implementation has the option of taking in a size parameter
        # in this implementation it's not used
        i = self.addrs.index(addr)
        del self.addrs[i]
        del self.sizes[i]

puanlama

Bu kod golf; bayt cinsinden en kısa kod kazanır. Ayırma cihazınızın gerektirdiği herhangi bir dahili durum için belleğin bitmesi konusunda endişelenmenize gerek yoktur.

Standart halka delikleri uygulanır.

Liderler Sıralaması


3
Python listelerinin öğe başına tam bir bayt aldığından şüpheliyim. "Ayrılan bellek" bayt cinsinden mi olmalı, yoksa sadece "dilinizin genel dizisi / liste türü" olabilir mi?
Kapı tokmağı

4
Gerçek bir tahsis gerekmez (kendi sanal adres alanında bulunan dahili durum izleme için ne istersen hariç); tam sayıları yalnızca soyut sonlu sanal adres alanına döndürüyorsunuz.
helloworld922

To help reduce the cost of distributing your implementation the size of the code must be as small as possibleya da mümkün olabilir (küçük ve verimli aynı değil)? : D
Kodlayıcı


Bu zorluk bir dil tasarım arka planı ile motive olsa da, bir dil tasarlamak aslında görevin bir parçası değildir (bir parçanın parçalarını uygulamak), bu yüzden etiketi kaldırdım.
Martin Ender

Yanıtlar:


4

Yakut, 80

i,a,d=->n{$m=?o*n},->n{$m.sub!(/\B#{?o*n}/,?f*n);"#$`".size},->n,s{$m[n,s]=?o*s}

MegaTom'un yanıtı gibi, ancak durumu depolamak için dizi yerine bir dize kullanır . "O" karakteri açık bir hücreyi, "f" ise doldurulmuş bir hücreyi belirtir. Bu, Ruby'nin nispeten kısa dize düzenleme işlevlerini kullanmamızı sağlar:

?o*n n "o" s dizesini başlatır.

/\B#{?o*n}/ilk karakteri içermeyen ardışık n "o" ler ile eşleşen normal bir ifadedir. sub!ilk maçı n "f" s ile değiştirir.

"#$`" dizeyi eşleşmenin soluna veya eşleşme yoksa boş bir dize verir, bu nedenle boyut ayrılan dizin veya 0 olur.

Deallocate, dizenin belirtilen bölümünü "o" s olarak ayarlar.


4

JavaScript (ES6), 88

Takip etmek için global bir değişken _( çok seyrek bir dizi) kullanmak.

Şimdi nasıl test edebilirim?

I=n=>(_=[1],_[n]=0)
A=n=>_.some((x,i)=>i-p<n?(p=i+x,0):_[p]=n,p=1)?p:0
D=p=>delete _[p]

3

Yakut, 135

Her dizinin tahsis edilip edilmediğini takip eden global bir diziye sahiptir.

i=->n{$a=[!0]*n;$a[0]=0}
a=->n{s=$a.each_cons(n).to_a.index{|a|a.none?};n.times{|i|$a[s+i]=0}if s;s||0}
d=->s,n{n.times{|i|$a[s+i]=!0}}

1

Mathematica, 152

i=(n=#;l={{0,1},{#,#}};)&
a=If[#=={},0,l=l~Join~#;#[[1,1]]]&@Cases[l,{Except@n,e_}:>{e,e+#}/;Count[l,{a_,_}/;e<=a<e+#]<1,1,1]&
d=(l=l~DeleteCases~{#,_};)&

ntoplam boyutu ldepolar, dahili durumu saklar. Ayırıcı, ayrılan belleğin başka bir bölümünün hemen arkasına ayırmaya çalışacaktır.

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.