7
\$\begingroup\$

Write a program that checks if a given positive integer can be represented as sum of two or more consecutive positive integers.

Example:

43 can be represented as 21 + 22

10 = 1+2+3+4

but 4 cannot be represented in this way.

Input spec: positive integer (as argument or stdin)

Output spec: truthy or falsy

Sample i/o

43 -> true
4 -> false

Shortest code wins.

\$\endgroup\$
  • \$\begingroup\$ I assume ./check 1 should return false? \$\endgroup\$ – mellamokb Jun 23 '11 at 4:23
  • \$\begingroup\$ @mellamokb, I've fixed the spec and it's now clear that 1 gives false. \$\endgroup\$ – Peter Taylor Jun 23 '11 at 9:24
  • \$\begingroup\$ Is case important for the output? \$\endgroup\$ – Joey Jun 24 '11 at 11:12
  • \$\begingroup\$ Not really, that should not be a problem :) \$\endgroup\$ – Aman ZeeK Verma Jun 24 '11 at 11:57
  • \$\begingroup\$ Any odd number greater than 1 would return true? \$\endgroup\$ – elssar Sep 5 '12 at 12:48

16 Answers 16

27
\$\begingroup\$

JavaScript (31)

alert(!!((n=~~prompt())&(n-1)))

From my testing, I believe this gives correct solutions.

http://jsfiddle.net/3e9FZ/

Edit: (SPOILER ALERT!) Here is the justification for this answer:

  1. All odd numbers greater than 1 can be trivially written as the sum of two consecutive numbers (ex 15 = 7+8, 23=11+12, etc.).
  2. For even numbers having an odd factor where the odd factor is less than twice the even factor. For example, 4*7, because 7 < (2*4 = 8). Simply add 7 numbers with 4 at the center, 1+2+3+4+5+6+7.
  3. For even numbers having an odd factor where the odd factor is more than twice the even factor. For example, 4*9, because 9 > (2 * 4 = 8). Double the even factor, and halve the odd factor to get 8*4.5. You will add the 8 numbers centered at 4.5, i.e., 1+2+3+4+5+6+7+8.
  4. The only numbers left are the even numbers having no odd factor, i.e., the powers of two. The formula for the sum of a consecutive set of numbers is (avg * count). Now if the count is odd, then avg is a whole number, and (avg * count) has an odd factor. If count is even, then avg must be #.5, and thus avg * 2 is odd, and so avg * count has an odd factor. Therefore, any sum using the formula (avg * count) must have an odd factor, which powers of two do not, and therefore have no solution.
\$\endgroup\$
  • 3
    \$\begingroup\$ It easy to see that odd numbers can be written as a sum of two consecutive numbers, and therefore any number that's not a power of two can be written as a sum of consecutive numbers. \$\endgroup\$ – Alexandru Jun 23 '11 at 13:49
  • 2
    \$\begingroup\$ @Paul R: I have updated the answer with justification for why this should be correct. \$\endgroup\$ – mellamokb Jun 23 '11 at 16:11
  • 1
    \$\begingroup\$ @mellamokb: cool - thanks ! \$\endgroup\$ – Paul R Jun 23 '11 at 16:13
  • 3
    \$\begingroup\$ +1 for the proof (although to be pedantic, all odd numbers greater than 1). \$\endgroup\$ – Peter Taylor Jun 23 '11 at 16:28
  • 1
    \$\begingroup\$ Bloody brilliant \$\endgroup\$ – Steve Robbins Aug 12 '11 at 0:55
3
\$\begingroup\$

Golfscript, 20 chars

~.(&!!"falsetrue"5/=

Someone had to.

\$\endgroup\$
3
\$\begingroup\$

Ruby (23)

only 3 chars longer than golfscript :)

p 0<(n=$*[0].to_i)&n-1

output:

$ ruby gc2958.rb 4
false
$ ruby gc2958.rb 43
true
$ wc gc2958.rb
  1       2      23 gc2958.rb
\$\endgroup\$
2
\$\begingroup\$

Haskell, 74

Felt like doing the brute force way.

import List
main=print.f=<<readLn
f n=elem n$map sum$tails=<<inits[1..n-1]
\$\endgroup\$
1
\$\begingroup\$

JavaScript (81)

n=prompt(r=i=1)|0;while(r&++i*i/2<n)if(i%2&!(n%i)|!(i%2|(n+i/2)%i))r=!r;alert(!r)

I'm cheating with & and | - even though they are technically bit-wise operations, they do the job quite nicely because the result is a 1/0 which are valid conditionals!

http://jsfiddle.net/HCqK2/4/

\$\endgroup\$
1
\$\begingroup\$

C, 67

As mellamokb suggested all numbers, except powers of two, can be written as sum of positive consecutive numbers:

main(int i,char**a){
printf((i=atoi(a[1]))&i-1?"true\n":"false\n");
}
\$\endgroup\$
  • \$\begingroup\$ your kinda stealing his idea... \$\endgroup\$ – Math chiller Oct 21 '13 at 17:12
1
\$\begingroup\$

C

return 1 or 0:

