拆分位!


17

我们定义作为鲜明的权力清单2那笔X。例如,V 35 = [ 32 2 1 ]V(x)2xV(35)=[32,2,1]

按照惯例,此处的权力从最高到最低排序。但这不会影响挑战的逻辑,也不会影响预期的解决方案。

任务

给定一个半素数 ,将V N )中的每个项替换为另一个与该项加和的2的幂的列表,这样所有结果子列表的并集就是矩阵M的精确覆盖,定义为:NV(N)2M

Mi,j=V(P)i×V(Q)j

其中QN的素数。PQN

通过一些示例,这更容易理解。

例子1

对于,我们有:N=21

  • V(N)=[16,4,1]
  • V P = [ 4 2 1 ]P=7V(P)=[4,2,1]
  • V Q = [ 2 1 ]Q=3V(Q)=[2,1]
  • M=(842421)

要将变成M的精确覆盖,我们可以将16分成8 + 4 + 44分成2 + 2,而1保持不变。因此,可能的输出是:V(N)M168+4+442+21

[[8,4,4],[2,2],[1]]

另一个有效的输出是:

[[8,4,2,2],[4],[1]]

范例#2

对于,我们有:N=851

  • V(N)=[512,256,64,16,2,1]
  • V P = [ 32 4 1 ]P=37V(P)=[32,4,1]
  • V Q = [ 16 4 2 1 ]Q=23V(Q)=[16,4,2,1]
  • M=(512641612816464823241)

可能的输出是:

[[512],[128,64,64],[32,16,16],[8,4,4],[2],[1]]

规则

  • 因为将分解不是挑战的主要部分,所以您可以交替使用PQ作为输入。NPQ
  • 当存在几种可能的解决方案时,您可以只返回其中之一,也可以全部返回。
  • 你可以交替地返回功率的指数(例如,,而不是[ [ 8 4 4 ] [ 2 2 ] [ 1 ] ])。[[3,2,2],[1,1],[0]][[8,4,4],[2,2],[1]]
  • 子列表的顺序无关紧要,每个子列表中术语的顺序也无关紧要。
  • 对于某些半素数,您无需拆分任何项,因为已经是M的完美覆盖(请参阅A235040)。但是您仍然必须返回(单例)列表的列表,例如[ [ 8 ] [ 4 ] [ 2 ] [ 1 ] ]N = 15V(N)M[[8],[4],[2],[1]]N=15
  • 这是

测试用例

 Input | Possible output
-------+-----------------------------------------------------------------------------
 9     | [ [ 4, 2, 2 ], [ 1 ] ]
 15    | [ [ 8 ], [ 4 ], [ 2 ], [ 1 ] ]
 21    | [ [ 8, 4, 4 ], [ 2, 2 ], [ 1 ] ]
 51    | [ [ 32 ], [ 16 ], [ 2 ], [ 1 ] ]
 129   | [ [ 64, 32, 16, 8, 4, 2, 2 ], [ 1 ] ]
 159   | [ [ 64, 32, 32 ], [ 16 ], [ 8 ], [ 4 ], [ 2 ], [ 1 ] ]
 161   | [ [ 64, 32, 16, 16 ], [ 8, 8, 4, 4, 4, 2, 2 ], [ 1 ] ]
 201   | [ [ 128 ], [ 64 ], [ 4, 2, 2 ], [ 1 ] ]
 403   | [ [ 128, 64, 64 ], [ 32, 32, 16, 16, 16, 8, 8 ], [ 8, 4, 4 ], [ 2 ], [ 1 ] ]
 851   | [ [ 512 ], [ 128, 64, 64 ], [ 32, 16, 16 ], [ 8, 4, 4 ], [ 2 ], [ 1 ] ]
 2307  | [ [ 1024, 512, 512 ], [ 256 ], [ 2 ], [ 1 ] ]

我们可以取P和Q代替N吗?
ngn

@ngn我要说是,因为分解N不是挑战的主要部分。
Arnauld

1
我们可以将输出展平吗?
暴民埃里克(Erik the Outgolfer)'18年

@EriktheOutgolfer ...展平的输出只是输入的一部分(例如1 + 2 + 2 + 4 = 9)。我不认为它应该被允许
Xcoder先生

@EriktheOutgolfer我不认为这种方式可能是明确的,因为子列表的最后一项可能与下一列表的第一项相同。
Arnauld

Answers:


4

K(ngn / k)66 63字节

{(&1,-1_~^(+\*|a)?+\b)_b:b@>b:,/*/:/2#a:{|*/'(&|2\x)#'2}'x,*/x}

在线尝试!

接受(P; Q)而不是N

算法:

  • 计算A作为V(P * Q)的部分和

  • 将每个V(P)与每个V(Q)相乘,以降序对乘积进行排序(我们称其为R),并计算其部分和B

  • 找出在A中也出现的B中那些元素的位置;在这些位置之后立即切R


3

果冻,24 字节

BṚT’2*
Ç€×þ/FṢŒṖ§⁼Ç}ɗƇPḢ

