# 切割金链

32

• n是大于0的整数。
• 您可以对链接使用基于0或基于1的索引。
• 对于某些数字，解决方案不是唯一的。例如，如果n = 15两个[3, 8][4, 8]是有效的输出。
• 您可以返回列表，也可以使用任何合理的分隔符进行打印。
• 这是，因此以字节为单位的最短代码获胜。

Input          Output (1-indexed)
1              []
3              [1]
7              [3]
15             [3, 8]
149            [6, 17, 38, 79]


 1 = 1
2 = 2
3 = 1+2
4 = 4
5 = 1+4
6 = 2+4
7 = 7
8 = 1+7
9 = 2+7
10 = 1+2+7
11 = 4+7
12 = 1+4+7
13 = 2+4+7
14 = 1+2+4+7
15 = 1+1+2+4+7


6

4
@Flater经理已经有了它。我们只需支付额外的费用。实际上，RHS是经理每天拥有的链接
polfosolఠ_ఠ

15

# 05AB1E，23 11 8字节

ΔÍN-;иg=


### 说明：

             # start from the implicit input
Δ            # loop forever
Í           # subtract 2
N-         # subtract the current iteration number
;        # divide by 2
и       # create a list of length x
g      # get the length of the list
=     # print


иg看起来像一个noop，但实际上它做两件事：将其截断为整数（;返回浮点数），如果x为负（这是唯一的退出条件），它将使解释器崩溃。

23字节的解决方案使用了一种非常不同的方法，因此这里是为后代使用的ÅœʒR2äθP}ʒæOê¥P}θ2äθη€OTIO说明）。

2

2
@KevinCruijssen Nnope，Ø.Ø实际上是我的第一个想法。您的评论促使我尝试随机的东西：我发现®Ÿàï®M以及更重要的是иg，这将产生这个漂亮的8 byter。我总是感到很讨厌，在很多情况下（比分是0，错误的类型等），osabie宁愿不执行任何操作而不是崩溃，因此此崩溃将派上用场。
Grimmy

2

2
“如果x为负（这是唯一的退出条件），则破坏解释器。” -我喜欢
John Dvorak

9

# Python 2，75个字节

f=lambda n,i=0:n>=i<<i and f(n,i+1)or[min(n,2**j*i-i+j)for j in range(1,i)]

### 说明：

63 可以进行3次切割，这意味着在base-4中进行分区（因为我们有3个单环）：

1       1
2       1 1
3       1 1 1
4       4
...
42      1 1 8 32
...
62      1 1 4 8 16 32
63      1 1 1 4 8 16 32

18: 4,11        ->  3 1 6 1 7
27: 5,14,27     ->  4 1 8 1 13 1
36: 5,14,31     ->  4 1 8 1 16 1 5
86: 6,17,38,79  ->  5 1 10 1 20 1 40 1 7

1

randomdude999

@ randomdude999，是的，我忘了...
TF场

@ randomdude999该规则适用于所有语言还是仅适用于python？因为我在这个挑战中看到一个纯正的lambda的javascript答案

3
TF场

1
@Shadow一个更通用的规则是，除非挑战明确允许，否则您不能引用代码中未定义或语言中未全局定义的内容。最常见的情况是递归函数，但这适用于其他情况。这个答案是另一个例子：f不是递归的，但是在代码中引用了它，因此必须命名。
Arnauld

8

# R，77 69字节

-8字节归功于Aaron Hayman

pmin(n<-scan(),0:(k=sum((a=2:n)*2^a<=n))+cumsum((k+2)*2^(0:k))+1)[-n]

$$kķk$$$$ķķk$$ 是最小整数，使得 $$（ķ + 1 ）⋅ 2ķ≥ ñ（ķ+1个）⋅2ķ≥ñ(k+1)\cdot2^k\geq n$$。确实，然后可能的解决方案是拥有一定长度的子链$$1 ，1 ，... ，11个，1个，…，1个1,1,\ldots,1$$$$ķķk$$ 次）和 $$（ķ + 1 ），2 （ķ + 1 ），4 （ķ + 1 ），8 （ķ + 1 ），... ，（ķ + 1 ）⋅ 2k − 1（ķ+1个），2（ķ+1个），4（ķ+1个），8（ķ+1个），…，（ķ+1个）⋅2ķ-1个(k+1), 2(k+1), 4(k+1), 8(k+1), \ldots, (k+1)\cdot 2^{k-1}$$。可以很容易地检查出它是否足够且最佳。

（如果我们超过了链的总长度，则可能需要缩短最后一个子链。）

Ungolfed（基于以前的类似版本）：

