Exercises in this lecture   Go to the notes, in which this exercise belongs -- Keyboard shortcut: 'u'   Alphabetic index   Course home   

Exercise solution:
Lexicographic photo file naming


Here is my solution. I assume that I know the number of letters in the alphabetic photo names. Alternatively, I could compute the necessary number of letters (by calculating log26(photo-list-lengt) and rounding up), where log26 is the logorithm function with base 26.

; RETURN the lexigraphically next string name (of the same string length as alpha-name-str) relative to alpha-name-str
(define (next-photo-name alpha-name-str)
  (next-photo-name-given-length alpha-name-str (string-length alpha-name-str)))

; The function doing the real work. str-lgt is the string length of the string this-alpha-name-str
(define (next-photo-name-given-length this-alpha-name-str str-lgt)
  (if (or (empty-string? this-alpha-name-str) (<= str-lgt 0))
      ""
      (let* ((this-alpha-name-list (string->list this-alpha-name-str))
             (last-ciffer (list-ref this-alpha-name-list (- str-lgt 1)))
             (first-ciffers (butlast this-alpha-name-list)))
        (if (char<? last-ciffer #\Z)
            (string-append (list->string first-ciffers) (string (integer->char (+ (char->integer last-ciffer) 1))))
            (string-append (next-photo-name-given-length (list->string first-ciffers) (- str-lgt 1)) "A")))))

; Generate a list of n photo names, starting with alpha-name (and all of the same string length as alpha-name)
(define (list-of-photo-names alpha-name n)
  (if (> n 0)
      (cons alpha-name 
            (list-of-photo-names (next-photo-name alpha-name) (- n 1)))
      '()))

; A couple of simple helping functions:

(define (empty-string? str)
  (string=? str ""))

(define (butlast lst)
  (cond ((null? lst)
           (error "Cannot apply butlast on an empty list"))
        ((null? (cdr lst))  ; a list of a single element
           '())
        (else (cons (car lst) (butlast (cdr lst))))))


(define (copy-photos! source-photo-path-list target-photo-path-list source-path destination-path)
  (for-each
    (lambda (source-photo-name target-photo-name)
      (let* ((source (string-append source-path source-photo-name))
             (destination (string-append destination-path target-photo-name)) 
            )
       (if (not (file-exists? destination))
           (copy-file source destination)
           (display-message "Destination file exists" destination "- NO copy made."))
      )
    )
    source-photo-path-list target-photo-path-list))

(copy-photos! 
    some-photo-list
    (list-of-photo-names \"AAA\" (length some-photo-list))
    ...)