一个接受两个整数的列表的单子链接,[P, Q]这将产生一个可能的列表列表,如问题中所述。

在线尝试!(页脚打印一个字符串表示形式,以显示列表的真实含义)

或查看测试套件(获取N的列表并重新排列结果以使其与问题中的结果相似)

怎么样?

我们可以总是向上切片的元素从最低起来,贪婪地(无论是有1中号或我们不得不的输入4,当中号= [ [ 4 ] ]),以便找到一个解决方案。中号1个中号4中号=[[4]]

注意:该代码将所有(一个!)这样的解决方案收集在一个列表中,然后获取(仅)结果的开头-即最终的标题是必需的,因为分区并不是所有可能的排序。

BṚT’2* - Link 1, powers of 2 that sum to N: integer, N    e.g. 105
B      - binary                                                [1,1,0,1,0,0,1]
 Ṛ     - reverse                                               [1,0,0,1,0,1,1]
  T    - truthy indices                                        [1,4,6,7]
   ’   - decrement                                             [0,3,5,6]
    2  - literal two                                           2
     * - exponentiate                                          [1,8,32,64]

Ç€×þ/FṢŒṖ§⁼Ç}ɗƇPḢ - Main Link: list of two integers, [P,Q]
Ç€                - call last Link (1) as a monad for €ach
    /             - reduce with:
   þ              -   table with:
  ×               -     multiplication
     F            - flatten
      Ṣ           - sort
       ŒṖ         - all partitions
              Ƈ   - filter keep if:
             ɗ    -   last three links as a dyad:
         §        -     sum each
            }     -     use right...
               P  -       ...value: product (i.e. P×Q)
           Ç      -       ...do: call last Link (1) as a monad
          ⁼       -     equal? (non-vectorising so "all equal?")
                Ḣ - head

3

Python 2中261个 233 232 231字节

g=lambda n,r=[],i=1:n and g(n/2,[i]*(n&1)+r,i*2)or r
def f(p,q):
 V=[[v]for v in g(p*q)];i=j=0
 for m in sorted(-a*b for a in g(p)for b in g(q)):
	v=V[i]
	while-m<v[j]:v[j:j+1]=[v[j]/2]*2
	i,j=[i+1,i,0,j+1][j+1<len(v)::2]
 return V

在线尝试!

Jo King 1个字节; 和另外1个字节,归因于Kevin Cruijssen

作为输入p,q。追求贪婪算法。


-k-1可以~k
乔纳森·弗雷希

i,j分配可i,j=[i+1,i,0,j+1][j+1<len(v)::2]为-1字节
乔金

@乔金:哈哈哈!那是扭曲的!
Chas Brown

while v[j]>-m可能是while-m<v[j]
Kevin Cruijssen

@Kevin Cruijssen:是的,的确如此。谢谢!
查斯·布朗

2

果冻,41个字节

Œṗl2ĊƑ$Ƈ
PÇIP$ƇṪÇ€Œpµ³ÇIP$ƇṪƊ€ŒpZPṢ⁼FṢ$µƇ

在线尝试!

可能应该短得多(某些零件感觉非常重复;尤其是ÇIP$Ƈ,但我不知道如何打高尔夫球)。进一步打高尔夫球后再作解释。如果存在多个,则返回所有可能的解决方案,并将输入作为[P]


并不是说这是一个问题,但这不是很快,不是吗?:)
Arnauld

@Arnauld它在一次运行中使用大约3个整数分区函数:)当然,它不是太快
Xcoder先生,18年

现在正在等待被淘汰。我认为在
35/30以下级别

2

果冻,34个字节

BṚT’2*
PÇŒṗæḟ2⁼ƊƇ€ŒpẎṢ⁼Ṣ}ʋƇÇ€×þ/ẎƊ

在线尝试!

输入格式:([P, Q]上面的TIO链接不接受此格式,而是接受一个数字,以帮助测试用例)。

输出格式:所有解决方案的列表(显示为TIO上3D列表的网格表示)。

速度:乌龟。



1

哈斯克尔,281个 195字节

import Data.List
r=reverse.sort
n#0=[]
n#x=[id,(n:)]!!mod x 2$(n*2)#div x 2
m!0=[]
m!x=m!!0:tail m!(x-m!!0)
m%[]=[]
m%n=m!head n:drop(length$m!head n)m%tail n
p&q=r[x*y|x<-1#p,y<-1#q]%r(1#(p*q))

1
这里有一些技巧:定义运算符而不是二进制函数会更便宜,重新排列防护和模式匹配可以节省您的时间(==),可以使用1>0代替True和不使用where。也n'可以缩短。。这样可以节省72个字节:在线尝试!
ბიმო

顺便说一句。如果您还没有,请查看Haskell提示部分。
ბიმო

我又看了看守的情况,还掉了13个字节:在线试用!
ბიმო

@OMᗺ,谢谢。我是新来的Haskell,所以这看起来对我来说魔术
ЕвгенийНовиков

不用担心:)如果您有任何疑问,请随时在《单子和男人》中提问
ბიმო
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.