分区列表!


10

在此挑战中,您需要对列表进行分区,其中分区具有最大大小,最小大小和首选大小。我将使用该符号(min,pref,max) 来表示此挑战中的大小。

对于不熟悉分区的人,以下列表已分为三部分:
[0..9] -> [[0,1,2],[3,4,5],[6,7,8]]

当列表不能被均等分割时,您需要使分区尽可能地接近首选大小:[0..10], (2,4,5) -> [[0,1,2,3],[4,5,6],[7,8,9]][[0,1,2,3],[4,5,6,7],[8,9]]即使该分区具有更多的首选长度,该分区也比首选。正式地,我们需要最小化(partitionLength-preferredSize)^2每个分区的总和。

分区长度的顺序无关紧要:对于[0..5], (2,3,3)[[0,1,2],[3,4]]或者[[0,1],[2,3,4]]有效。如果没有分区,则返回一个空数组:[0..7], (4,4,5) -> []

您可以假定1<=min<=pref<=max,并且传递给您的数组是一个非空的整数数组。数组将始终是第一个参数。您可以以任何顺序,以元组或单独的参数接受min,max和pref。

您的程序必须在几秒钟内运行。基本上,不允许在边界内遍历所有可能的分区大小。

测试用例:

[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]]

这是一个,因此,请以您喜欢的语言尽可能少的字节为目标!


您所使用的符号[a..b]包括a和排除b,对吗?
Alex A.

A包含式,B排除式。
内森·美林

请注意,您对a的解释与集合论划分不同 ……
敏捷

但它有效地等同于整数分割。
内森·梅里尔

如果没有解决方案怎么办?
feersum

Answers:


2

哈斯克尔(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]]

在任何分区中,如果有两个长度相差两个或多个的列表,则缩小较大的列表并放大较小的列表将总是有益的。因此,我们只需要考虑只有两个列表大小的分区,从而简化了计算。

然后,程序将在分区中所有可能的列表数量上运行。给定分区中列表的数量,分数是唯一确定的。程序将计算一个合适的分区及其得分。

然后找到总最小值,然后将其返回。

用法:输入类似f [1,2,3,4,5] 1 3 4f是解决挑战的函数)

尽管可以通过数字方式计算出最佳选项,然后才对列表进行分区,但它占用了太多字节。但是,这种方法的最新版本是:

_%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]]

1

CJam,70岁

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

在线尝试

该代码使用动态编程(通过记忆式递归)根据列表大小找到最佳的分区大小序列,然后继续对列表进行分区。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.