views:

105

answers:

4

SO has frozen for the nth time now trying to ask this question, so third time is a charm? I'm trying to write a rubyish solution to problem 6 in Project Euler, because I have the propensity to write C in other languages. However, this code:

sqrsum, sumsqr = 0, 0
(1..100).each { |x| sqrsum, sumsqr += x, x**2 }
p (sumsqr - (sqrsum ** 2))

kicks up these errors:

/Users/Andy/Documents/Programming/Ruby/ProjectEuler/P6.rb:2: syntax error, unexpected tOP_ASGN, expecting '='
(1..100).each { |x| sqrsum, sumsqr += x, x**2 }
                                     ^
/Users/Andy/Documents/Programming/Ruby/ProjectEuler/P6.rb:2: syntax error, unexpected tPOW, expecting '='
(1..100).each { |x| sqrsum, sumsqr += x, x**2 }
                                            ^

What am I doing wrong here? Am I only allowed to assign in that syntactic structure?

+1  A: 

Do you want that

sqrsum, sumsqr = sumsqr + x, x**2

Your answer is the closest. It turns out what I actually wanted was`sqrsum, sumsqr = sumsqr+x, sqrsum+x**2`
Andrew
+2  A: 

You are trying to make multiple assignments, but you are not using the assignment operator =.

Compare sqrsum, sumsqr = 0, 0 with sqrsum, sumsqr += x, x**2.

Probably you wanted to write

sqrsum, sumsqr = sqrsum+x, sumsqr+x**2
kiamlaluno
I'm sorry, I still don't understand why my version (the second code snippet in your answer) isn't valid.
Andrew
= can do multiple assignments, += can not
Neil Sarkar
@Neil, thank you.
Andrew
+1  A: 

why not just do { |x| sqrsum += x; sumsqr += x**2}

Neil Sarkar
Because I didn't know I could! +1
Andrew
yeah a semi-colon in ruby basically acts as a newline, allowing you to execute multiple commands on a single line
Neil Sarkar
+2  A: 

you could also use inject

sqrsum, sumsqr = (1..100).inject(:+), (1..100).inject(0) { |result,x| result + x**2 }
p(sumsqr - sqrsum**2)

[edit: thanks to commenters for pointing out :+ shorthand]

Neil Sarkar
I like this method, but your example does not work. Can you help me understand why?
Andrew
Oh! I figured it out! It should be `|result, x|`, not the other way around. Hooray for the docs. :)
Andrew
Wayne Conrad
@Wayne Conrad: `inject` also takes a simple symbol: `(1..100).inject(:+)`.
Jörg W Mittag
@Andrew my fault, edited above. @Jorg and @Wayne cool, didnt know about :+
Neil Sarkar
How exactly does the `.inject(:+)` work?
Andrew
@Andrew, `.inject(:+)` is equivalent to `.inject { |a, b| a + b }`. How it works, I haven't a clue: It's some magic buried in the interpreter, or library, or both.
Wayne Conrad