Está diseñando un nuevo lenguaje de programación esotérico y una característica que ha decidido agregar es un asignador dinámico de memoria. Su idioma especifica un espacio de dirección virtual dedicado especial para el espacio del programa del usuario. Esto es independiente del espacio de direcciones utilizado por el asignador de memoria para cualquier estado interno.
Para ayudar a reducir el costo de distribuir su implementación, el tamaño del código debe ser lo más pequeño posible.
Interfaz
Debe proporcionar tres funciones: inicialización, asignación y desasignación.
Inicialización
Esta función toma un único parámetro entero positivo N. Esto significa que el programa de un usuario tiene Nbytes en su espacio de direcciones desde los cuales hay N-1bytes para asignar memoria. La dirección 0está reservada para "nulo".
Se garantiza que esta función se invocará exactamente una vez antes de cualquier llamada de asignación / desasignación.
Tenga en cuenta que esta función no necesita asignar ninguna memoria física para el espacio de direcciones virtuales del programa de usuario; básicamente está creando la "apariencia" de un asignador de memoria hueca.
Asignar
La función de asignación debe tomar una solicitud del número de bytes de memoria para asignar. La entrada está garantizada para ser positiva.
Su función debe devolver una dirección entera al comienzo del bloque asignado, o 0para indicar que no hay un bloque contiguo del tamaño solicitado disponible. ¡Si un bloque contiguo del tamaño disponible está disponible en cualquier parte del espacio de direcciones, debe asignarlo!
Debe asegurarse de que no se superpongan dos bloques asignados.
Desasignar
La función de desasignación debe tomar una dirección del inicio de un bloque asignado y, opcionalmente, también puede tomar el tamaño del bloque dado.
La memoria que se ha desasignado está disponible nuevamente para asignación. Se supone que la dirección de entrada es una dirección válida.
Ejemplo de implementación de Python
Tenga en cuenta que puede elegir cualquier método para realizar un seguimiento del estado interno; en este ejemplo, la instancia de clase lo rastrea.
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]
Puntuación
Este es el código de golf; el código más corto en bytes gana. No necesita preocuparse por quedarse sin memoria para cualquier estado interno requerido por su asignador.
Se aplican agujeros de bucle estándar.
Tabla de clasificación
To help reduce the cost of distributing your implementation the size of the code must be as small as possibleo podría ser eficiente (pequeño y eficiente no son lo mismo) como sea posible? : D