Номер схемы для списка

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


person Matt    schedule 11.10.2012    source источник
comment
Используйте по модулю, это не так сложно :) я не уверен, что вы подразумеваете под «каждым местом». Вы просто извлекаете значащую цифру по модулю 10, делите число на 10 и повторяете (возможно, рекурсивно).   -  person piokuc    schedule 11.10.2012
comment
Эй, спасибо piokuc, имеет смысл использовать деление, чтобы продолжать уменьшать число.   -  person Matt    schedule 11.10.2012


Ответы (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)
person Óscar López    schedule 11.10.2012
comment
Спасибо за "пустое" решение - person demas; 11.10.2012

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

(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)

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

person demas    schedule 11.10.2012
comment
вы можете сохранить порядок, используя именованный let внутри num2list вместо внешнего помощника. Основной код будет таким же, но он будет содержаться в функции, которая нуждается в помощи. Единственная причина иметь его на верхнем уровне - это если у вас есть более одной функции, которая нуждается в этой конкретной помощи. - person itsbruce; 11.10.2012
comment
Я обновил свой ответ и спрятал вспомогательную функцию внутри основной. Но мне не удалось использовать 'let' или 'лямбда' в этом коде :( Я рекурсивно вызываю num2list-helper и не знаю, как вызвать рекурсивно анонимную функцию. Поэтому я буду благодарен, если вы поделитесь этим кодом для меня. . - person demas; 11.10.2012

Я не сторонник ручного зацикливания, поэтому вот решение, основанное на развертывании (загрузить 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) синтаксис.

person Chris Jester-Young    schedule 11.10.2012