Check if number is a sum of consecutive numbers or not

7

2

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.

Aman ZeeK Verma

Posted 2011-06-23T03:29:49.183

Reputation: 609

Any odd number greater than 1 would return true? – elssar – 2012-09-05T12:48:29.643

I edited the question to be clearer, and only code-golf. – mbomb007 – 2016-03-11T15:05:02.987

Good edit, @mbomb007 – Timtech – 2016-03-11T15:57:37.723

Related OEIS sequence – MildlyMilquetoast – 2016-12-06T05:23:05.543

I assume ./check 1 should return false? – mellamokb – 2011-06-23T04:23:16.140

1@mellamokb, I've fixed the spec and it's now clear that 1 gives false. – Peter Taylor – 2011-06-23T09:24:22.453

Is case important for the output? – Joey – 2011-06-24T11:12:37.107

Not really, that should not be a problem :) – Aman ZeeK Verma – 2011-06-24T11:57:11.077

Answers

28

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.

mellamokb

Posted 2011-06-23T03:29:49.183

Reputation: 5 544

About the JavaScript code: Does JavaScript guarantee strict left-to-right evaluation of the arguments to &? In C that expression would be undefined behaviour. – celtschk – 2012-02-04T10:55:24.473

What's your source? According to sources I found by Googling, both Javascript and C have operator precendence charts listing & as left-to-right associative. Why would it be undefined behavior?

– mellamokb – 2012-02-06T13:59:05.473

1You can change it to an anonymous function: x=>!!(x&x-1) (12 bytes) – Esolanging Fruit – 2016-12-06T00:34:55.753

1Edit: you can also get rid of the !!(), because positive integer values are considered truthy. This yields x=>x&x-1 (8 bytes) – Esolanging Fruit – 2016-12-06T00:48:40.830

great work with the math man! – Math chiller – 2013-10-21T17:10:34.490

3It 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. – Alexandru – 2011-06-23T13:49:32.227

How do you get from "all odd numbers" to "all numbers that are not a power of 2" ? – Paul R – 2011-06-23T15:56:28.803

2@Paul R: I have updated the answer with justification for why this should be correct. – mellamokb – 2011-06-23T16:11:08.117

@Alexandru: That is the basic idea, but you can't jump directly to powers of 2 without covering all the cases as I've given above with rules #2 and #3. – mellamokb – 2011-06-23T16:11:52.297

1@mellamokb: cool - thanks ! – Paul R – 2011-06-23T16:13:30.357

3+1 for the proof (although to be pedantic, all odd numbers greater than 1). – Peter Taylor – 2011-06-23T16:28:19.023

1@mellamokb: to be pedantic you still need to prove lack of solution for powers of two. – Alexandru – 2011-06-23T16:42:39.637

@Alexandru, @Peter Taylor: Duly updated, thanks for the input! – mellamokb – 2011-06-23T16:55:39.670

1Bloody brilliant – Steve Robbins – 2011-08-12T00:55:38.963

3

Golfscript, 20 chars

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

Someone had to.

Peter Taylor

Posted 2011-06-23T03:29:49.183

Reputation: 41 901

3

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

jsvnm

Posted 2011-06-23T03:29:49.183

Reputation: 441

2

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]

Thomas Eding

Posted 2011-06-23T03:29:49.183

Reputation: 796

1

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.

MildlyMilquetoast

Posted 2011-06-23T03:29:49.183

Reputation: 2 907

not actually the powers of two... It is actually the powers of two with 1 replaced by 0 – Destructible Lemon – 2016-12-06T06:16:34.267

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 – Destructible Lemon – 2016-12-06T06:29:31.723

@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). – MildlyMilquetoast – 2016-12-06T06:48:49.557

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) – Destructible Lemon – 2016-12-06T06:53:20.807

1

Python, 19 17 16

x=input()
x>x&-x

Coding man

Posted 2011-06-23T03:29:49.183

Reputation: 1 193

1Nice. You can actually shave off two characters on the second line: ~-x&x>0 – daniero – 2013-10-22T18:18:59.880

@daniero Nice trick!! – Coding man – 2013-10-22T19:07:57.467

x&-x<x saves yet 1 character – AMK – 2013-10-23T15:07:00.753

@AMK great trick!! updated the code. – Coding man – 2013-10-23T17:50:39.610

1

Wren, 18 17 bytes

Umm, it's shorter than GolfScript...

Fn.new{|n|n&-n<n}

Try it online!

user85052

Posted 2011-06-23T03:29:49.183

Reputation:

1

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/

mellamokb

Posted 2011-06-23T03:29:49.183

Reputation: 5 544

1

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

Alexandru

Posted 2011-06-23T03:29:49.183

Reputation: 5 485

your kinda stealing his idea... – Math chiller – 2013-10-21T17:12:05.700

1

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.

Fraxtil

Posted 2011-06-23T03:29:49.183

Reputation: 2 495

1

C

return 1 or 0:

int i(int j){return((j%2)?!(j==1):i(j/2));}

Anthony

Posted 2011-06-23T03:29:49.183

Reputation: 199

3doesnt fulfill the task - it has to output "true" or "false". – oenone – 2011-08-11T12:50:30.487

1

Python, 24 chars

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

bin(input()).count('1')>1

daniero

Posted 2011-06-23T03:29:49.183

Reputation: 17 193

1bin(input()).count('1')>=2? – Keith Randall – 2012-09-05T04:18:59.977

1Haha, that's kinda obvious really :D thanks. And >=2 == >1 ;) – daniero – 2012-09-05T15:37:24.247

Is this not repl snippet? – Destructible Lemon – 2016-12-06T00:38:25.460

1

Mathematica, 23 bytes

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

For once it's actually useful

CalculatorFeline

Posted 2011-06-23T03:29:49.183

Reputation: 2 608

1

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

Timtech

Posted 2011-06-23T03:29:49.183

Reputation: 12 038

0

Jelly, 2 bytes

&’

Try it online!

Just a translation of the accepted JavaScript solution.

Unrelated String

Posted 2011-06-23T03:29:49.183

Reputation: 5 300

0

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

Fernando Martin

Posted 2011-06-23T03:29:49.183

Reputation: 131

0

Perl:

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

$perl Soc.pl 45

false

$perl Soc.pl 8

true

beginnerProg

Posted 2011-06-23T03:29:49.183

Reputation: 1

1You posted the output incorrectly: for 45 gives true and for 8 gives false. – manatwork – 2012-09-03T12:35:28.127

0

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

defhlt

Posted 2011-06-23T03:29:49.183

Reputation: 1 717