Reputation: 137
Ok, I took scheme last semester, and I Know you can't be so good at scheme within one semester. A friend asked me how I could count the number of times a certain digit comes in a number. I know how to do if it was a list. At first I thought it was a simple use of either inbuilt quotient or remainder, but didnt end up what it seemed like to me. For instance, how can I count number of times five appears in a number: (numfives 125458563) should return 3. Any help is appreciated.
P.s: I am not helping him with his hw, I am doing this for myself. I like challenges.
Upvotes: 2
Views: 966
Reputation: 235984
Here's a possible way: convert the number
parameter to a list of chars and count the number of chars equal to the char corresponding to the digit
received as a parameter:
(define (num-digits number digit)
(let ((n (number->string number))
(d (integer->char (+ (char->integer #\0) digit))))
(count (lambda (x) (char=? x d))
(string->list n))))
Another way to write the above procedure, shorter but harder to read:
(define (num-digits number digit)
(count (curry char=? (integer->char (+ (char->integer #\0) digit)))
(string->list (number->string number))))
Yet another alternative would be to process each digit in turn by means of arithmetic operations as in @ChrisJester-Young's answer, but taking into account the edge case where both the number and the digit are exactly zero, and avoiding the redefinition of the built-in count
procedure - also bear in mind that this will only work for integer numbers >= 0 and in base 10. Here's how:
(define (num-digits number digit)
(if (= number digit 0)
1
(let loop ((num number)
(counter 0))
(cond ((zero? num)
counter)
((= digit (remainder num 10))
(loop (quotient num 10) (add1 counter)))
(else
(loop (quotient num 10) counter))))))
The string-based solutions above might seem a bit clunky, but are shorter to write and have the additional advantages of working for negative numbers, numbers with decimals, numbers in bases different from 10, etc. Anyway, this will work in any version:
(num-digits 125458563 5)
> 3
And this will work with the string-based versions:
(num-digits -123.1234152 1)
> 3
Upvotes: 1
Reputation: 222973
I dislike all of the string-based solutions.
The best way to do it, in my view, is to look at each digit by dividing (and modding) by 10 at each stage, then comparing. Example:
(define (count-digit num digit)
(let loop ((num num)
(count 0))
(if (zero? num) count
(loop (quotient num 10)
(+ count (if (= digit (remainder num 10)) 1 0))))))
Upvotes: 2
Reputation: 5932
Using string->list
to turn the string into a list of characters. Then proceed as you would with a list, which you say you already know how to do. (You can use various formatting functions to convert the number to a string.)
Upvotes: 3
Reputation: 5655
Than convert a number to a list and than find out number of a times a digit is appearing in a number. For converting a number into a list See this example.
Upvotes: 0