4
\$\begingroup\$

I am learning Haskell and as exercise I am doing Project Euler Problems. In this case PE1.

-- Sum any given finite Airthmetic Progression
sumAP :: Integer -> Integer -> Integer -> Integer
sumAP first limit step = do
  let last  = limit - (limit `rem` step)
  let terms = (last - first) `quot` step + 1
  let avg   = first + last
  terms * avg `quot` 2

Now, off the bat I am shadowing the last function. How could I rename this variable along with first?

Is there any way I can improve readability? Any edge case or fail case I haven't covered? Any performance fail?

\$\endgroup\$
  • 1
    \$\begingroup\$ The sum of the following arithmetic progression [3,5,7,9,11] is 35. However, sumAP 3 11 2 gives 26. So I believe that your function is wrong. \$\endgroup\$ – Marcus Vinícius Monteiro Jun 21 '15 at 15:30
  • \$\begingroup\$ Yes, it was wrong. I added in the comments that I forgot to account for the initial dephase. ;_; \$\endgroup\$ – Fabián Heredia Montiel Jun 21 '15 at 15:31
  • \$\begingroup\$ Just so you know, adding the first rem step to last puts it back in the same offset from 0 as first. \$\endgroup\$ – Fabián Heredia Montiel Jun 22 '15 at 4:15
5
\$\begingroup\$

My first comment would be to comment your code.

You need documentation so I know what your function is meant to do. "Sum any given finite Arithmetic Progression" would suffice if you passed in an ArithmeticProgression, but instead you pass in some bounds. Writing an arithmetic progression type would be simple and might even help a little, but you still need to document that.

I don't know what algorithm you're trying to use. You've evidently taken some maths for sums of arithmetic progressions and applied it to the problem, but there's no way for me to verify that the maths is correct or that the code implements it correctly without at least rudimentary explanation of what you did. I could reimplement it myself, but code should be verifiable much more easily than that.

\$\endgroup\$
  • \$\begingroup\$ Added comments, hope it became more readable. \$\endgroup\$ – Fabián Heredia Montiel Jun 20 '15 at 19:52
  • \$\begingroup\$ @FabiánH.jr. You're not meant to change any code in the question that would invalidate any answers, so the edit is invalid. Feel free to add it as text outside of the code, though. \$\endgroup\$ – Veedrac Jun 20 '15 at 20:00
  • \$\begingroup\$ Sorry about that, my bad; I separated the code into the original version and an updated version from feedback. Is that better or should I take another approach? \$\endgroup\$ – Fabián Heredia Montiel Jun 20 '15 at 20:04
  • \$\begingroup\$ Supposedly appending code is also disallowed. See meta.codereview.stackexchange.com/questions/1763/…. \$\endgroup\$ – Veedrac Jun 20 '15 at 20:35
  • \$\begingroup\$ Oh, interesting. I will remove the edits then. \$\endgroup\$ – Fabián Heredia Montiel Jun 20 '15 at 21:01
3
\$\begingroup\$

Int faster than Integer. If you have acceptable limitations you should use Int.

"Integer" is an arbitrary precision type: it will hold any number no matter how big, up to the limit of your machine's memory…. This means you never have arithmetic overflows. On the other hand it also means your arithmetic is relatively slow. Lisp users may recognise the "bignum" type here.

"Int" is the more common 32 or 64 bit integer. Implementations vary, although it is guaranteed to be at least 30 bits.

Source: The Haskell Wikibook. Also, you may find the Numbers section of A Gentle Introduction to Haskell useful.

Copy-paste from Haskell Int and Integer

\$\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.