Does anyone know how to return a number of specific elements in a list?
Example: given
(list 'a 'a 'a 'a 'a 'b 'b 'b)
Returns the numbers of 'a: 5
numbers of 'b: 3
You count them. You make a procedure that takes a list and what you want to search for and you iterate that list while keeping a count and when you reach the end you return that value.
A skeleton for a simple recursive solution:
(define (count-element element lst)
(define (helper lst count)
(cond ((empty? lst) count)
((equal? element <first element>) <recurse whith cdr and increasing count>)
(else <recurse with cdr>)))
(helper lst 0))
Or you can use foldl
(define (count-element element lst)
(foldl (lambda (e count)
(if <e is the same as element>
<return 1 more than count>
<return count>))
0
lst))
There are probably 10 more ways I could do it, but the first is the most educational and the second the most common way I would do it.
Some tests:
(define test '(a a a a a b b b))
(count-element 'b '()) ; ==> 0
(count-element 'e test) ; ==> 0
(count-element 'a test) ; ==> 5
(count-element 'b test) ; ==> 3
I somewhat managed to find the answer, so here's the function definition:
(define (number-of s L)
(cond
[(empty? L) 0]
[else (cond [(eq? s (first L)) (+ 1 (number-of s (rest L)))]
[else (number-of s (rest L))])]))
Related
I am looking for a function that does what "filter" is used for, but without using filter. On top, it should also filter nested lists.
E. g. list ( 1 2 (list 3 'a 'b) 3 4) should return list (1 2 (list 3) 3 4).
I already have the function to filter. My thought is, that I have to distinguish in the beginning of the function, if first lst is a list itself.
What I got so far is:
(define (my-filter pred lst)
(cond ((null? lst) null) ;;(after this I would try to test if it is a list itself, but I am not sure how)
((pred (first lst))
(cons (first lst) (my-filter pred (rest lst))))
(else (my-filter pred (rest lst)))))
As it has been said in the comments, a possible solution is:
(define (my-filter pred lst)
(cond [(null? lst) null]
[(list? (first lst)) (cons (my-filter pred (first lst))
(my-filter pred (rest lst)))]
[else (if (pred (first lst))
(cons (first lst) (my-filter pred (rest lst)))
(my-filter pred (rest lst)))]))
Example
> (my-filter number? '(1 a 2 (3 (b 4) c) 5 6 d 7))
'(1 2 (3 (4)) 5 6 7)
> (my-filter (lambda (x) (not (number? x))) '(1 a 2 (3 (b 4) c) 5 6 d 7))
'(a ((b) c) d)
Here is my code? Can anyone tell me how to iterate through a list? if the character in the list is alphabetic, I want to add to a new string
#lang racket
(define (conversion input)
(define s (string))
(let ((char (string->list input)))
(cond
[(char-alphabetic? (first (char)))
(string-append s first)]
[(char-alphabetic? (rest (char)))
(string-append s rest)]))
(display s))
Basic iteration is:
(define (copy-list lst)
(if (null? lst)
'()
(cons (car lst)
(copy-list (cdr lst))))
(copy-list '(1 2 3)) ; ==> (1 2 3)
This one actually makes a shallow copy of your list. Sometimes you iterate with keeping some variables to accumulate stuff:
(define (sum-list lst acc)
(if (null lst)
acc
(sum-list (cdr lst) (+ acc (car lst)))))
(sum-list '(1 2 3)) ; ==> 6
Looking at these you'll see a pattern emerges so we have made stuff like map, foldl, and foldr to abstract the iteration:
(define (copy-list-foldr lst)
(foldr cons '() lst)
(define (copy-list-map lst)
(map values lst))
(define (sum-list-foldl lst)
(foldl + 0 lst))
Looking at your challenge I bet you can fix it with a foldr.
I am trying to produce the product of the even numbers in a given list.
I am trying to replicate the following example:
Example:
(product-even-numbers '(2 1 6 3 5))
==> 12
This is my version of the definition for product-even-numbers:
(define (product-even-numbers lst)
(define/match (recurse lst accumulator)
;; A _ pattern matches any syntax object
[(_ _) (* car (recurse cdr))])
(recurse lst 1))
I am getting the following error:
(product-even-numbers '(2 1 6 3 5))
. . recurse: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
arguments...:
I understand that i am missing the second argument, but I do not know what the second argument is supposed to be.
Why are you using pattern matching? this would be easier to understand without it, and first of all you need to get the recursion and the logic right:
(define (product-even-numbers lst)
(define (recurse lst acc)
(cond ((null? lst) acc)
((even? (car lst)) (recurse (cdr lst) (* (car lst) acc)))
(else (recurse (cdr lst) acc))))
(recurse lst 1))
In this case, it's clear that the second argument is the accumulated product we have so far. And we need to consider three cases: empty list, even element, odd element. For example:
(product-even-numbers '(2 1 6 3 5))
=> 12
(define (product-even-numbers lst)
(local [(define tmp (foldr * 1 (filter even? lst)))]
(if (= 1 tmp) 'nothing tmp)))
If output 1 means no any even number.
(define (product-even-numbers2 lst)
(foldr * 1 (filter even? lst))) ; or use (apply * (filter even? lst))
I want to make a list of pairs starting from a list, the cdr will be always the same. For example, (make-pair '(1 2 3 4 5)) should return '((1.a)(2.a)(3.a)(4.a)(5.a)).
This is the code i am developing, but it doesn't work and I don't know how to debug it.
(define (make-pair lst)
(if (null? (car lst))
'()
(cons ((car lst) ".a")
(make-pair (cdr lst)))))
Thank you in advance!
You have a couple of errors:
(define (make-pair lst)
(if (null? (car lst)) ; - the base case is when the list is null
'()
(cons ((car lst) ".a") ; - there's a missing cons
; - `a` appears to be a symbol, not a string
; - that's not how we create a dotted pair
; - the surrounding `()` are misplaced
(make-pair (cdr lst)))))
This is the right way:
(define (make-pair lst)
(if (null? lst)
'()
(cons (cons (car lst) 'a)
(make-pair (cdr lst)))))
Or even better, use built-in procedures:
(define (make-pair lst)
(map (lambda (n) (cons n 'a))
lst))
Either way, it works as expected:
(make-pair '(1 2 3 4 5))
=> '((1 . a) (2 . a) (3 . a) (4 . a) (5 . a))
I have a series of expressions to convert from postfix to prefix and I thought that I would try to write a program to do it for me in DrRacket. I am getting stuck with some of the more complex ones such as (10 (1 2 3 +) ^).
I have the very simple case down for (1 2 \*) → (\* 1 2). I have set these expressions up as a list and I know that you have to use cdr/car and recursion to do it but that is where I get stuck.
My inputs will be something along the lines of '(1 2 +).
I have for simple things such as '(1 2 +):
(define ans '())
(define (post-pre lst)
(set! ans (list (last lst) (first lst) (second lst))))
For the more complex stuff I have this (which fails to work correctly):
(define ans '())
(define (post-pre-comp lst)
(cond [(pair? (car lst)) (post-pre-comp (car lst))]
[(pair? (cdr lst)) (post-pre-comp (cdr lst))]
[else (set! ans (list (last lst) (first lst) (second lst)))]))
Obviously I am getting tripped up because (cdr lst) will return a pair most of the time. I'm guessing my structure of the else statement is wrong and I need it to be cons instead of list, but I'm not sure how to get that to work properly in this case.
Were you thinking of something like this?
(define (pp sxp)
(cond
((null? sxp) sxp)
((list? sxp) (let-values (((args op) (split-at-right sxp 1)))
(cons (car op) (map pp args))))
(else sxp)))
then
> (pp '(1 2 *))
'(* 1 2)
> (pp '(10 (1 2 3 +) ^))
'(^ 10 (+ 1 2 3))
Try something like this:
(define (postfix->prefix expr)
(cond
[(and (list? expr) (not (null? expr)))
(define op (last expr))
(define args (drop-right expr 1))
(cons op (map postfix->prefix args))]
[else expr]))
This operates on the structure recursively by using map to call itself on the arguments to each call.