Search code examples
schemeracketaccumulator

Accumulative Recursion to Replace String Characters With Numbers in Scheme


The question is the following:

  1. Use accumulative recursion
  2. Function consumes a string and produces a new string
  3. Each character that appears consecutively is replaced by the letter and the number of times of its consecutive appearances
  4. Example: "hellooo" => "hel2o3"
  5. Question is University Level Based

I've tried the following:

(define (abbreviate str)
  (local [(define str-lst (string->list str))
          (define (count-duplicate lst char count)
            (cond
              [(empty? lst) count]
              [(equal? (first lst) char)
               (count-duplicate (rest lst)
                                (first lst)
                                (add1 count))]
              [else (count-duplicate (rest lst)
                                     (first lst)
                                     count)]))
          (define (build-string lst)
            (cond
              [(empty? lst) empty]
              [else (cons (first lst)
                          (cons (string->list (number->string 
                                         (count-duplicate (rest lst)
                                                          (first lst) 1)))
                          (build-string (rest lst))))]))]


    (build-string str-lst)))

But I get the result:

(list #\h (list #\4) #\e (list #\4) #\l (list #\4) #\l (list #\3) #\o (list #\3) #\o (list #\2) #\o (list #\1))

Any help?


Solution

  • I assume, since this is a "university level" question, you're actually learning racket for a class - I assume then that you are using the Advanced Student Language Pack.

    My understanding of accumulative recursion is that the program uses some type of memory. Here is a solution I worked on. It's a complete solution to the question and is completely compatible with the Advanced Student Language Pack; code's a bit clunky but you're welcome to refine it of course.

    ;; abbreviate : string -> string
    ;; consumes a string and produces a new string, with all occurences of
    ;; sequences of repeating characters reduced to 1 character and the 
    ;; number of times the character repeats
    ;; Example
    ;; (abbreviate "oooo) should be "o4"
    ;; (abbreviate "thiis iss a teesstt") should be "thi2s is2 a te2s2t2"
    ;; (abbreviate "magic") should be "magic"
    ;; Definitions:
    (define (abbreviate a-string)
      (local ((define memory empty)
              (define (count-dupes b)
                (cond ((empty? b) 0)
                      ((duplicate? b) (+ 1 (count-dupes (rest b))))
                      (else 0)))
              (define (skip-dupes c n)
                (cond ((= n 0) c)
                      ((empty? c) c)
                      (else (skip-dupes (rest c) (sub1 n)))))
              (define (duplicate? a)
                (equal? (first a) (first memory)))
              (define (load lst)
                (begin (set! memory (cons (first lst) memory)) (abbreviate-x (rest lst))))
              (define (abbreviate-x lst)
                (cond ((empty? lst) lst)
                      ((empty? memory) (cons (first lst) (load lst)))
                      ((duplicate? lst) (cons (+ 1 (count-dupes lst)) 
                                              (abbreviate-x 
                                                (skip-dupes lst (count-dupes lst)))))
                      (else (cons (first lst) (load lst)))))
              (define (string-adapt d)
                (cond ((empty? d) empty)
                      ((number? (first d)) (append (string->list (number->string (first d)))
                                                   (string-adapt (rest d))))
                      (else (cons (first d) (string-adapt (rest d)))))))
        (list->string (string-adapt (abbreviate-x (string->list a-string))))))
    ;; Test
    (check-expect (abbreviate "hellooo wooorldd") "hel2o3 wo3rld2"
    

    Kind Regards