views:

148

answers:

3

I am trying to write a function that evaluates to the number of distinct characters in the input string str. So for example (distinct-char "eeeiicczz") would return 4. I need some help with my code. This is what I have.

(define string-contains
  (lambda (str char)
    (if (equal? str "")
        #f
        (if (char=? (string-ref str 0) char)
            #t
            (if (not (char=? (string-ref str 0) char))
                (string-contains (substring str 1 (string-length str)) char))))))

(define unique-chars
  (lambda (str)
    (cond
      ((equal? str "") "")
      ((equal? (string-length str) 1) (string-ref str 0))
      (else
      (if (equal? (string-contains (substring str 1 (string-length str)) (string-ref str 0)) #t)
          (unique-chars (substring str 1 (string-length str)))
          (string-append (substring str 0 1) (substring str 1 (string-length str))))))))

(define distinct-char
  (lambda (str)
    (string-length (unique-chars str))))

I am limited to using these Built in functions:

(if x y z), (cond ...),  
(read)  
(string-length x)  
(string-ref str x)  
(substring x y) 
(string-append x y)  
(equal? x y), (char=?)  
(remainder x y), (quotient x y)  
(max ...), (min ...)  
(+ x y), (- x y), (* x y), (/ x y)  
(> x y), (< x y), (<= x y), (>= x y) 
(and x y), (or x y), (not x y)  
+2  A: 

Since it's possible to convert a string to a list, it would be much easier to do that and use the built in list functions. (Note: the following code is in Racket. Since it's pretty much Scheme, I'm assuming these functions exist. If they don't check your docs for something similar)

(define (distinct-char str)
  (length (remove-duplicates (string->list str))))

Here is a template you can fill in. Replace the comments with what you think should happen in each situation. Good luck!

(define (empty-string? str) 
  ( #| What property does an empty string have? Add a simple boolean expression here. |# )

 (define (char-exists? str char)
  (cond
    [(empty-string? str) ( #| If the string is empty, does the character exist? |# )]
    [else ( #| Check the first character in the string. If it is what we're looking for
               we're done! If it's not call this function on the rest of the string. |# )]))

(define (unique-chars str)
  (cond
    [(empty-string? str) ( #| What should you return if the string is empty? |# )]
    [(equal? (string-length str) 1) ( #| What should you return if the string is one character long? |# )]
    [else ( #| If the character at the beginning of the string exists in the rest of the string, ignore it
               and preform recursion on the rest of the string. If it doesn't, append the character to
               the result of this function on the rest of the string. |# )]))

(define (distinct-char str)
  (string-length (unique-chars str)))
Paul
While you were typing up your answer, he posted his homework restrictions. Clever answer though, assuming remove-duplicates is available (it is not present in my version of Petite Chez Scheme).
erjiang
@erjiang: Ah, that's unfortunate. I'll leave this answer up for Brian to look into it after he is finished with his assignment.
Paul
Do you have any ideas how I can use the given functions to solve this? I need to recur when I check if the first element is equal to the next so it will check the first element with all the elements in the string.
user258875
@Brian: You should follow Daniel Martin's advice. Its essentially what I posted here, except you need to make the functions yourself (and for strings instead of lists).
Paul
@Brian: There, I've added a simple template to get you started. Mind the spaces, SOs code formatting only likes C#.
Paul
A: 

You can keep and pass along a list of every distinct character that you've come across before. That way, every time you check a new character, you look it up in your list to see if you've already seen it before. If it's not in your list, then it's a new character and you can add it to your list.

Homework question, so I'm not writing code in the answer.

erjiang
+1  A: 

One of the reasons you learn stuff in scheme is it trains you to build up useful building blocks yourself, and then hook those building blocks together.

In this case, the general approach I would recommend is to write a function:

(string-contains str ch)

That returns #t or #f depending on whether or not str contains the character ch, and then use that to define a function:

(unique-chars str)

that returns a string of the unique characters in str (you scan str, building up your answer, and at every spot see if the next character is already in the answer string you're building, and if not, add it to your answer string).

Then, the function you wanted is just

(string-length (unique-chars str))
Daniel Martin
yes but the (unique-chars str) is what I am trying to figure out how to do. All my code works good but it needs to be able to loop through the entire string looking for the unique character.
user258875
Okay, but you'll need that `string-contains` helper function. Then you can write `unique-chars` by observing that `unique-chars` of the empty string is the empty string, and of other strings is either `(unique-chars (substring str 1))` or is the first character of `str` appended to `(unique-chars (substring str 1))`, depending on whether the first character of `str` is in `(unique-chars (substring str 1))`
Daniel Martin
ok so you look at he first char and append it to some other str1 right? then check char 2 if its in the other str1 then do nothing else append it to the str1? something like that.
user258875
Here is my (string-contains) function, look good? ^
user258875
You seem to have the general idea, yeah.Your `string-contains` is slightly more complicated than it needs to be - you can eliminate the final `if` (with the `not`) bit to just have at the end: #t (string-contains (substring str 1 (string-length str)) char)
Daniel Martin
ok so for the function (unique-chars) if the str is 1 character what do I want to do, return the character?
user258875
ok i posted my unique-chars function, is it correct, I am kinda confused by what you mean by "append the character to the result of this function on the rest of the string"
user258875