1

I decided to write a function that given a number will return a list containing the digits in that number, my attempt is:

(define (rev-digits n)
  (if (= n 0)
    '()
    (cons (modulo n 10) (digits (quotient n 10)))))

(define (digits n)
  (reverse (rev-digits n)))

The fact is, I need the digits to be in proper order, but the function returns, for example:

> (digits 1234567890)
'(9 7 5 3 1 2 4 6 8 0)

In seemingly random order... can you help me getting a more ordinated output?

Caridorc
  • 6,222
  • 2
  • 31
  • 46
  • 1
    I cannot reproduce this behavior. The function works as expected and returns `'(0 9 8 7 6 5 4 3 2 1)` for me. I am using DrRacket 5.2.1 on Windows. –  Apr 18 '15 at 15:33
  • @MarkusHimmel my bad, the code was not complete, let me add more context. – Caridorc Apr 18 '15 at 15:46

3 Answers3

1

rev-digits needs to call itself, not digits.

(define (rev-digits n)
  (if (= n 0)
    '()
    (cons (modulo n 10) (rev-digits (quotient n 10)))))

(define (digits n)
  (reverse (rev-digits n)))

should work.

It's worth noting that your "random" output was not in fact random; rather the digits were "bouncing" back and forth from the start to the end of the list. Which makes sense, because you were effectively switching back and forth between a "normal" and reversed version of your digits function.

Jay Kominek
  • 8,674
  • 1
  • 34
  • 51
1

The answer given by @JayKominek is spot-on and fixes the error in your code. To complement it, here's an alternative implementation:

(define (rev-digits n)
  (let loop ((n n) (acc '()))
    (if (< n 10)
        (cons n acc)
        (loop (quotient n 10) (cons (modulo n 10) acc)))))

The advantages of the above code are:

  • It's tail recursive and hence more efficient
  • It correctly handles the edge case when n is zero (your code returns an empty list)
  • It doesn't require a helper procedure, thanks to the use of a named let
  • It builds the list in the correct order, there's no need to reverse it at the end
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

A simple solution:

#lang racket
(define (digits n)
  (for/list ([c (number->string n)])
    (- (char->integer c) (char->integer #\0))))
soegaard
  • 30,661
  • 4
  • 57
  • 106