连续奇数之和


24

尽管已经提出了相关的 挑战,但这一挑战有待提出自己的问题。


挑战

给定一个正整数,返回其总和为给定整数的连续正奇数整数的最长序列。如果不存在这样的序列,则您可能会以对您的语言有意义的任何方式报告错误,包括返回虚假值或引发异常。

测试用例

  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]不是有效答案)

计分

这是,因此每种语言中最短的答案将获胜。


2
如果没有解决方案,我的程序可以永远运行吗?
丹尼斯

很有关系。一些偶数无法在该数字中表示的事实可能会使它免于被骗。
ETHproductions

6
15不能给[-1,1,3,5,7]吗?如果仅允许使用正值,则应这样说。
xnor

2
@ЕвгенийНовиков您跳过了17
kalsowerus

1
@kalsowerus是的。我误解词“连续”
ЕвгенийНовиков

Answers:


11

Haskell,67 65 63 62 58字节

由于朱利安·沃尔夫节省了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选择了最小值,所以将输出最长的列表


7
不赞成投票:添加说明您的理由的评论既友善,也更具建设性,尤其是当反对新用户投票时。
乔纳森·艾伦,

1
除非我丢失了某些内容,否则,您只需将x两者都加起来就可以节省4个字节,n并且m
朱利安·沃尔夫

众所周知,当您编辑答案时,社区用户会自动投下反对票。我认为这是一个错误。(CC @JonathanAllan)
丹尼斯

啊,就是其中之一。
乔纳森·艾伦

9

Python 2中66 62个字节

f=lambda n,k=0,*r:n-sum(r)and f(n,k+1,*range(k%n|1,k/n,2))or r

如果没有解决方案,则以RuntimeError退出(超过最大递归深度)。

在线尝试!


1
如果输入值足够高,但是有解决方案,这会导致RuntimeError吗?
Okx

如果递归限制不够高和/或堆栈不够大,那么可以。但是,通常会忽略物理限制(例如,C答案仅适用于32位整数),OP明确表示,如果没有解决方案,则永远运行是可以接受的。
丹尼斯

9

果冻 11  10 字节

感谢丹尼斯-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)

1
ẆḤ’保存一个字节。
丹尼斯

8

JavaScript(ES7),87 86 85 81字节

返回以逗号分隔的整数列表,或者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,则nx-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


3
等一下,您是否告诉我n^2总是等于第一个n奇数的和?嗯,很有趣
Skidsdev '17

2
@Mayube 的确
Arnauld


7

05AB1E9 8字节

-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Ï保存一个字节。
Emigna

@JonathanAllan Docs说“参差不齐”,以至于可能会感到困惑……
Outgolfer的Erik

1
@JonathanAllan小错误。固定。
Okx

6

Haskell61 60字节

感谢@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..]
maple_shaft,

1
您可以使用助手功能保存7个字节r?n=[r,r+2..n]在线尝试!
与Orjan约翰森

4

Python,67字节

f=lambda n,R=[1]:n-sum(R)and f(n,[R+[R[-1]+2],R[1:]][sum(R)>n])or R

在线尝试!

从上一个连续的总和挑战中复制了答案,并将更改+1+2。谁知道高尔夫球代码可以如此模块化?

一个奇怪的简单策略:R用所需的和搜索间隔。

  • 如果总和太小,请在间隔的右端点上附加下一个数字2,将其右移2。
  • 如果总和太大,则通过删除最小的元素来向左端点上移
  • 如果总和正确,则输出R

由于间隔的底端仅增加,因此在较短的间隔之前会找到较长的间隔。如果找不到可能的时间间隔,则以IndexError终止。


4

JavaScript(ES6),65 64字节

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,那么我们将使用递归搜索第一个解决方案ai+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]。)

这是正在运行的程序的直观表示:


3

Python 2.7版,109 108 97字节

减少了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。程序n0进行迭代N,当发现x整数时,将创建一个列表(2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))并返回它。



@EriktheOutgolfer,谢谢,我忘了使用标签(=
dark32 '17

3

Python 3,190 81字节

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


4
只需删除一些缩进就可以将其减少到122个字节。如果您想进一步缩短代码,请查看Python打高尔夫球技巧
ovs

3
这不会在Python 3中运行,因为对的调用print缺少括号
musicman523

2
您可以l.append(i)通过l+[i]在递归调用中使用来删除。您可以l.pop(0)通过l[1:]在递归调用中使用来删除。您可以c通过使用关键字参数来删除对最底部的调用。您可以>0在第2行上删除。最后,您可以使用三元形式将ifand else语句更改为表达式,从而将您作为lambda表达式减小到92个字节。在线尝试!
musicman523

1
根据@ musicman523的建议,我们仍然可以缩短条件并丢弃i以达到总共81个字节
ovs '17

我想,你可以改变sum(l)>q else,以q<sum(l)else节省1个字节。
扎卡里

2

QBIC,47字节

{_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)

1

R,90字节

f=function(x,y=1)'if'(length(w<-which(cumsum(r<-y:x*2-1)==x)),r[1:w],'if'(y>x,0,f(x,y+1)))

在线尝试!

使用递归函数测试转换为奇数序列的y:x序列的累加和。y在每次递归时递增,直到超过x。将返回与目标求和的第一个序列。


1

Python 2,89个字节

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>=ji是出界); 用正确的和过滤那些if sum(v)==n; 使用返回第一个(因此也是最长的)切片[0]






0

Python 3, 93 bytes

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]

Try it online!

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.


0

Python 3, 185 bytes

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))

Try it online!


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.


Would this work? repl.it/JTt7 (177 bytes)
Zacharý

0

Mathematica, 56 bytes

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.


0

JavaScript (ES6), 72 bytes

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.


0

PHP, 78 bytes

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.


0

C# (.NET Core), 129 bytes

(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:

  1. Start with [1]
  2. If the sum is equal to the target, return the list
  3. If the sum is less than the target, add the next odd number
  4. If the sum is greater than the target, remove the first item
  5. If the list is empty, return it
  6. Repeat from 2

You can write (i)=> as i=>
aloisdg says Reinstate Monica

0

C++, 157 -> 147 Bytes


-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 ^^


You could save some bytes if you made it an int function and returned 0 or 1. Also, you could do 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
DJMcMayhem

the if i did the last recomendation then it would print a new line on every single number but i want to seperate number groups, but thanks anyways for -10 Bytes
SeeSoftware

0

Kotlin, 152 bytes

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;
            }

        }
    }
}

0

Excel VBA, 139 Bytes

Subroutine 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
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.