2015-02-21 4 views
0

Я пытаюсь программным образом увеличивать чисто алфавитную строку в Схеме.Приращение алфавитной строки в схеме

Как и этот «МА», затем «МБ», и когда он достигнет «МЗ», он должен стать «МАА» и т. Д. До «МЗЗ», а затем он должен стать «МААА» и т. Д. «М «нужно добавить в качестве префикса для той работы, которую я делаю.

Я посмотрел на этот вопрос: Incrementing alphabets и это именно то, что я хочу.

Однако у меня нет абсолютно никакой идеи, с чего начать. Для начала я даже не уверен, как обращаться с ASCII в схеме. Я не ожидаю всего кода, но я был бы признателен, если бы получил несколько советов.

ответ

2

Вот моя реализация. Обратите внимание, что вам необходимо загрузить SRFI 1, который обеспечивает unfold-right:

(define letters "ABCDEFGHIJKLMNOPQRSTUVWXYZ") 

(define (number->letters num) 
    (unfold-right negative? 
       (lambda (i) (string-ref letters (remainder i 26))) 
       (lambda (i) (- (quotient i 26) 1)) 
       num)) 

(define (number->tag num) 
    (list->string (cons #\M (number->letters num)))) 

Примеры:

> (number->tag 0) 
"MA" 
> (number->tag 18277) 
"MZZZ" 
> (number->tag 18278) 
"MAAAA" 

ОП попросил объяснения того, что делает код. Таким образом, при понимании того, что ОП уже понимает алгоритм (поскольку они уже связаны с ним), то, что в принципе осталось, - это операция разворачивания.

Сложите и разворачивайте, чтобы объяснить, и я не хочу срывать это сообщение, объясняя их, но можно «развернуть» разворачивание в эквивалентный цикл (используя те же имена переменных, что и SRFI 1 reference implementation из unfold-right), чтобы выразить то, что происходит:

(define (number->letters num) 
    (let lp ((seed num) (ans '())) 
    (if (negative? seed) 
     ans 
     (lp (- (quotient seed 26) 1) 
      (cons (string-ref letters (remainder seed 26)) ans))))) 

в основном, это создает список, справа налево, используя (string-ref letters (remainder seed 26)) каждой итерации (где seed является num в начальной итерации). Значение seed затем обновляется до (- (quotient seed 26) 1) для следующей итерации. Список останавливается, когда верно значение (negative? seed).

Тогда вы можете спросить, почему вместо цикла нужно использовать развертку. В принципе, в функциональном программировании, когда «концепция» может быть выражена в терминах более высокого уровня (например, для каждого, на карте, на фильтрацию, сворачивание или разворачивание), использование этих терминов помогает другим программистам понять, что делает код. Это немного напоминает «шаблоны проектирования» (как это обычно используется в объектно-ориентированном программировании) в контексте функционального программирования. :-)

+0

Спасибо! Но не могли бы вы предоставить мне объяснение того, что на самом деле делает код? –

+0

Я добавил многообещающее объяснение. Лемм знает, есть ли что-то еще, что вам нужно объяснить. :-) –

+0

У меня получилось :) Однако я хотел бы улучшить свое понимание складок и разворачиваться и на карте. Не могли бы вы предоставить мне некоторые ссылки, где есть простое объяснение? Я новичок в функциональном программировании. –

Смежные вопросы