ZETT

;; Transform a string: replace '[' with '(' and append one ')' per '[' at end of each line.

(define (split-lines s)
  (let loop ((i 0) (len (string-length s)) (cur "") (acc '()))
    (if (>= i len)
        (reverse (cons cur acc))
        (let ((ch (string-ref s i)))
          (if (char=? ch #\newline)
              (loop (+ i 1) len "" (cons cur acc))
              (loop (+ i 1) len (string-append cur (string ch)) acc))))))

(define (count-char s target)
  (let loop ((i 0) (len (string-length s)) (cnt 0))
    (if (>= i len)
        cnt
        (let ((ch (string-ref s i)))
          (loop (+ i 1) len (if (char=? ch target) (+ cnt 1) cnt))))))

(define (replace-brackets s)
  (let loop ((i 0) (len (string-length s)) (out ""))
    (if (>= i len)
        out
        (let ((ch (string-ref s i)))
          (loop (+ i 1) len
                (string-append out (string (if (char=? ch #\[) #\( ch))))))))

(define (process-line line)
  (let ((n (count-char line #\[))
        (repl (replace-brackets line)))
    (string-append repl (make-string n #\)))))

(define (join-lines lines)
  (let loop ((lst lines) (out ""))
    (if (null? lst)
        out
        (let ((next (if (string=? out "") (car lst) (string-append out "\n" (car lst)))))
          (loop (cdr lst) next)))))

(define (compile s)
  (join-lines (map process-line (split-lines s))))