Particionar una lista!

10

En este desafío, debe particionar una lista, donde las particiones tienen un tamaño máximo, un tamaño mínimo y un tamaño preferido. Usaré la notación (min,pref,max) para indicar los tamaños en este desafío.

Para aquellos que no están familiarizados con la partición, la siguiente lista se ha dividido en partes de 3:
[0..9] -> [[0,1,2],[3,4,5],[6,7,8]]

Cuando la lista no es divisible, necesita las particiones a estar tan cerca del tamaño preferido como sea posible: [0..10], (2,4,5) -> [[0,1,2,3],[4,5,6],[7,8,9]]. Es preferible esta partición [[0,1,2,3],[4,5,6,7],[8,9]], aunque esta última tenga más de la longitud preferida. Formalmente, necesitamos minimizar la suma de (partitionLength-preferredSize)^2cada partición.

El orden de las longitudes de las particiones no importa: para [0..5], (2,3,3), [[0,1,2],[3,4]]o [[0,1],[2,3,4]]funciona. Si ninguna partición es posible, devolver una matriz vacía: [0..7], (4,4,5) -> [].

Puede suponer eso 1<=min<=pref<=max, y que la matriz que le pasó es una matriz no entera de enteros. La matriz siempre será el primer argumento. Puede aceptar min, max y pref en cualquier orden y como una tupla o como argumentos separados.

Su programa debe ejecutarse en unos segundos. Básicamente, no se permite iterar a través de todos los tamaños de partición posibles dentro de los límites.

Casos de prueba:

[1], (1,3,4)         -> [[1]]
[100], (1,2,3)       -> [[100]]
[1,2], (1,1,2)       -> [[1],[2]]
[1,2], (1,2,2)       -> [[1,2]]
[1,2], (1,3,3)       -> [[1,2]]
[1,2,3], (1,2,3)     -> [[1,2],[3]] or [[1,2,3]]
[1,2,3,4], (1,3,4)   -> [[1,2,3,4]]
[1,2,3,4,5], (3,3,4) -> []
[1,2,3,4,5], (2,2,2) -> []
[1,2,3,4,5], (3,3,5) -> [[1,2,3,4,5]]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49], (2,6,6) -> [[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29],[30,31,32,33,34],[35,36,37,38,39],[40,41,42,43,44],[45,46,47,48,49]]

Este es un , ¡así que apunte a la menor cantidad de bytes posible en su idioma favorito!

Nathan Merrill
fuente
La notación que está utilizando [a..b]incluye ay excluye b, ¿correcto?
Alex A.
A inclusivo, B exclusivo.
Nathan Merrill
Tenga en cuenta que su interpretación de un no es lo mismo que una partición de la teoría de conjuntos ...
agtoever
Pero es efectivamente equivalente a la partición de enteros.
Nathan Merrill
¿Qué pasa si no hay solución?
feersum

Respuestas:

2

Haskell, 152

_%0=[]
s%k|(a,b)<-splitAt(div(z s)k)s=a:b%(k-1)
z=length
f s n p x=snd$minimum$(z s*p^2,[]):[(sum[(z x-p)^2|x<-s%k],s%k)|k<-[-div(-z s)x..div(z s)n]]

En cualquier partición, si hay dos listas que tienen longitudes que difieren en dos o más, siempre será beneficioso reducir la lista más grande y ampliar la lista más pequeña. por lo tanto, solo necesitamos considerar particiones con solo dos tamaños de lista, lo que simplifica el cálculo.

el programa se ejecuta en todas las cantidades posibles de listas en la partición. Dada la cantidad de listas en la partición, la puntuación se determina de forma única. el programa calcula una partición de ajuste y su puntaje.

luego encuentra el mínimo general y lo devuelve.

Uso: entrada como f [1,2,3,4,5] 1 3 4( fes la función que resuelve el desafío)

Aunque es posible calcular la mejor opción completamente numéricamente y solo luego particionar la lista en consecuencia, tomó demasiados bytes. Sin embargo, mi última versión de este enfoque es:

_%0=[]
s%k|(a,b)<-splitAt(div(length s)k)s=a:b%(k-1)
f s n p x|l<-length s=(s%)$snd$minimum$(l*p^2,0):[(k*j^2+mod l k*(1-2*j),k)|k<-[1..div l n],k*x>=l,j<-[p-div l k]]
orgulloso Haskeller
fuente
1

CJam, 70

q~:S;_,[0L]a{_S2=e<),S0=>f{[__S1=-_*\]@@-j.+}[esL]a+:e<}j1={/(\e_}/;]p

Pruébalo en línea

El código encuentra una secuencia óptima de tamaños de partición en función del tamaño de la lista, mediante la programación dinámica (a través de la recursión memorizada), luego continúa y divide la lista.

aditsu renunció porque SE es MALO
fuente