What I need to add to count the number of zeros only in the even lists?
For example,
(count-zeroes '((1 1 1) (1 0 0) (1 1 1) (1 0 0)))
4
it is for one list.
(define count-zeroes
(lambda (list)
(cond ((null? list) 0)
((= 0 (car list)) (+ 1 (count-zeroes (cdr list))))
(else (+ 0 (count-zeroes (cdr list))))
)
)
)
(define count-zeroes
(lambda (list)
(cond ((null? list) 0) ; a
((= 0 (car list)) (+ 1 (count-zeroes (cdr list)))) ; b
(else (+ 0 (count-zeroes (cdr list))))))) ; c
If list is initially a list of lists, then (null? list) in line a can be true (when you get to the end of the list), but the condition (= 0 (car list)) in the line b will never be true, since (car list) will always be another list, and 0 isn't a list.
A better way to break this down would probably be to first extract the even positioned sublists, then flatten them into a single list, and then count the zeros in those. That's not the most efficient way to do it (you'll create some intermediate storage), but you should probably implement something like that first, and then gradually optimize it afterward.
It's also worth noting that lists are typically indexed starting with position zero, so the second, fourth, etc., elements in the list are the ones with odd positions, not even positions. Here's the kind of abstraction that might help you in getting started with this kind of approach:
(define first car)
(define rest cdr)
(define list* cons)
(define (odds list)
(if (null? list) '()
(evens (cdr list))))
(define (evens list)
(if (null? list) '()
(list* (first list)
(odds (rest list)))))
(define sample '((0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1)))
;; (display (odds sample))
;; => ((0 1 0) (1 0 0) (1 1 0))
An interesting question. If you are operating on a lists of lists you need to add car-cdr recuresion.
(define (count-zeroes lst) ;;don't override core function names with a variable
(cond ((null? lst) 0)
((pair? (car lst))
(+ (count-zeroes (car lst))
(count-zeroes (cdr lst))))
((= 0 (car lst))
(+ 1 (count-zeroes (cdr lst))))
(else (count-zeroes (cdr lst))))))
No as to only evens you are no longer counting zeros, so a new function name is in order. You could make up a higher order function like this.
(define (count-zeros-of selector lst)
(count-zeroes (selector lst)))
And make a general selector
(define (take-every-Xnth-at-y x y lst)
(cond ((null? lst) '())
((= y 0) (cons (car lst)
(take-every x (- x 1) (cdr lst))))
(else (take-every x (- y 1) (cdr lst)))))
To put it all together
(define (count-zeroes-of-even lst)
(count-zeroes-of
(lambda (lst) ;;to bad we can't do partial application
(take-every-Xnth-at-y 2 1 lst))
lst)
Note each of these parts do their one thing and do it well.
Related
Given a list of the type '('a 1 'b 2 'c 3) I want to calculate the mean of the numbers in the list.
This is what I have done so far: I have written 3 functions that work correctly, one to remove the characters, the other to calculate the sum of the numbers in a list, and the other to find the average. But I do not know how to put them together to solve my problem.
;remove all non numbers from a list:
(define (all-numbers x)
(cond ((null? x) null)
((integer? (car x)) (cons (car x) (all-numbers (cdr x))))
(else (all-numbers (cdr x)))))
;sum the elements of the list
(define (sumlist lst)
(cond ((null? lst) 0)
(( + (car lst) (sumlist (cdr lst))))))
; find the mean of the list
(define (a_mean lst)
(cond ((null? lst) 0)
((/ (sumlist lst) (length lst)))))
(a_mean '(1 2 3))
;find the mean of a mixed list
(define (m_mean lst)
(cond ((null? lst) 0)
((/ (sumlist ((all-numbers lst)) (length (all-numbers lst)))))))
(m_mean '('a 1 'b 2 'c 3))
I get an error in the above code for m_mean. Please help! Thanks.
The answer by Óscar López should fix your problems.
I will now provide a more concise way of solving the same problem:
(define (m-mean lst)
(define all-numbers (filter number? lst)) ; Filter out all the non-numbers.
(if (null? all-numbers)
0 ; The mean is 0 if there are no numbers.
(/ (apply + all-numbers) (length all-numbers)))) ; Calculate mean.
This way, you do not have to explicitly define the all-numbers and sumlist functions.
For starters, some of your cond expressions are missing the else keyword in the final condition - this is mandatory, as you did in all-numbers. Also, in m_mean there are a couple of incorrect brackets; this should fix the errors:
(define (m_mean lst)
(cond ((null? lst) 0)
(else (/ (sumlist (all-numbers lst))
(length (all-numbers lst))))))
Now it works as expected:
(m_mean '(a 1 b 2 c 3))
=> 2
I'm trying to create a function that returns the adjacent duplicates of a list, for example (dups '(1 2 1 1 1 4 4) should return the list (1 4).
This is the code I came up with so far:
(define (dups lst)
(if (equal? (car lst)(car(cdr lst)))
(cons(cdr lst) '())
(dups(cdr lst))))
This function doesn't return all the adjacent duplicates, it only returns the first adjacent duplicates!
How can I fix it so that it returns all the adjacent duplicates of a list?
Thank you.
Once your code finds a duplicate, it stops processing the rest of the list: when the if test is true, it yields (cons (cdr lst) '()). Whether or not it finds a duplicate, it should still be calling dups to process the rest of the list.
Also: if your list has no duplicates, it it going to run into trouble.
Here's a simpler solution than the others posted:
(define (dups lst)
(if (< (length lst) 2)
; No room for duplicates
'()
; Check for duplicate at start
(if (equal? (car lst) (cadr lst))
; Starts w/ a duplicate
(if (or (null? (cddr lst)) ; end of list
(not (equal? (car lst) (caddr lst)))) ; non-matching symbol next
; End of run of duplicates; add to front of what we find next
(cons (car lst) (dups (cdr lst)))
; Othersise keep looking
(dups (cdr lst)))
; No duplicate at start; keep looking
(dups (cdr lst)))))
Basically this boils down to only keeping the elements which are the same as the previous one, but different from the next.
Here's an example implementation using a named let.
(define (adj-dups lst)
(let loop ((lst (reverse (cons (gensym) lst)))
(e-2 (gensym))
(e-1 (gensym))
(acc '()))
(if (null? lst)
acc
(let ((e-0 (car lst)))
(loop (cdr lst)
e-1
e-0
(if (and (eqv? e-2 e-1) (not (eqv? e-1 e-0)))
(cons e-1 acc)
acc))))))
(gensym) comes in handy here because it's a convenient way to initialise the working variables with something that's different from everything else, and filling up the initial list with a dummy element that needs to be added so that we don't miss the last element.
Testing:
> (adj-dups '())
'()
> (adj-dups '(1 1 4 4 1 1))
'(1 4 1)
> (adj-dups '(1 1 1 1 1))
'(1)
> (adj-dups '(1 2 1 1 1 4 4))
'(1 4)
> (adj-dups '(2 3 3 4 4 4 5))
'(3 4)
The most straightforward way I can think of to tackle this is with an internal procedure with an extra variable to keep track what the prior element was and a boolean to track if the element was repeated. You can then do a mutual recurstion between the helper and main function to build the answer one duplicate element at a time.
(define (dups lst)
(define (dups-helper x repeat? L)
(cond ((null? L)
(if repeat?
(list x)
'()))
((equal? x (car L))
(dups-helper x #t (cdr L)))
(else
(if repeat?
(cons x (dups L))
(dups L)))))
(if (null? lst)
'()
(dups-helper (car lst) #f (cdr lst))))
(dups (list 1 1 4 4 5 6 3 3 1))
;Value 43: (1 4 3)
I'm working on implementing a bubble sorting algorithm in Scheme, and I must say that the functional way of programming is a strange concept and I am struggling a bit to grasp it.
I've successfully created a function that will bubble up the first largest value we come across, but that's about all it does.
(bubbleH '(5 10 9 8 7))
(5 9 8 7 10)
I am struggling with the helper function that is required to completely loop through the list until no swaps have been made.
Here's where I am at so far, obviously it is not correct but I think I am on the right track. I know that I could pass in the number of elements in the list myself, but I am looking for a solution different from that.
(define bubbaS
(lambda (lst)
(cond (( = (length lst) 1) (bubba-help lst))
(else (bubbaS (bubba-help lst))))))
Using the bubble-up and bubble-sort-aux implementations in the possible-duplicate SO question I referenced...
(define (bubble-up L)
(if (null? (cdr L))
L
(if (< (car L) (cadr L))
(cons (car L) (bubble-up (cdr L)))
(cons (cadr L) (bubble-up (cons (car L) (cddr L)))))))
(define (bubble-sort-aux N L)
(cond ((= N 1) (bubble-up L))
(else (bubble-sort-aux (- N 1) (bubble-up L)))))
..., this is simple syntactic sugar:
(define (bubbleH L)
(bubble-sort-aux (length L) L))
With the final bit of syntactic sugar added, you should get exactly what you specified in your question:
(bubbleH '(5 10 9 8 7))
=> (5 7 8 9 10)
You can tinker with everything above in a repl.it session I saved & shared.
Here's my own tail-recursive version.
The inner function will bubble up the largest number just like your bubbleH procedure. But instead of returning a complete list, it will return 2 values:
the unsorted 'rest' list
the largest value that has bubbled up
such as:
> (bsort-inner '(5 1 4 2 8))
'(5 2 4 1)
8
> (bsort-inner '(1 5 4 2 8))
'(5 2 4 1)
8
> (bsort-inner '(4 8 2 5))
'(5 2 4)
8
Now the outer loop just has to cons the second value returned, and iterate on the remaining list.
Code:
(define (bsort-inner lst)
(let loop ((lst lst) (res null))
(let ((ca1 (car lst)) (cd1 (cdr lst)))
(if (null? cd1)
(values res ca1)
(let ((ca2 (car cd1)) (cd2 (cdr cd1)))
(if (<= ca1 ca2)
(loop cd1 (cons ca1 res))
(loop (cons ca1 cd2) (cons ca2 res))))))))
(define (bsort lst)
(let loop ((lst lst) (res null))
(if (null? lst)
res
(let-values (((ls mx) (bsort-inner lst)))
(loop ls (cons mx res))))))
For a recursive version, I prefer one where the smallest value bubbles in front:
(define (bsort-inner lst)
; after one pass, smallest element is in front
(let ((ca1 (car lst)) (cd1 (cdr lst)))
(if (null? cd1)
lst ; just one element => sorted
(let ((cd (bsort-inner cd1))) ; cd = sorted tail
(let ((ca2 (car cd)) (cd2 (cdr cd)))
(if (<= ca1 ca2)
(cons ca1 cd)
(cons ca2 (cons ca1 cd2))))))))
(define (bsort lst)
(if (null? lst)
null
(let ((s (bsort-inner lst)))
(cons (car s) (bsort (cdr s))))))
I'm trying to create a function to count all the elements in a list, including the elements of its sublists. initially, to get started, i came up with a basic function myList:
(define myLength
(lambda (L)
(cond
((null? L) 0)
(else (+ 1 (myLength (cdr L)))))))
However, it doesn't help me account for function calls like:
(numAtoms '()) "...should be 0"
(numAtoms '(())) "...should be 0"
(numAtoms '(1 1)) "...should be 2"
(numAtoms '(1 (1 1) 1)) "...should be 4"
(numAtoms '(1 (1 (1 1)) 1)) "...should be 5"
I'm trying to use basic functions like length, null?, and list?.
I think the trick here is to imagine how you can transform your input into the code that you'd want to use to compute the sum. Let's write each of your inputs in the fully expanded form, in terms of cons and '() and whatever other atoms appear in your data:
'() == '()
'(()) == (cons '() '())
'(1 1) == (cons 1 (cons 1 '()))
'(1 (1 1) 1) == (cons 1 (cons 1 (cons 1 '())) (cons 1 '()))
'(1 (1 (1 1)) 1) == ...
Now, look what would happen if you replaced each occurrence of cons with +, and each occurrence of '() with 0, and each occurrence of something that's not '() with 1. You'd have:
'() => 0 == 0
(cons '() '()) => (+ 0 0) == 0
(cons 1 (cons 1 '())) => (+ 1 (+ 1 0)) == 2
(cons 1 (cons 1 (cons 1 '())) (cons 1 '())) => (+ 1 (+ 1 (+ 1 0)) (+ 1 0)) == 4
... => ... == ...
Notice that those sums are exactly the values that you want! Based on this, it seems like you might not want to treat your input as a list so much as a tree built from cons cells. In general, you can map over a tree by specifying a function to apply to the recursive results of processing a pair, and a function to process the atoms of the tree:
(define (treeduce pair-fn atom-fn tree)
(if (pair? tree)
(pair-fn (treeduce pair-fn atom-fn (car tree))
(treeduce pair-fn atom-fn (cdr tree)))
(atom-fn tree)))
You could then implement that mapping of cons to + and everything else to 1 if it's a list and 0 if it's not by:
(define (non-null-atoms tree)
(treeduce +
(lambda (atom)
(if (not (null? atom))
1
0))
tree))
This yields the kinds of results you'd expect:
(non-null-atoms '()) ;=> 0
(non-null-atoms '(())) ;=> 0
(non-null-atoms '(1 1)) ;=> 2
(non-null-atoms '(1 (1 1) 1)) ;=> 4
(non-null-atoms '(1 (1 (1 1)) 1)) ;=> 5
Here is a recursive template you can use:
(define (num-atoms lst)
(cond ((pair? lst) (+ (num-atoms <??>)
(num-atoms <??>)))
((null? lst) <??>) ; not an atom
(else <??>))) ; an atom
This next example uses a helper that has the accumulated value (num) as an argument.
(define (num-atoms lst)
;; locally defined helper
(define (helper num lst)
(cond ((pair? lst) (helper (helper <??> <??>) <??>)) ; recurse with the sum of elements from car
((null? lst) <??>) ; return accumulated value
(else (helper <??> <??>)))) ; recurse with add1 to num
;; procedure starts here
(helper 0 lst))
Hope it helps
Make my-length work for any argument type, list or 'atom'; then the recursive algorithm becomes almost trivial:
(define (my-length l)
(cond ((null? l) 0)
((list? l) (+ (my-length (car l)) (my-length (cdr l))))
(else 1))) ; atom
> (my-length '(1 (1 (1 1)) 1)))
5
I'm having trouble writing a function in Scheme that returns the number of odd numbers in a list without using any assignment statements. I'm trying to use the predicate odd? as well. Any help/tips would be appreciated.
Ex: (odds '(1 2 3 4 5) // returns 3
Also, the list is of integers
Well, if no assignment statements can be used, you can still use the built-in procedures for this. In particular, count will work nicely in Racket:
(define (odds lst)
(count odd? lst))
... But I'm guessing that you're supposed to implement the solution from scratch. Some hints for finding the solution on your own, fill-in the blanks:
(define (odds lst)
(cond (<???> ; if the list is empty
<???>) ; then how many odd numbers are in it?
((odd? <???>) ; if the first element is odd
(<???> (odds <???>))) ; then add one and advance recursion
(else ; otherwise
(odds <???>)))) ; just advance the recursion
Anyway, it works as expected:
(odds '(1 2 3 4 5))
=> 3
Regardless if you use (R6RS?) Scheme or Racket, this will work for both:
(define (odds lst)
(length (filter odd? lst)))
(define l '(1 2 3 4 5 6 7 8 9 10))
(odds l)
As low level as I can get it :
(define odds
(lambda (lst)
(cond ((empty? lst) 0)
((not (= 0 (modulo (car lst) 2))) (+ 1 (odds (rest lst))))
(else (odds (cdr lst))))))
Here's another one-liner
(define (odds L)
(reduce + 0 (map (lambda (x) (if (odd? x) 1 0)) L)))
Here is a function that returns a function that counts anything based on a predicate:
(define (counter-for predicate)
(define (counting list)
(if (null? list)
0
(+ (if (predicate (car list)) 1 0)
(counting (cdr list)))))
counting))
which is used like:
(define odds (counter-for odd?))
[MORE OPTIONS] Here is a nice recursive solution
(define (odds list)
(if (null? list)
0
(+ (if (odd? (car list)) 1 0)
(odds (cdr list)))))
here is a tail recursive solution:
(define (odds list)
(let odding ((list list) (count 0)))
(if (null? list)
count
(odding (cdr list)
(+ count (if (odd? (car list)) 1 0))))))
Here is a routine that counts anything based on a predicate:
(define (count-if predicate list)
(if (null? list)
0
(+ (if (predicate (car list)) 1 0)
(count-if predicate (cdr list)))))