University of Virginia, Department of Computer Science CS200: Computer Science, Spring 2002

 Problem Set 4: The Lorenz Cipher and the Postman's ComputerSelected Answers

 Honor Code Reminder: If you are currently taking CS200, it is a violation of the course pledge to look at Problem Set answers and discussions from previous years. Please don't do it.

 Question 1: Define the xor function that takes two bits as parameters and evaluates to 1 if exactly one of the parameters is 1 and evaluates to 0 otherwise. Your xor function should produce these evaluations:    > (xor 0 0)    0    > (xor 0 1)    1    > (xor 1 0)    1    > (xor 1 1)    0

```(define (xor a b) (if (eq? a b) 0 1))
```
 Question 2:a. Write a function string-to-baudot that takes a string and transforms it into a list of Baudot codes. b. Write the inverse function, baudot-to-string, that takes a list of lists of baudot codes and transforms it back into a string.

The best answers used map, although it was reasonable to define this recursively also. Here's Jacques Fournier's answer:

```(define (string-to-baudot string)
(map char-to-baudot (string->list string)))

(define (baudot-to-string baudot-list)
(list->string (map baudot-to-char baudot-list)))
```
 Question 3: To rotate our wheels we will take the number at the front of the list and move it to the back. The first number in the list will represent the current position of the wheel. a. Define a function rotate-wheel that takes one of the wheels as a parameter. It should return the wheel rotated once. For example, (rotate-wheel (list 1 0 0 1 0)) should evaluate to (0 0 1 0 1). Although all the wheels in our simulated Lorenz cipher machine have five bits, your rotate-wheel procedure should work for any length list. b. Define a function rotate-wheel-by that takes a wheel as the first parameter and a number as the second. The function should return the wheel list rotated by the number passed in. For example, (rotate-wheel-by (list 1 0 0 1 0) 2) should evaluate to (0 1 0 1 0) and (rotate-wheel-by wheel 5) should evaluate to wheel.

```(define (rotate-wheel wheel)
(append (cdr wheel) (list (car wheel))))

(define (rotate-wheel-by wheel n)
(if (= n 0) wheel
(rotate-wheel-by (rotate-wheel wheel) (- n 1))))
```
Another approach is to remember n-times from PS2. Here is Katie Winstanley's answer:
```(define (rotate-wheel-by wheel n)
((n-times rotate-wheel n) wheel))
```
 Question 4: a. Define a function rotate-wheel-list that takes a list of wheels (like K-wheels) as a parameter and evaluates to a list of wheels where each of the wheels in the parameter list of wheels has rotated once. For example, (rotate-wheel-list K-wheels) should evaluate to    ((1 0 1 0 1) (1 0 0 1 0) (0 0 1 0 1) (1 1 0 1 1) (0 0 0 1 1)). b. Define a function rotate-wheel-list-by that takes a list of wheels and a number as parameters, and evaluates to a list of where where each of the wheels in the parameter list of wheels has rotated the number parameter times. For example, (rotate-wheel-list-by K-wheels 5) should evaluate to the same list as K-wheels.

```(define (rotate-wheel-list wheellist) (map rotate-wheel wheellist))

(define (rotate-wheel-list-by wheellist n)
((n-times rotate-wheel-list n) wheellist))
```
Another approach is to use rotate-wheel-by, as was done by Jeff Taylor:
```(define (rotate-wheel-list-by wheels n)
(map (lambda (wheel) ((rotate-wheel-by wheel) n)) wheels))
```
 Question 5: Define a function wheel-encrypt that takes a Baudot-encoded letter (a list of 5 bits) and a list of wheels as parameters. The function should xor each bit of the Baudot list with the first value of its respective wheel and return the resulting list. For example, (wheel-encrypt (list 0 0 0 1 1) K-wheels) should produce (1 0 1 0 0).

```(define (wheel-encrypt baudot-letter wheel-list)
(map xor baudot-letter (map car wheel-list)))
```
 Question 6: a. Define a function called do-lorenz that takes a list of Baudot values, the K wheels, S wheels and M wheel. The function should encrypt the first Baudot code with the K and S wheels, then recursively encrypt the rest of the Baudot codes with the wheels rotated. The function should return the encrypted values in the form of a list of Baudot values. b. Define a function lorenz that takes four parameters: a string and three integers. The integers represent the starting positions of the three wheels, respectively. The function should call do-lorenz with the string converted to Baudot and the wheels rotated to the correct starting positions. The function should return the ciphertext in the form of a string.

```(define (do-lorenz code k-wheels s-wheels m-wheel)
(if (null? code) code
(cons
(wheel-encrypt (wheel-encrypt (car code) k-wheels) s-wheels)
(do-lorenz (cdr code)
(rotate-wheel-list k-wheels)
(if (= (car m-wheel) 1) (rotate-wheel-list s-wheels) s-wheels)
(rotate-wheel m-wheel)))))

(define (lorenz string n1 n2 n3)
(if (null? string) string
(baudot-to-string
(do-lorenz (string-to-baudot string)
(rotate-wheel-list-by k-wheels n1)
(rotate-wheel-list-by s-wheels n2)
(rotate-wheel-by m-wheels n3)))))
```
 Question 7: Define a function called solve-lorenz that takes a ciphertext and evaluates lorenz on the ciphertext for all 125 possible starting positions. It may be helpful to use the function printf that will print out a string to the interactions window.

```(define (solve-lorenz string position1 position2 position3)
(if (<= position1 5)
(if (<= position2 5)
(if (<= position3 5)
(string-append (lorenz string position1 position2 position3)
(solve-lorenz string position1 position2 (+ 1 position 3)))
(solve-lorenz string position1 (+ 1 position2) 1))
(solve-lorenz string (+ 1 position1) 1 1))
""))
```
```(define (solve-lorenz ctext)