Projektujesz nowy ezoteryczny język programowania, a jedną z funkcji, którą postanowiłeś dodać, jest dynamiczny alokator pamięci. Twój język określa specjalną dedykowaną wirtualną przestrzeń adresową dla przestrzeni programowej użytkownika. Jest to oddzielne od przestrzeni adresowej używanej przez alokator pamięci dla dowolnego stanu wewnętrznego.
Aby zmniejszyć koszt dystrybucji implementacji, rozmiar kodu musi być jak najmniejszy.
Berło
Musisz zapewnić trzy funkcje: inicjowanie, przydzielanie i cofanie przydziału.
Inicjalizacja
Ta funkcja przyjmuje pojedynczy dodatni parametr liczby całkowitej N
. Oznacza to, że program użytkownika ma N
w swojej przestrzeni adresowej bajty, z których są N-1
bajty do przydzielenia pamięci. Adres 0
jest zarezerwowany dla „null”.
Zagwarantowane jest, że funkcja ta zostanie wywołana dokładnie raz przed każdym połączeniem alokacji / cofnięcia przydziału.
Należy pamiętać, że ta funkcja nie musi przydzielać pamięci fizycznej dla wirtualnej przestrzeni adresowej programu użytkownika; zasadniczo tworzysz „wygląd i styl” pustego alokatora pamięci.
Przeznaczyć
Funkcja przydzielania musi przyjąć żądanie liczby bajtów pamięci do przydzielenia. Dane wejściowe są gwarantowane jako pozytywne.
Twoja funkcja musi zwrócić adres liczby całkowitej na początek przydzielonego bloku lub 0
wskazać, że nie ma dostępnego ciągłego bloku o żądanym rozmiarze. Jeśli ciągły blok o dostępnym rozmiarze jest dostępny w dowolnym miejscu w przestrzeni adresowej, musisz go przydzielić!
Musisz upewnić się, że żadne dwa przydzielone bloki się nie pokrywają.
Cofnij przydział
Funkcja dezalokacji musi przyjmować adres początku przydzielonego bloku i opcjonalnie może również przyjmować rozmiar danego bloku.
Pamięć, która została zwolniona, jest ponownie dostępna do alokacji. Zakłada się, że adres wejściowy jest prawidłowy.
Przykładowa implementacja języka Python
Pamiętaj, że możesz wybrać dowolną metodę śledzenia stanu wewnętrznego; w tym przykładzie instancja klasy śledzi to.
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]
Punktacja
To jest kod golfowy; najkrótszy kod w bajtach wygrywa. Nie musisz się martwić, że zabraknie pamięci dla dowolnego stanu wewnętrznego wymaganego przez twój program przydzielający.
Obowiązują standardowe otwory na pętle.
Tabela liderów
var QUESTION_ID=67895,OVERRIDE_USER=31729;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"http://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>
To help reduce the cost of distributing your implementation the size of the code must be as small as possible
czy może być wydajny (mały i wydajny to nie to samo), jak to możliwe? : DOdpowiedzi:
Ruby, 80
Podobnie jak odpowiedź MegaTom, ale do przechowywania stanu używa ciągu zamiast tablicy. Znak „o” oznacza otwartą komórkę, a „f” oznacza wypełnioną. To pozwala nam używać względnie zwięzłych funkcji manipulacji ciągiem Ruby:
?o*n
inicjuje ciąg n "o"./\B#{?o*n}/
jest wyrażeniem regularnym pasującym n kolejnych „o”, które nie zawierają pierwszego znaku.sub!
zastępuje pierwsze dopasowanie n „f” s."#$`"
podaje ciąg po lewej stronie dopasowania lub pusty ciąg, jeśli nie było dopasowania, więc rozmiar jest albo przydzielonym indeksem, albo 0.Deallocate po prostu ustawia wyznaczoną sekcję ciągu z powrotem na „o”.
źródło
JavaScript (ES6), 88
Używanie zmiennej globalnej
_
( bardzo rzadkiej tablicy) do śledzenia.Jak mogę to przetestować?
źródło
Ruby, 135
Ma globalną tablicę śledzącą, czy każda komórka jest przydzielona czy nie.
źródło
Mathematica, 152
n
zapisz całkowity rozmiar,l
przechowuje stan wewnętrzny. Alokator spróbuje przydzielić bezpośrednio za inną sekcją przydzielonej pamięci.źródło