; three homework problems

(define (sum-odd n)
  (if (zero? n) 0
    (+ (sum-odd (- n 1)) n n -1)))

(display (sum-odd 5)) (newline)

(define (sum-odd-aux n sum)
  (if (zero? n) sum
    (sum-odd-aux (- n 1) (+ sum n n -1))))

(define (sum-odd n)
  (sum-odd-aux n 0))

(display (sum-odd 5)) (newline)

(define (sum-odd n) (* n n))

(display (sum-odd 5)) (newline)

(define (freq str)
  (let ((counts (make-vector 256 0)))
    (do ((i 0 (+ i 1)))
        ((= i (string-length str)))
      (let ((c (char->integer (string-ref str i))))
        (vector-set! counts c (+ (vector-ref counts c) 1))))
    (do ((i 0 (+ i 1))) ((= 256 i))
      (when (positive? (vector-ref counts i))
        (display (integer->char i)) (display #\tab)
        (display (vector-ref counts i)) (newline)))))

(freq "hello")

(define (uniq-c eql? xs)
  (if (null? xs) xs
    (let loop ((xs (cdr xs)) (prev (car xs)) (k 1) (result '()))
      (cond ((null? xs) (reverse (cons (cons prev k) result)))
            ((eql? (car xs) prev) (loop (cdr xs) prev (+ k 1) result))
            (else (loop (cdr xs) (car xs) 1 (cons (cons prev k) result)))))))

(define (freq str)
  (uniq-c char=? (sort (string->list str) char<?)))

(display (freq "hello")) (newline)

(define (caesar n str)
  (define (rotate c)
    (if (not (and (char<=? #\A c) (char<=? c #\Z))) c
      (integer->char (+ (modulo (+ (char->integer c) n -65) 26) 65))))
  (list->string (map rotate (string->list str))))

(display (caesar 5 "ATTACK AT DAWN")) (newline)
(display (caesar -5 "FYYFHP FY IFBS")) (newline)