Vous concevez un nouveau langage de programmation ésotérique et l'une des fonctionnalités que vous avez décidé d'ajouter est un allocateur de mémoire dynamique. Votre langue spécifie un espace d'adressage virtuel dédié spécial pour l'espace programme de l'utilisateur. Ceci est distinct de l'espace d'adressage utilisé par l'allocateur de mémoire pour tout état interne.
Pour réduire le coût de distribution de votre implémentation, la taille du code doit être aussi petite que possible.
Interface
Vous devez fournir trois fonctions: initialisation, allocation et désallocation.
Initialisation
Cette fonction prend un seul paramètre entier positif N
. Cela signifie que le programme d'un utilisateur a des N
octets dans son espace d'adressage à partir desquels il y a des N-1
octets pour allouer de la mémoire. L'adresse 0
est réservée à "null".
Il est garanti que cette fonction sera appelée exactement une fois avant tout appel d'allocation / désallocation.
Notez que cette fonction n'a pas besoin d'allouer de mémoire physique pour l'espace d'adressage virtuel du programme utilisateur; vous créez essentiellement le "look and feel" d'un allocateur de mémoire creux.
Allouer
La fonction d'allocation doit accepter une demande du nombre d'octets de mémoire à allouer. L'entrée est garantie positive.
Votre fonction doit renvoyer une adresse entière au début du bloc alloué, ou 0
pour indiquer qu'il n'y a pas de bloc contigu de la taille demandée disponible. Si un bloc contigu de la taille disponible est disponible n'importe où dans l'espace d'adressage, vous devez allouer!
Vous devez vous assurer qu'aucun deux blocs alloués ne se chevauchent.
Désallouer
La fonction de désallocation doit prendre une adresse du début d'un bloc alloué et peut également prendre la taille du bloc donné.
La mémoire qui a été désallouée est à nouveau disponible pour l'allocation. Il est supposé que l'adresse d'entrée est une adresse valide.
Exemple d'implémentation Python
Notez que vous pouvez choisir n'importe quelle méthode pour garder une trace de l'état interne; dans cet exemple, l'instance de classe en garde la trace.
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]
Notation
C'est le golf de code; le code le plus court en octets gagne. Vous n'avez pas à vous soucier de manquer de mémoire pour tout état interne requis par votre allocateur.
Des trous de boucle standard s'appliquent.
Classement
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 pourrait-il être efficace (petit et efficace ne sont pas les mêmes) que possible? : DRéponses:
Rubis, 80
Comme la réponse de MegaTom, mais utilise une chaîne au lieu d'un tableau pour stocker l'état. Le caractère "o" indique une cellule ouverte, tandis qu'un "f" indique une cellule remplie. Cela nous permet d'utiliser les fonctions de manipulation de chaînes relativement succinctes de Ruby:
?o*n
initialise une chaîne de n "o" s./\B#{?o*n}/
est une expression régulière correspondant à n "o" consécutifs qui n'inclut pas le premier caractère.sub!
remplace la première correspondance par n "f" s."#$`"
donne la chaîne à gauche de la correspondance, ou une chaîne vide s'il n'y avait pas de correspondance, donc la taille est soit l'index alloué, soit 0.La désallocation redéfinit simplement la section désignée de la chaîne sur "o".
la source
JavaScript (ES6), 88
Utiliser une variable globale
_
(un tableau très clairsemé) pour garder une trace.Maintenant, comment pourrais-je le tester?
la source
Rubis, 135
Dispose d'un tableau global pour savoir si chaque cellule est allouée ou non.
la source
Mathematica, 152
n
stocker la taille totale,l
stocke l'état interne. L'allocateur tentera d'allouer juste derrière une autre section de mémoire allouée.la source