2013-04-10 2 views
0

Я начинаю рисовать, и я пытаюсь изучить некоторую арифметическую рекурсию. Кажется, я не могу оборачивать голову, делая это с помощью схемы и получаю правильные результаты. В моем примере я пытаюсь создать целочисленный ключ для строки, выполнив арифметику для каждого символа в строке. В этом случае строка представляет собой список, такой как: '(h e l l o). Арифметику, которую мне нужно выполнить, - это:Арифметическая рекурсия

Для каждого символа в строке do -> (постоянная 33 + позиция буквы в алфавите) Где константа - это вход, а строка вводится как список.

До сих пор у меня есть это:

(define alphaTest 
    (lambda (x) 
    (cond ((eq? x 'a) 1) 
      ((eq? x 'b) 2)))) 

(define test 
    (lambda (string constant) 
     (if (null? string) 1 
     (* (+ (* 33 constant) (alphaTest (car string))) (test (cdr string))) 

Я пытаюсь проверить простую строку (тест «(а б) 2), но я не могу произвести правильный результат. Я понимаю, что моя рекурсия должна быть неправильной, но я много раз общался с ней и каждый раз нажимал на стену. Может ли кто-нибудь помочь в достижении этой арифметической рекурсии? Пожалуйста и спасибо. Имейте в виде, я любитель на Схеме языке :)

EDIT Я хотел бы постоянная, которая вводится для изменения через каждую итерацию строки, сделав новый постоянную = (+ (* 33 константы) (alphaTest (автомобильная строка))). Результат, который я ожидаю для входной строки '(ab) и константы 2, должен быть следующим:

1-я итерация' (a): (+ (* 33 2) (1)) = 67 sum = 67, постоянные становится 67
2nd итерации «(б): (+ (* 33) 67 (2)) = 2213 сум = 2213, константа становится 2213

(test '(a b) 2) => 2280 
+0

Вы описали, что делать с каждым символом строки, но не с тем, как объединить результаты для каждого символа, чтобы предоставить окончательное одиночное число. Кроме того, это поможет, если вы описали ожидаемый результат '(test '(# \ a # \ b) 2)' – GoZoner

+0

Я обновил вопрос. Спасибо GoZoner. – Sixers17

ответ

1

это то, что вы ищете?

(define position-in-alphabet 
    (let ([A (- (char->integer #\A) 1)]) 
    (λ (ch) 
     (- (char->integer (char-upcase ch)) A)))) 

(define make-key 
    (λ (s constant) 
    (let loop ([s s] [constant constant] [sum 0]) 
     (cond 
     [(null? s) 
      sum] 
     [else 
      (let ([delta (+ (* 33 constant) (position-in-alphabet (car s)))]) 
      (loop (cdr s) delta (+ sum delta)))])))) 

(make-key (string->list) 2) => 0 
(make-key (string->list ab) 2) => 2280 

BTW, должна ли процедура работать со строками, содержащими символы, отличные от буквенных цифр или пробелов? В этом случае position-in-alphabet может дать некоторые неожиданные результаты. Чтобы сделать приличный ключ, вы можете просто позвонить char->integer и не беспокоиться о position-in-alphabet. char->integer даст вам другое число для каждого символа, а не только каждую букву в алфавите.

+0

Спасибо за ваш быстрый ответ Бен! Чтобы ответить на ваш вопрос, я не учитываю специальные символы в строке, только буквы. Ваш код работает, однако я забыл упомянуть, что мне нужно постоянно обновлять константу, устанавливая ее равной сумме каждой итерации. Я попробовал добавить еще один аргумент в цикл (x constant), а затем, когда вы вызываете цикл, добавьте (* 1 sum), чтобы передать как x, но при этом он видит сумму при 0. Как это сделать, чтобы я мог передать результат суммы в качестве новой константы? – Sixers17

+1

Теперь я думаю, что понимаю. В этом случае вы можете рассчитать сумму, используя текущую константу, и просто передать новую сумму в качестве новой константы во всех, кроме первой итерации. Я отредактировал решение для иллюстрации. Или, если константа должна быть ключом для строки нулевой длины, то решение Ankur является правильным. –

+0

Спасибо за обновление вашего решения. То, что вы мне дали, очень полезно и высоко ценится. Я почти полностью согласен с этим, но то, что я имел в виду с постоянным обновлением, заключается в том, что я не хочу, чтобы константа была: новая константа + сумма, а скорее просто новая константа, не добавляя себя к сумме. Я объясню это, обновив исходный вопрос с ожидаемыми результатами. – Sixers17

1
(define position-in-alphabet 
    (let ([A (- (char->integer #\A) 1)]) 
    (lambda (ch) 
     (- (char->integer (char-upcase ch)) A)))) 


(define (test chars constant) 
    (define (loop chars result) 
    (if (null? chars) 
     result 
     (let ((r (+ (* 33 result) (position-in-alphabet (car chars))))) 
      (loop (rest chars) (+ r result))))) 
    (loop chars constant)) 

(test (list #\a #\b) 2) 
0

Вот решение (в MIT-Гну Scheme):

(define (alphaTest x) 
    (cond ((eq? x 'a) 1) 
    ((eq? x 'b) 2))) 

(define (test string constant) 
    (if (null? string) 
     constant 
     (test (cdr string) 
     (+ (* 33 constant) (alphaTest (car string)))))) 

Примеры выходов:

(test '(a) 2) 
;Value: 67 

(test '(a b) 2) 
;Value: 2213 

Я просто преобразование константы в каждом рекурсивном вызове и возвращает его в качестве значения когда строка заканчивается.

Я избавился от лямбда-выражений, чтобы было легче увидеть, что происходит. (Кроме того, в этом случае лямбда-формы на самом деле не нужны.)


Ваше определение процедуры испытаний, кажется, сломана:

(define test 
    (lambda (string constant) 
    (if (null? string) 
    1 
    (* (+ (* 33 constant) 
      (alphaTest (car string))) 
     (test (cdr string))) 

Ваш код гласит:

  • Создайте процедуру test, которая принимает два аргумента; string и constant.

  • Если string имеет значение null, значение пропуска 1, чтобы завершить рекурсию. В противном случае, необходимо умножить следующие значения:

    • терм х т = (33 * постоянная) + (AlphaTest (автомобиль строка)), а
    • терм у, то есть выходной рекурсивно прохождения (CDR строка) к процедуре испытания

Я не вижу, как член у будет оценивать, как «тест» нужны два аргумента. Мой переводчик сделал ошибку. Кроме того, скобки не сбалансированы. И есть что-то странное в отношении вычислений, на которые я не могу положиться. Попробуйте сделать бумажную оценку, чтобы увидеть, что можно вычислить при каждом рекурсивном вызове.

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