Você está projetando uma nova linguagem de programação esotérica e um recurso que decidiu adicionar é um alocador de memória dinâmico. Seu idioma especifica um espaço de endereço virtual dedicado especial para o espaço do programa do usuário. Isso é separado do espaço de endereço usado pelo alocador de memória para qualquer estado interno.
Para ajudar a reduzir o custo de distribuição de sua implementação, o tamanho do código deve ser o menor possível.
Interface
Você deve fornecer três funções: inicialização, alocação e desalocação.
Inicialização
Esta função aceita um único parâmetro inteiro positivo N
. Isso significa que o programa de um usuário possui N
bytes no espaço de endereço dos quais existem N-1
bytes para alocar memória. O endereço 0
está reservado para "nulo".
É garantido que esta função será chamada exatamente uma vez antes de qualquer chamada de alocação / desalocação.
Observe que essa função não precisa alocar memória física para o espaço de endereço virtual do programa do usuário; você está basicamente criando a "aparência e aparência" de um alocador de memória vazio.
distribuir
A função de alocação deve receber uma solicitação do número de bytes de memória a ser alocada. A entrada é garantida para ser positiva.
Sua função deve retornar um endereço inteiro para o início do bloco alocado ou 0
para indicar que não há nenhum bloco contíguo do tamanho solicitado disponível. Se um bloco contíguo do tamanho disponível estiver disponível em qualquer lugar do espaço de endereço, você deverá alocar!
Você deve garantir que nenhum dos dois blocos alocados se sobreponha.
Desalocar
A função de desalocação deve assumir um endereço do início de um bloco alocado e, opcionalmente, também pode assumir o tamanho do bloco especificado.
A memória desalocada está disponível novamente para alocação. Supõe-se que o endereço de entrada seja um endereço válido.
Exemplo de implementação em Python
Observe que você pode escolher qualquer método para acompanhar o estado interno; neste exemplo, a instância da classe controla isso.
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]
Pontuação
Isso é código de golfe; o menor código em bytes vence. Você não precisa se preocupar com a falta de memória para qualquer estado interno exigido pelo seu alocador.
Aplicam-se orifícios de loop padrão.
Entre os melhores
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
ou poderia ser eficiente (pequeno e eficiente não são os mesmos) possível? : DRespostas:
Ruby, 80
Como a resposta do MegaTom, mas usa uma string em vez de uma matriz para armazenar o estado. O caractere "o" indica uma célula aberta, enquanto um "f" indica uma célula preenchida. Isso nos permite usar as funções de manipulação de string relativamente concisas do Ruby:
?o*n
inicializa uma sequência de n "o" s./\B#{?o*n}/
é uma expressão regular que corresponde a n "o" s consecutivos que não incluem o primeiro caractere.sub!
substitui a primeira correspondência por n "f" s."#$`"
fornece a sequência à esquerda da correspondência ou uma sequência vazia, se não houver correspondência; portanto, o tamanho é o índice alocado ou 0.A desalocação apenas define a seção designada da string de volta para "o" s.
fonte
JavaScript (ES6), 88
Usando uma variável global
_
(uma matriz muito esparsa) para acompanhar.Agora, como eu poderia testá-lo?
fonte
Ruby, 135
Possui uma matriz global para acompanhar se cada célula está alocada ou não.
fonte
Mathematica, 152
n
armazenar o tamanho total,l
armazena o estado interno. O alocador tentará alocar logo atrás de outra seção da memória alocada.fonte