n = scan()                            # read input
if(n - 1){                            # If n==1, return NULL
k = match(F, (a = 2:n) * 2 ^ a > n) # compute k
b = (k + 1) * 2 ^ (1:k - 1)         # lengths of subchains
c = 1:k + cumsum(b)                 # positions of cuts
pmin(c, n )                         # if last value is >n, coerce it to n
}

(Proof that the value of $$kkk$$ is as I state: suppose we have $$kkk$$ cuts. We then have $$kkk$$ unit subchains, so we need the first subchain to be of length $$k+1k+1k+1$$. We can now handle all lengths up to $$2k+12k+12k+1$$, so we need the next one to be of length $$2k+22k+22k+2$$, then $$4k+44k+44k+4$$... Thus the maximum we can get out of $$kkk$$ cuts is obtained by summing all those lengths, which gives $$(k+1)⋅2k−1(k+1)⋅2k−1(k+1)\cdot 2^k-1$$.)

If $$a(k)a(k)a(k)$$ is the smallest integer $$nnn$$ requiring $$kkk$$ cuts, then $$a(k)a(k)a(k)$$ is OEIS A134401.

I doubt it would help with the special case for n=1, but an alternative way to generate the cutoffs is the recurrence 1, 4, 4a(n-1)-4a(n-2).
Peter Taylor

@PeterTaylor I had a similar recurrence for computing k; this corresponds to OEIS A134401: oeis.org/A134401 But my implementation of the recurrence relation takes up more bytes than the current code.
Robin Ryder

A bit of rearrangement I got it down to 73. Try it online!
Aaron Hayman

@AaronHayman Thanks! Smart move using sum instead of match.
Robin Ryder

69 bytes and got rid of that if statement that was upsetting you: Try it online!
Aaron Hayman

3

# Jelly, 12 bytes

’_‘ɼ:2»-µƬṖḊ


Try it online!

Translation of Grimy's 05AB1E answer so be sure to upvote that one too! Slightly disappointed this comes in a byte longer, but does at least have something a bit like an emoticon as the first three bytes!

2

# JavaScript (ES6), 66 bytes

This is a port of TFeld's answer.

n=>(g=a=>n<++i<<i?a.map(j=>(j+=(i<<j)-i)>n?n:j):g([...a,i]))(i=[])

Try it online!

2

# C++, 109,107 bytes

-2 bytes thanks to Kevin

#include<iostream>
main(){int n,k=0;for(std::cin>>n;++k<<k<n;);for(n-=k;n>0;k*=2,n-=k+1)std::cout<<n<<',';}


The algorithm is similar to the Robin Ryder's answer. The code is written in a compilable, whole form. Try it!

Details:

std::cin>>n;               // get the value of n as input
while(++k<<k<n);           // determine k
for(n-=k;n>0;k*=2,n-=k+1)  // we don't need n, so the lengths...
std::cout<<n<<' ';     // of links are subtracted repeatedly


This has a C variation with the same byte length (doesn't seem to need a separate answer):

#include<stdio.h>
main(){int n,k=0;for(scanf("%d",&n);++k<<k<n;);for(n-=k;n>0;k*=2,n-=k+1)printf("%d,",n);}


Two minor things to golf: =0 after k can be removed, since its 0 by default. std::cin>>n;while(++k<<k<n); can be for(std::cin>>n;++k<<k<n;);. I also have the feeling for(n-=k;n>0;k*=2,n-=k+1) can be simplified somehow by combining stuff, but not sure how. PS: Changing the comma-delimiter to a space looks slightly better since you don't see the trailing one imo, but this is purely cosmetic :)
Kevin Cruijssen

1
@KevinCruijssen Thanks, but some compilers don't assign a default value to non-static variables. So I thought =0 was necessary for portability ;) I also realized that the space after #include is not necessary.
polfosol ఠ_ఠ

Ah ok. I don't know C++ too well, so I've used that online compiler you linked in your answer to test some things. :) You forgot the second change I proposed in my comment: the while-loop to a for-loop and putting the std::cin>>n inside it.
Kevin Cruijssen

1

# Retina 0.8.2, 61 bytes

.+
11,$&$*
+\b(1+),(\1(1*)1?\3)$1$2¶1$1,$3
1+,
1
1A
1+
$.&  Try it online! 1-indexed port of @Grimy's answer. Explanation: .+ 11,$&$*  Start with N=2 and the input converted to unary. +\b(1+),(\1(1*)1?\3)$


Repeatedly try to subtract N from the input and then divide by 2.

1$2¶1$1,$3  如果成功，请记住比上一行输入多1，N在当前行上递增，然后将输入更新为新值。 1+, 1  删除N并增加最后一个值，使其也为1索引。 1A  删除增加的原始输入。 1+$.&


1

# 红宝石，62字节

->n{(1...c=(0..n).find{|r|n<r<<r}).map{|b|[n,b-c+(c<<b)].min}}