挑战
给定一个正整数,返回其总和为给定整数的连续正奇数整数的最长序列。如果不存在这样的序列,则您可能会以对您的语言有意义的任何方式报告错误,包括返回虚假值或引发异常。
测试用例
1-> [1] 2-> [] 3-> [3] 4-> [1,3] 5-> [5] 6-> [] 9-> [1、3、5](请注意,[9]不是有效答案) 15-> [3,5,7] 104-> [23,25,27,29](请注意,[51,53]不是有效答案)
计分
这是代码高尔夫球,因此每种语言中最短的答案将获胜。
给定一个正整数,返回其总和为给定整数的连续正奇数整数的最长序列。如果不存在这样的序列,则您可能会以对您的语言有意义的任何方式报告错误,包括返回虚假值或引发异常。
1-> [1] 2-> [] 3-> [3] 4-> [1,3] 5-> [5] 6-> [] 9-> [1、3、5](请注意,[9]不是有效答案) 15-> [3,5,7] 104-> [23,25,27,29](请注意,[51,53]不是有效答案)
这是代码高尔夫球,因此每种语言中最短的答案将获胜。
Answers:
由于朱利安·沃尔夫节省了4个字节
f x=[[2*n+1,2*n+3..2*m]|n<-[0..x],m<-[n..x],m^2-n^2==x]!!0
我检查数字是否可以表示为他的两个平方的差:m^2-n^2
。然后,我可以构造连续的奇数列表:[2n+1,2n+3...2m-1]
。请注意,因为n
选择了最小值,所以将输出最长的列表
x
两者都加起来就可以节省4个字节,n
并且m
感谢丹尼斯-1字节(使用Ẇ
-替换Rm2Ẇ
为的隐式范围构建ẆḤ’
)
ẆḤ’S_¥Ðḟ⁸Ṫ
一个单子链接,如果可能,0
则返回被加数的列表。
ẆḤ’S_¥Ðḟ⁸Ṫ - Link: number, n
Ẇ - all sublists (implicit range of input) note: ordered by increasing length
- i.e. [[1], [2], [3], ..., [1,2], [2,3], ..., [1,2,3], ...]]
Ḥ - double [[2], [4], [6], ..., [2,4], [4,6], ..., [2,4,6], ...]]
’ - decrement [[1], [3], [5], ..., [1,3], [3,5], ..., [1,2,5], ...]]
⁸ - link's left argument, n
Ðḟ - filter out items for which the following yields a truthy value:
¥ - last two links as a dyad:
S - sum
_ - subtract the right from the left = sum - n
Ṫ - tail (last and hence longest such run)
ẆḤ’
保存一个字节。
返回以逗号分隔的整数列表,或者0
如果不存在任何解决方案。
n=>(g=(s,k,x=n+s)=>(x**.5|0)**2-x?k>n?0:g(s+k,k+2):(n-=k)?k+','+g(-n,k+2):k)(0,1)
我们首先寻找最小的理想平方s,使得x = n + s是另一个理想平方。
如果存在s,则n是x-s的差 2个完美平方,可以写成2个连续奇数序列的差。然后,我们生成结果列表。
例:
对于n = 104:
我们发现s =11²= 121满足x = n + s = 225 =15²
然后:
15²= 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21 + 23 + 25 + 27 +
2911²= 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 +
21104 =15²-11²= 23 + 25 + 27 + 29
n^2
总是等于第一个n
奇数的和?嗯,很有趣
-1字节感谢Emigna
ÅÉŒʒOQ}н
说明:
ÅÉ Generate a list of odd numbers up to, and including, the input
Œ Substrings
ʒ Only keep values
O where the sum
Q equals the input
} End
For 9, the result would look like this:
[[1, 3, 5], [9]]
н Get the first value
输入无效时,不输出任何内容。
ʒOQ}
而不是DO¹QÏ
保存一个字节。
感谢@maple_shaft削减了1个字节
f n=[k|r<-[1,3..],s<-[r,r+2..n],k<-[[r,r+2..s]],sum k==n]!!0
使用以下事实:最长的运行将始终是从最低编号开始的运行。
我想用算术代替强行执行某些操作k
,但fromInteger
似乎将其杀死。
[1,3..n]
为[1,3..]
f=(a,i=1)=>a>i?(c=f(a-i,i+=2))[0]==i?[i-2,...c]:f(a,i):a<i?0:[i]
如果有解决方案,则返回一个数组;如果没有解决方案,则返回0。
这是一个效率很低但又打高尔夫球的东西解决问题的办法。
即使不使用递归堆栈,它也会使用a-i
和搜索第一个解决方案i=1
。如果该解决方案并非以开头i+2
,那么我们将使用递归搜索第一个解决方案a
和i+2
。
不打高尔夫球
f=(a,i=1)=>
a > i ?
(c = f(a - i, i += 2))[0] == i ?
[i-2, ...c] :
f(a, i) :
a < i ?
0 :
[i]
测试用例:
为了了解这种方法的效率如何,解决方案 f(104)
要想需要69,535个递归调用。堆栈的深度永远不会超过51层,因此堆栈溢出没有问题。
解决方案f(200)
需要860 万递归调用,堆栈深度为99级。(其解决方案是[11,13,15,17,19,21,23,25,27,29]
。)
这是正在运行的程序的直观表示:
减少了11个字节,这要归功于Outgolfer的Erik。
这是我第一次打高尔夫球!
def f(N):
for n in range(N):
x=(n*n+N)**.5-n
if x%1==0:return[2*(k+n)+1for k in range(int(x))]
我使用了众所周知的身份 1 + 3 + 5 + ... + (2n - 1) = n²
以情况为例 15
15 = 3 + 5 + 7 = (1 + 2) + (3 + 2) + (5 + 2) = (1 + 3 + 5) + 3×2 = 3² + 3×2
通常,如果有x个词以开头2n + 1
,例如
(2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))
等于 2nx + x²
如果N
是输入整数,则问题减少到找到最大值x
,从而
x² + 2nx - N = 0
它是带解的二次方程
x = sqrt(n² + N) - n
最长的序列是最大的序列x
。程序n
从0
进行迭代N
,当发现x
整数时,将创建一个列表(2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))
并返回它。
def c(q,l,i): if sum(l)0: l.append(i) return c(q,l,i+2) elif sum(l)>q: l.pop(0) return c(q,l,i) else: print(l) c(q,[1],1)
c=lambda q,l=[1]:c(q,l+[l[-1]+2])if(sum(l)<q)*l else c(q,l[1:])if sum(l)>q else l
感谢@ovs和@ musicman523
print
缺少括号
l.append(i)
通过l+[i]
在递归调用中使用来删除。您可以l.pop(0)
通过l[1:]
在递归调用中使用来删除。您可以c
通过使用关键字参数来删除对最底部的调用。您可以>0
在第2行上删除。最后,您可以使用三元形式将if
and else
语句更改为表达式,从而将您作为lambda表达式减小到92个字节。在线尝试!
sum(l)>q else
,以q<sum(l)else
节省1个字节。
{_Cg=q┘q=q+2~g>:|_Xp\?g,[q,a,2|?b,┘g=g+b~g=a|_X
这将尝试计算从一个到其总和为的所有奇数n
。如果通过n
,请重置循环,将1增加到3,然后重试。退出,如果循环开始时是我们的数字,则打印0 > n
。
{ Do infinitely
_C Clear the screen (we basically print every run of odd numbers, but clear out everything that doesn't sum up to n)
g=q Set g to the first num of this cycle (q starts as 1 in QBIC)
┘ (Syntatcic linebreak)
q=q+2 Raise q to the next odd number, this sets up both the next outer loop as well as a coming FOR loop
~g>:| If we start out with a number > n (read as 'a' from the cmd line)
_Xp THEN quit, printing 0 (the value of the number var 'p')
\ ELSE
[q,a,2| FOR b = q, b <= n, b+=2
?b,┘ PRINT b followed by a tab
g=g+b Add 'b' to running total 'g'
~g=a| and if that lands us on 'n'
_X QUIT (printing nothing: everything is already printed)
lambda n,r=range:[v for v in[r(1,n+1,2)[i:j]for i in r(n)for j in r(n+1)]if sum(v)==n][0]
一个未命名函数,采用正整数,n
如果存在则返回结果,IndexError
否则返回。
创建一个所有相关奇数的列表,r(1,n+1,2)
其为range(start=1, stop=n+1, step=2)
;创建来自所有相关子片段(加上一些空的)由切片i
包容到j
独占与[i:j]
跨越i
在[0,n)的 使用r(n)
和j
在[0,n]的使用r(n+1)
(与空粒时i>=j
或i
是出界); 用正确的和过滤那些if sum(v)==n
; 使用返回第一个(因此也是最长的)切片[0]
。
-1个字节,感谢musicman523。-4字节感谢Step Hen。哈哈
def f(n,R=range):r=R(1,n,2);print[i for w in R(1,len(r)+1)for i in[r[j:j+w]for j in R(len(r)-w+1)]if sum(i)==n][-1]
range
, Try it online!
lambda n,r=range:[[*r(s,e+1,2)]for s in r(1,n+1,2)for e in r(s,n+1,2)if(s+e)*(2+e-s)==4*n][0]
Only thing special I did was noting that (s+e)*(2+e-s)==4*n
is equivalent to sum(range(s,e+1,2))==n
, and though they're the same size when r=range
, the former can be placed closer to the if
statement.
def f(s):
d={k:v for k,v in{a:(1-a+((a-1)**2+4*s)**(.5))/2 for a in range(1,s,2)}.items()if int(v)==v};m=max(d.keys(), key=(lambda k: d[k]));return list(range(int(m),int(m+2*d[m]),2))
As for how this works, I tried to go for a bit more elegant solution than a simple brute force search. I rearranged the formula for the sum of an arithmetic sequence and applied the quadratic formula to get the expression (1-a+((a-1)**2+4*s)**(.5))/2
, which appears in the code. What the expression calculates is, given a desired sum s
and a first term for of arithmetic sequence a
, the length of the sequence. These lengths are stored in a dictionary as values to the first terms as keys.
Next, all non-integer values are removed from the dictionary, as those represent invalid sequences. From there, the largest value is identified with max(d.keys(), key=(lambda k: d[k]))
and the sequence of odd numbers at that position and at that length is made with list(range(int(m),int(m+2*d[m]),2))
.
I'm looking for help golfing this if you see anything. I was more interested in seeing how well I could do with a non-trivial algorithm; my answer is nearly twice as long as the best Python solution.
Last@Cases[Subsequences@Table[n,{n,1,#,2}],x_/;Tr@x==#]&
Function
with first argument #
. Table[n,{n,1,#,2}]
computes the list of positive odd numbers less than or equal to #
. Subsequences
returns all subsequences of that list ordered by increasing length. We then take the Cases
which match x_/;Tr@x==#
, that is, sequences x
such that their sum Tr@x
is equal to the input #
. We then take the Last
such sequence.
n=>(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?l+' '+g(s,l+=2):u)(n-1,l=u=1)
Returns a space-separated string of odd numbers or throws on invalid input. 84 byte version that returns an (empty when appropriate) array:
n=>n%4-2?(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?[l,...g(s,l+=2)]:[u])(n-1,l=u=1):[]
Explanation: Loosely based on @Cabbie407's awk solution to Sums of Consecutive Integers except I was able to save some bytes by using recursion.
for($b=-1;$s-$argn;)for($n=[$s=$x=$b+=2];$s<$argn;)$s+=$n[]=$x+=2;print_r($n);
infinite loop if no solution. insert ?$b>$argn+2?$n=[]:1:0
after $s-$argn
to print empty array instead.
Run with -nR
or try it online.
(i)=>{int s,j,b=1,e=3;for(;;){var o="";s=0;for(j=b;j<e;j+=2){s+=j;o+=j+" ";}if(s==i)return o;s=s<i?e+=2:b+=2;if(b==e)return"";}};
Outputs numbers in a string, space delimited (any other character would just require changing the " "
). Input with no solution returns an empty string (though if running forever without error is a valid way to indicate no solution then 17 bytes could be saved by removing if(b==e)return"";
).
Algorithm is:
(i)=>
as i=>
-10 Bytes thanks to DJMcMayhem
will return 0 if there's no answer, 1 otherwise
the last line it prints is the answer
int f(int n){for(int i=1;;i+=2){int v=0;for(int k=i;;k+=2){v+=k;std::cout<<k<<" ";if(v==n)return 1;if(v>n)break;}if(i>n)return 0;std::cout<<"\n";}}
ungolfed:
int f(int n)
{
for (int i = 1;; i += 2)
{
int v = 0;
for (int k = i;; k += 2)
{
v += k;
std::cout << k << " ";
if (v == n)
return 1;
if (v > n)
break;
}
if (i > n)
return 0;
std::cout << "\n";
}
}
this is my first code golf ^^
int v=0;
instead of int v;....v=0;
and if you made your output Newline delimited, you could do std::cout<<k<<"\n";
and then remove the second Newline altogether
fun f(a:Double){var n=Math.sqrt(a).toInt()+1;var x=0;while(n-->0){if(((a/n)-n)%2==0.0){x=((a/n)-n).toInt()+1;while(n-->0){println(x.toString());x+=2}}}}
Try it online (Wait 4-5 seconds, compiler is slow)
Ungolfed
fun f(a: Double){
var n=Math.sqrt(a).toInt()+1;
var x=0;
while(n-->0){
if(((a/n)-n)%2==0.0){
x=((a/n)-n).toInt()+1;
while(n-->0){
println(x.toString());
x+=2;
}
}
}
}
Sub
routine that takes input n
of expected type integer and reports the longest sequence of consecutive odd numbers to cell [A1]
Sub a(n)
For i=1To n Step 2
s=0
For j=i To n Step 2
s=s+j
If s=n Then:For k=i To j-1 Step 2:r=r &k &"+":Next:[A1]=r &j:End
Next j,i
End Sub