#scheme #racket
#схема #ракетка
Вопрос:
Как мне преобразовать число в список цифр?
В настоящее время я делаю:
;; (num->list 12345) -> '(1 2 3 4 5)
(define (num->list n)
(local
((define (num->list n)
(map (lambda (c)
(char->num c))
(string->list (number->string n))))
(define (char->num c)
(- (char->integer c) 48)))
(num->list n)))
но хотелось бы знать, есть ли лучший способ.
Ответ №1:
Вот как я бы сделал это в Racket:
(require srfi/1 srfi/26)
(define (digits->list num (base 10))
(unfold-right zero? (cut remainder <> base) (cut quotient <> base) num))
Это та проблема, для которой unfold
была разработана. 😀
Ответ №2:
Это функция digits моей стандартной прелюдии:
(define (digits n . args)
(let ((b (if (null? args) 10 (car args))))
(let loop ((n n) (d '()))
(if (zero? n) d
(loop (quotient n b)
(cons (modulo n b) d))))))
Ваша версия функции перемещается взад-вперед между строками и числами; моя версия чисто арифметическая. Моя версия также предусматривает базы, отличные от десятичной.
Комментарии:
1. Тьфу, ручная распаковка аргументов. 🙁 К счастью, Racket реализует необязательные аргументы в стиле SRFI-89 (как показано в моем сообщении), и этот вопрос помечен как специфичный для Racket. 😀
Ответ №3:
«Лучше» всегда доступно для определения, но немного более прямым / очевидным способом было бы что-то вроде этого:
(define (int->list n) (if (zero? n) `()
(append (int->list (quotient n 10)) (list (remainder n 10)))))
Что касается того, является ли это «хорошим», «плохим», «лучше» и т.д., Я думаю, это зависит от того, что вы хотите. Нет сомнений в том, что вы можете найти код, который более эффективен, более универсален и т.д. (на самом деле, @user448810 уже опубликовал некоторые). Это скорее то, что я бы назвал примером кода для чего-то вроде введения в схему — акцент делается на простоте и легкости понимания / объяснения1. Я ожидаю, что почти любой, кто имеет абсолютный минимум знаний о каком-либо языке, подобном Lisp, и общее представление о том, как выполняется такое числовое преобразование, должен быть в состоянии разобраться во всем, что здесь происходит, довольно быстро / легко.
- Даже за счет неправильного поведения для некоторых угловых случаев — например, как есть, он даже пытается корректно работать только для строго положительных чисел.
Комментарии:
1. За исключением того, что
append
list
является антишаблоном в программировании схем (cons
reverse
гораздо более ортодоксально, хотя в этом примере нетreverse
необходимости). Итак, я бы не счел это подходящим примером «введение в схему». 🙁
Ответ №4:
;(n-to-list n) convert Num n into a list of its digits
;n-to-list: Num -> (listof Num)
(define (n-to-list n)
(cond
[(= n 0) empty]
[else (cons (remainder n 10) (n-to-list (quotient n 10)))]))