Мне нужна подпрограмма для моей программы, написанной по схеме, которая принимает целое число, скажем, 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))))
В разных реализациях Scheme используется разный синтаксис для необязательных аргументов; выше используется стиль Racket (и/или стиль SRFI 89) синтаксис.