1
\$\begingroup\$

I have been programming for about ~2 years, and mostly wrote OOP and structural code. Recently, I have decided to pick up a functional programming language, and Haskell being too alien for me, looked to Racket (since it is high time I learned a LISP anyways) and am loving it. Since this is a new area of programming for me, I would appreciate any feedback you could give me on this program. It is the solution to the first Project Euler program.

;If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
;Find the sum of all the multiples of 3 or 5 below 1000.

#lang racket

(define max 1000)

(define (multiple_of base test)
    (equal? (remainder test base) 0))

(define (primes current total)
    (if (< current max)
        (primes
            (+ current 1)
            (+ total (if
                (or (multiple_of 5 current) (multiple_of 3 current)) current 0)))
        total))

(primes 1 0)

; Output: 233168
; Success
\$\endgroup\$
0
1
\$\begingroup\$
  1. In Scheme, we use hyphens to separate words, not underscores. Also boolean-returning procedures should end in ?. So it should be multiple-of?
  2. Instead of (equal? x 0), use (zero? x).
  3. Instead of a recursive loop, you can use for comprehensions:

    (for/sum ((i (in-range 1000))
              #:when (or (multiple-of? 5 i)
                         (multiple-of? 3 i)))
      i)
    

    Surely, that's much more readable. In my humble opinion. :-)

  4. Notwithstanding the last comment, your formatting for your primes procedure is not ideal. Here's a more proper formatting:

    (define (primes current total)
      (if (< current max)
          (primes (add1 current)
                  (+ total (if (or (multiple-of? 5 current)
                                   (multiple-of? 3 current))
                               current
                               0)))
          total))
    
\$\endgroup\$
4
  • \$\begingroup\$ Why do you start at 1? \$\endgroup\$ – itsbruce Jan 23 '15 at 11:13
  • \$\begingroup\$ thank you! Especially about 1 and 2. I wasn't aware of those tips. About number 3, I haven't learned for loops in racket yet, which is the only reason why i went with recursion, but you are right: That looks more readable. As to number 4, do you have a guide documenting this that you can link to? \$\endgroup\$ – DTSCode Jan 23 '15 at 17:03
  • \$\begingroup\$ @DTSCode You're welcome! for "looks like" a loop but is actually a comprehension (if you've ever played with such things in Python or the like). As for style guide, look at mumble.net/~campbell/scheme/style.txt \$\endgroup\$ – Chris Jester-Young Jan 23 '15 at 18:32
  • \$\begingroup\$ alright! thanks a ton! my python is a bit rusty, but I'm sure if I google list comprehension python Ill get it \$\endgroup\$ – DTSCode Jan 23 '15 at 19:13
0
\$\begingroup\$

The Scheme code is quite reasonable. However, this is a very naive solution to the problem. You are wasting processing time by testing each number to see if it is a multiple. Even with this naive solution, why do you start at 1, not 3?.

Think. If you do start at 1 (which you know fails the test), you can create all the multiples there are by working forward.

Don´t forget you need to avoid generating numbers which are multiples of both 5 and 3 more than once.

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