0

Define a procedure encrypt that takes three strings: a message to be encrypted and two alphabets, which we will call regular and encrypted. The alphabet strings are both the same length and they do not contain duplicates. For each character in the message, look it up in regular and, if you find it, convert it to the character in the corresponding location of encrypted. For example, if the regular is abc and the encrypted is def, that means that an a in the message will encode as a d, a b encodes as an e, and a c encodes as an f.

i wrote my code as follow:

(define encrypt
  (lambda (message regular encrypted)
    (define help
      (lambda (ls1 ls2 ls3)
         (if (null? ls1) '()
           (if (and (null? ls2) (null? ls3)) ls1
              (if (equal? (car ls1) (car ls2)) 
                  (cons (car ls3) (help (cdr ls1) ls2 ls3))
                  (help ls1 (cdr ls2) (cdr ls3))))))
    (list->string (help 
                    (string->list message) 
                    (string->list regular) 
                    (string->list encrypted)))))

I have been trying to get a running. but the result returns Exception in car: () is not a pair

I quite check it many times, but I didn't what I should change. is there anyone can help me?

  • I'm not getting the error stated in the question's title, but notice that the parentheses in the code are wrong, you're not properly closing `help`. That's the least of your problems though, because the procedure as it is won't work, see my answer for more information – Óscar López Oct 31 '13 at 03:03

3 Answers3

3

Óscar López's answer pointed out some of the problems that you might be having in this code, but I think it's important to specifically address the error message that you mentioned: () is not a pair. This means that you're calling a function that expects a pair (so typical candidates would be car and cdr on an empty list. Let's take a look at your code and see where this could happen:

(define help
      (lambda (ls1 ls2 ls3)
         (if (null? ls1) '()                                 ; a
           (if (and (null? ls2) (null? ls3)) ls1             ; b
              (if (equal? (car ls1) (car ls2))               ; c
                  (cons (car ls3) (help (cdr ls1) ls2 ls3))  ; d 
                  (help ls1 (cdr ls2) (cdr ls3))))))         ; e
  1. Lines a and b don't call any functions that expect a pair, so you shouldn't run into this problem there.
  2. In line c, you do (car ls1) and (car ls2). Line a ensured that ls1 isn't (), but ls2 still could be, since b only checked that it's not the case that both ls2 and ls3 are (); either one alone still could be.
  3. In line d, you've got (car ls3) and (cdr ls1). Line a ensured that ls1 isn't (), but ls2 still could be for the same reason given in the previous case.
  4. Line e has (cdr ls2) and (cdr ls3), and both of these could cause a problem, because either one of them (but not both) could be ().

Though your title didn't say it, your question mentioned that this is actually happening with car, which means that it's not happening in e, which leaves c and d. It's either happening in (car ls2) in c or in (car ls3) in d.

If you're using Dr. Racket to run your code, the IDE should highlight the place where the bad call happened (something like what's shown in the screenshot in this answer).

Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
2

The help function is not doing what you imagine, you actually need two helpers:

  • One for iterating over the message and "encrypting" each character in it, for that it uses the next function as helper
  • And one for "encrypting" a single character, that takes care of finding the encrypted character corresponding to a plaintext character

If you don't do the above, you'll discover that not all the characters are being replaced, because you're traversing the regular/encrypted lists only once, but for the algorithm to work you have to traverse them once for each character in the input message.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
0
(define (encrypt message regular encrypted)
   (letrec ((key 
              (lambda (reg enc)
                 (if (null? reg) 
                     '()
                     (cons (cons (car reg) (car enc)) 
                           (key  (cdr reg) (cdr enc))))))
             (keys (key (string->list regular) 
                        (string->list encrypted))))
    (list->string
      (let loop ((message (string->list message)))
         (if (null? message) 
             '()
              (cons (cdr (assoc (car message) keys)) 
                    (loop (cdr message))))))))
WorBlux
  • 1,423
  • 11
  • 20
  • 1
    Can you elaborate? This doesn't explain _why_ OP was getting a "not a pair" error, and, while it might be an example of what OP should change _to_, it doesn't really explain any of the problems with the original code, or why this is a better alternative. – Joshua Taylor Oct 31 '13 at 03:36