数字的排序词法分区


17

挑战非常简单:给定一个数字,将其数字拆分为一个较小数字的数组,以使结果数字不变。要注意的是,您必须将其拆分为最大数组长度。

困惑?

  • 您可以通过STDIN(或最接近的替代方法),命令行参数或函数参数以任何方便,明确的输入格式为您提供正整数。
  • 您必须将数字的十进制数字划分为连续的,不相交的组。
  • 这些数字组代表的数字数组应排序(按通常的,不递减的顺序),而无需重新排列组
  • 如果存在多个这样的分区,则必须将输入划分为尽可能多的数字。如果是平局,则返回一个这样的结果。
  • 您可以将数组输出到STDOUT(或最接近的替代品)或作为函数返回值。如果是STDOUT(或最接近的替代产品),则应以任何方便,明确的列表格式打印阵列。
  • 分割数不应包含前导零。因此,例如1002003,不能将其打印为[1, 002, 003][1, 2, 3],并且唯一有效的答案是[100, 2003]

测试用例:

123456 -> [1, 2, 3, 4, 5, 6]
345823 -> [3, 4, 5, 8, 23]
12345678901234567890 -> [1, 2, 3, 4, 5, 6, 7, 8, 90, 123, 456, 7890]
102 -> [102]
302 -> [302]
324142 -> [3, 24, 142] OR [32, 41, 42]
324142434445 -> [32, 41, 42, 43, 44, 45]
1356531 -> [1, 3, 5, 6, 531]
11121111111 -> [1, 1, 1, 2, 11, 11, 111]
100202003 -> [100, 202003]

计分

这是代码高尔夫球,因此以字节为单位的最短代码获胜。

Answers:


10

珀斯,34岁

FNyUz#aYmv:zhdedC,+0N+NlzB)efqSTTY

在这里在线尝试。注意,这具有O(n)的时间(和空间)复杂度。因此测试用例12345678901234567890在在线编译器中花费的时间太长。请改用离线版本(在笔记本电脑上为1分钟)。

这只是我的第一次尝试。可能还有一些改进的空间。

首先,我的算法是如何工作的。

  • 我将输入解释为字符串而不是数字。
  • 然后,我创建所有可能的子集 [0, 1, 2, ..., len(n-1)]
  • 对于每个这些子集(让我们取[1, 4, 5]),我使用这些数字将输入字符串分成了一部分。[input[0:1], input[1, 4], input[4,5], input[5,len(input)]]
  • 之后,我尝试将这些数字转换为字符串。可能有两个问题。Pyth(或Python)针对空字符串以及以开头的数字字符串引发异常0。因此我使用try - catch块(实际上是带有立即中断的无限循环)。如果转换成功,则将结果添加到list中Y
  • 处理完所有子集后,我Y将为已排序的结果筛选列表,并打印最后一个(最后一个具有最多的组)。

现在详细说明:

                            Implicit: z = input() (z is a String!)
                                      Y = empty list
FNyUz                       for each subset N of [0, 1, 2, ..., len(z)-1]:

     #                         start try-catch block (actually an infinite loop, 
                               but the Python implementation uses a try catch. 

      aY                          append to Y:
                C,+0N+Nlz            zip([0] + N, N + [len(z)])
        m                            map each element d to
          :zhded                     z[d[0]:d[-1]]
         v                           evaluated
                         B        if this didn't throw an exception already, end the infinite loop
                          ) end for loop   

 f    Y      filter Y for elements T, for which
  qSTT           sorted(T) == T
e            and print the last one (the subsets generated with yUz are sorted 
             by length, so the last one has the most groups)

您可以使用aY,而不是~Y]
FryAmTheEggman

@FryAmTheEggman我总是忘了a。不知道为什么。
2015年

@Jakube也许是因为它不在文档中?
Sp3000

我有〜45个字符的解决方案。我不知道int("01")在Pyth中有错误(在Python中不会发生)。
2015年

3
@Jakube哈哈,虽然看起来合乎逻辑,但通常n是输入的长度。
Optimizer

6

Mathematica,134 127字节

这是非常低效的,因为它会产生一个很大比有效问卷更多的分区。该324142434445测试案例在几秒钟内运行,但我不会尝试12345678901234567890

f/@Last@Select[Needs@"Combinatorica`";f=FromDigits;SetPartitions[d=IntegerDigits@#],0<=##&@@f/@#&&Join@@#==d&&#~FreeQ~{0,__}&]&

这定义了一个未命名函数,该函数采用一个整数并返回一个整数列表。

说明

这段代码的读取顺序到处都是,所以我将按照预期的读取顺序进行分解(并在大多数情况下进行评估):

  • d=IntegerDigits@#获取输入的十进制数字,并将此列表分配给d
  • SetPartitions(这需要Needs@"Combinatorica`";)给了我所有的分区。但是,由于它将输入视为set,因此返回的值比我实际想要的要多得多。这就是使它效率低下的原因,但是我正在使用它,因为我知道获取所有列表分区的最短方法要长得多。例如,如果列表是{1, 2, 3}该函数,则将返回:

    {{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 2}, {3}}, {{1, 3}, {2}}, {{1}, {2}, {3}}}
    

    请注意,a)连续的分区都按正确的顺序排列,b)分区从最粗到最细排序。

  • Select[...,...&] 然后通过作为第二个参数传入的匿名函数过滤此列表。
    • Join @@ # == d 检查我们实际上是否具有列表分区,而不是常规集合分区。
    • #~FreeQ~{0, __} 检查是否没有分区以前导零开头。
    • 0 <= ## & @@ f /@ #有点晦涩。首先,我们映射FromDigits到分区中的每个列表以恢复由数字表示的数字。然后,我们将0 <= ##这些数字##应用于所有数字。如果分区是,{1, 23, 45}则扩展为0 <= 1 <= 23 <= 45,因此它检查数组是否已排序。
  • Last@ 然后给我过滤后剩下的最后一个分区-之所以有效,是因为 SetPartitions已经对分区进行了排序,使得最好的分区在最后。
  • 最后,f/@从数字列表中恢复数字。

