Номер схемы к списку

Мне нужна подпрограмма для моей программы, написанная по схеме, которая принимает целое число, скажем 34109, и помещает его в список с элементами 3, 4, 1, 0, 9. Целое число может быть любой длины. У кого-нибудь есть хитрость для этого? Я думал об использовании по модулю для каждого места, но я не думаю, что это должно быть так сложно.

3 ответа

Решение

Самым простым способом, который я могу придумать, является использование арифметических операций и именованногоlet для реализации хвостовой рекурсии:

(define (number->list num)
  (let loop ((num num)
             (acc '()))
    (if (< num 10)
        (cons num acc)
        (loop (quotient num 10)
              (cons (remainder num 10) acc)))))

Кроме того, вы можете решить эту проблему, используя строковые операции:

(define char-zero (char->integer #\0))

(define (char->digit c)
  (- (char->integer c) char-zero))

(define (number->list num)
  (map char->digit
       (string->list (number->string num))))

Это можно сжать в одну функцию, но я считаю, что это легче понять, если мы разделим проблему на части, как описано выше.

(define (number->list num)
  (map (lambda (c) (- (char->integer c) (char->integer #\0)))
       (string->list
        (number->string num))))

Во всяком случае, результаты, как и ожидалось:

(number->list 34109)
> '(3 4 1 0 9)

Что-то вроде этого:

(define (num2list-helper num lst)
  (cond ((< num 10) (cons num lst))
        (else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))

(define (num2list num)
  (num2list-helper num '()))

(num2list 1432)

Как отметил его Брюс, вы можете скрыть вспомогательную функцию внутри основной:

(define (num2list num)
  (define (num2list-helper num lst)
    (cond ((< num 10) (cons num lst))
          (else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))

    (num2list-helper num '()))

(num2list 1432)

продолжение следует...

Я не фанат ручного зацикливания, поэтому вот решение, основанное на развертывании (сначала загрузите SRFI 1 и SRFI 26):

(define (digits n)
  (unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))

Это возвращает пустой список для 0, хотя. Если хочешь вернуть (0) вместо этого мы добавляем особый случай:

(define (digits n)
  (case n
   ((0) '(0))
   (else (unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))))

Конечно, вы можете обобщить это для других основ. Здесь я реализую это, используя необязательные аргументы, поэтому, если вы не укажете основание, по умолчанию будет 10:

(define (digits n (base 10))
  (case n
   ((0) '(0))
   (else (unfold-right zero? (cut modulo <> base) (cut quotient <> base) n))))

Различные реализации Схемы используют разные синтаксисы для необязательных аргументов; Выше используется синтаксис в стиле Racket (и / или в стиле SRFI 89).

Другие вопросы по тегам