Search code examples
recursionschemearithmetic-expressions

Arithmetic Recursion


I'm a beginner to scheme and I'm trying to learn some arithmetic recursion. I can't seem to wrap my head around doing this using scheme and producing the correct results. For my example, I'm trying to produce a integer key for a string by doing arithmetic on each character in the string. In this case the string is a list such as: '(h e l l o). The arithmetic I need to perform is to:

For each character in the string do --> (33 * constant + position of letter in alphabet) Where the constant is an input and the string is input as a list.

So far I have this:

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

I am trying to test a simple string (test '( a b ) 2) but I cannot produce the correct result. I realize my recursion must be wrong but I've been toying with it for hours and hitting a wall each time. Can anyone provide any help towards achieving this arithmetic recursion? Please and thank you. Keep in mind I'm an amateur at Scheme language :)

EDIT I would like to constant that's inputted to change through each iteration of the string by making the new constant = (+ (* 33 constant) (alphaTest (car string))). The output that I'm expecting for input string '(a b) and constant 2 should be as follows:

1st Iteration '(a): (+ (* 33 2) (1)) = 67 sum = 67, constant becomes 67
2nd Iteration '(b): (+ (* 33 67) (2)) = 2213 sum = 2213, constant becomes 2213

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

Solution

  • Is this what you're looking for?

    (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, is the procedure supposed to work on strings containing characters other than letters—like numerals or spaces? In that case, position-in-alphabet might yield some surprising results. To make a decent key, you might just call char->integer and not bother with position-in-alphabet. char->integer will give you a different number for each character, not just each letter in the alphabet.