5

Python 3,134个字节

def f(s,n=0,L=[],R=[],i=0):
 while s[i:]:i+=1;m=int(s[:i]);R=max([f(s[i:],m,L+[m]),R][m<n or"1">s[i:]>"":],key=len)
 return[L,R][s>""]

有点混乱,但是哦。该程序只是递归地生成所有有效分区。有趣的部分是,不允许前导零,所有必要的是附加or "1">s[i:]>""条件。

接受类似的输入f("12345678901234567890")并返回一个整数列表。


4

Pyth, 62 61 60

JlzKkef&qJsml`dTqTSTolNmmibTcjKsC,z+m>Ndt>+*J]0jk2_JKNU^2-J1

说明

该算法通过生成介于0(包含)和2^(n-1)(不含)之间的所有二进制数来工作,其中n输入长度。

然后将每个的二进制数字映射到1的分隔符(N),而0 则不映射。

然后,将这些字符插入每个输入字符之间,然后将结果除以N,得到一个列表。

然后将列表中的值解析为整数,然后按长度对列表进行排序。然后剩下的就是过滤掉未排序的那些和已在前导零处分割的那些,然后选择最长的列表。

Jlz                                                   set J to len(input)
Kk                                                    set K to ""
e                                                     take the last of:
 f&                                                    only take lists where:
   qJsml`dT                                             sum of string lengths of items
                                                        is equal to length of input and
           qTST                                         list is in order
               olN                                       sort by length
                  m                                       map k over...
                   mibT                                    convert items to int (base-10)
                       c                        N           split by N
                        jK                                   join by ""
                          s                                   sum to combine tuples
                           C,z                                 zip input with
                              +                K                append [""] for equal lengths
                               m>Nd                              replace 1 with N, 0 with ""
                                   t                              take all but first
                                    >        _J                    take len(input) last values
                                     +                              pad front of binary with
                                      *J]0                           [0] times input's length
                                          jk2                        current k in binary
                                                 U^2-J1  range 0..2^(len(input)-1)-1

1

(非竞争)Pyth,25个字节

ef&&Fmnhd\0T.A<V=NsMTtN./

在线尝试!

怎么运行的:

ef&&Fmnhd\0T.A<V=NsMTtN./  Q = eval(input())
                         ./  all partitions of Q
 f                       ./  filter all partitions of Q where:
  &                            both:
   &Fmnhd\0T                     neither substring starts with "0"
                               and:
            .A<V=NsMTtN          all entries are less than their proceeding ones
e                            returns the last amongst the filtered partitions

0

J,109个字节

很长,但至少要占用O(n *(2n)!)内存和O(n * log(n)*(2n)!)时间,其中n是输入的长度。(因此,请勿尝试使用超过5位的数字来运行它。)

f=.3 :0
>({~(i.>./)@:(((-:/:~)@(#$])*#)@>))<@".(' 0';' _1')rplc"1~(#~y-:"1' '-."#:~])(i.!2*#y)A.y,' '#~#y
)

该函数将输入作为字符串。

例子:

   f every '5423';'103';'1023'
  5 423
103   0
 10  23

方法:

  • 在输入中添加与其长度相同的空格。
  • 以各种可能的方式对其进行置换。
  • 检查无空格字符串是否与输入相同(即它的一部分)。
  • 将“ 0”替换为“ _1”以使前导零解无效。
  • 评估每个字符串。
  • 找到最长的列表,该列表也已排序。这是返回值。

0

Haskell,161字节

(#)=map
f[x]=[[[x]]]
f(h:t)=([h]:)#f t++(\(a:b)->(h:a):b)#f t
g l=snd$maximum[(length x,x::[Int])|x<-[read#y|y<-f l,all((/='0').head)y],and$zipWith(>=)=<<tail$x]

测试运行:

*Main> mapM_ (print . g) ["123456","345823","12345678901234567890","102","302","324142","324142434445","1356531","11121111111","100202003"]
[1,2,3,4,5,6]
[3,4,5,8,23]
[1,2,3,4,5,6,7,8,90,123,456,7890]
[102]
[302]
[32,41,42]
[32,41,42,43,44,45]
[1,3,5,6,531]
[1,1,1,2,11,11,111]
[100,202003]

工作原理:辅助函数f将输入列表拆分为每个可能的子列表列表。g首先丢弃那些以子列表开头的子列表0,然后丢弃那些顺序不正确的子列表。将每个剩余列表与其长度配对,取最大并再次丢弃长度部分。

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.