int i(int j){return((j%2)?!(j==1):i(j/2));}
\$\endgroup\$
  • 3
    \$\begingroup\$ doesnt fulfill the task - it has to output "true" or "false". \$\endgroup\$ – oenone Aug 11 '11 at 12:50
1
\$\begingroup\$

Python, 24 chars

Shortest python atm, borrowing bin() from @Fraxtil :)

bin(input()).count('1')>1
\$\endgroup\$
  • 1
    \$\begingroup\$ bin(input()).count('1')>=2? \$\endgroup\$ – Keith Randall Sep 5 '12 at 4:18
  • 1
    \$\begingroup\$ Haha, that's kinda obvious really :D thanks. And >=2 == >1 ;) \$\endgroup\$ – daniero Sep 5 '12 at 15:37
  • \$\begingroup\$ Is this not repl snippet? \$\endgroup\$ – Destructible Lemon Dec 6 '16 at 0:38
1
\$\begingroup\$

Python, 19 17 16

x=input()
x>x&-x
\$\endgroup\$
  • 1
    \$\begingroup\$ Nice. You can actually shave off two characters on the second line: ~-x&x>0 \$\endgroup\$ – daniero Oct 22 '13 at 18:18
  • \$\begingroup\$ @daniero Nice trick!! \$\endgroup\$ – Coding man Oct 22 '13 at 19:07
  • \$\begingroup\$ x&-x<x saves yet 1 character \$\endgroup\$ – AMK Oct 23 '13 at 15:07
  • \$\begingroup\$ @AMK great trick!! updated the code. \$\endgroup\$ – Coding man Oct 23 '13 at 17:50
1
\$\begingroup\$

Mathematica, 23 bytes

N[2~Log~#]~MatchQ~_Real

For once it's actually useful

\$\endgroup\$
1
\$\begingroup\$

TI-Basic, 6 bytes

fPart(logBASE(Ans,2

Operating system ≥2.53 required due to logBASE(. Without logBASE, there are alternatives:

7 bytes: fPart(ln(Ans)/ln(2
7 bytes: fPart(log(Ans)/log(2
\$\endgroup\$
1
\$\begingroup\$

Befunge-93, 28 bytes

Try it Online!

&v@.1<@.0<
:</2_^#!_^#-1\%2:

Instead of checking if the given integer is an element in this sequence, it's much easier to check if it isn't in the complimentary sequence (powers of 2 with 0 instead of 1). This functions very similarly to mellamokb's answer in that sense.

Note that the linked sequences are not exact representations of all truthy/falsey results of each integer, because the sequence uses non-negative integers instead of strictly positive. Thus, 1 is in the linked sequence, even though for this specific problem it should be in its compliment.

\$\endgroup\$
  • \$\begingroup\$ not actually the powers of two... It is actually the powers of two with 1 replaced by 0 \$\endgroup\$ – Destructible Lemon Dec 6 '16 at 6:16
  • \$\begingroup\$ also you are using the wrong sequence. that one includes 1 as a number by virtue of 1+0, as it uses non negative rather than positive \$\endgroup\$ – Destructible Lemon Dec 6 '16 at 6:29
  • \$\begingroup\$ @DestructibleWatermelon I realize that the sequence doesn't completely match the problem, but only in regards to the base case of 1. The complimentary sequence for the one that matches the problem is the powers of 2 (possibly in addition to 0, depending on where the sequence starts). \$\endgroup\$ – MildlyMilquetoast Dec 6 '16 at 6:48
  • \$\begingroup\$ Why don't you just use the actual powers of two instead of that sequence of two? (0 is not a positive number anyway, so no need to cover it) \$\endgroup\$ – Destructible Lemon Dec 6 '16 at 6:53
0
\$\begingroup\$

Python, 33 chars

It seems that there's a way shorter way to do this though:

s=input()
n=2
while n<s:n*=2
n!=s
\$\endgroup\$
0
\$\begingroup\$

Python, 34

bool(int(bin(2*int(input()))[3:]))

I took an alternative approach to the solution, but can't seem to squeeze anything else out of it. This code takes the input, multiplies it by two (this fixes the input case of 1 which breaks otherwise), converts it to binary, strips out the first 3 characters (0b1), converts the remainder to an integer (which is 0 iff the input was a power of two), and then converts that to a boolean.

As mentioned above, you can remove the 2* to get a 32-char solution that fails on an input of 1 but is otherwise perfect.

\$\endgroup\$
0
\$\begingroup\$

Perl:

print(((log($ARGV[0])/log(2))=~ /\./ )?true:false);

$perl Soc.pl 45

false

$perl Soc.pl 8

true
\$\endgroup\$
  • 1
    \$\begingroup\$ You posted the output incorrectly: for 45 gives true and for 8 gives false. \$\endgroup\$ – manatwork Sep 3 '12 at 12:35
0
\$\begingroup\$

J, 12

It doesn't follow the spec 'true'/'false'. Rather I stick with 1/0. It checks if log base 2 of a number has a decimal mark.

+/=&'.'":2^.

   +/=&'.'":2^.1
0
   +/=&'.'":2^.4
0
   +/=&'.'":2^.43
1
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.