Sum all the numbers in a list of dotted pairs - list

I'm new in Scheme and I have a lot of problems to understand it.
If I have this list '((a . 1) (c . 3) (b . 2)), I will need to get the number 6.
I know how to do it with numbers instead of dotted pairs (get it from this SO answer):
(define (sum elemList)
(if
(null? elemList)
0
(+ (car elemList) (sum (cdr elemList)))
)
)
But, how can I get the sum of all numbers in a dotted pairs list?

This is how you can do it:
(define (sum elemList)
(if (null? elemList)
0
(+ (cdr (car elemList)) (sum (cdr elemList)))))
Simply take the cdr of the car of each element. With the car part you extract the first pair of the list, and with the cdr you retrieve the second element of that pair. We can even simplify it a bit:
(cdr (car elemList))
Is equivalent to this:
(cdar elemList)
But in Scheme we prefer to use built-in functions to compose solutions, so an even more idiomatic way to write it would be:
(define (sum elemList)
(apply + (map cdr elemList)))
We take the cdr of each pair in the list, and then we add them all together. Short, nice and simple. Any of the above solutions will work as expected:
(sum '((a . 1) (c . 3) (b . 2)))
=> 6

Related

how to make a recursive racket list that, from the input list, outputs its decreasing to 1 for every element in the list (e.g. ('3 2) outputs ('32121)

****What I tried****
(define(help num)
(if(= num 1)
num
(cons(num (help( - num 1))))))
;i called this defination in the bottom one
(define (list-expand L)
(cond
[(empty? L)'()]
[(=(car L)1)(cons(car L)(list-expand (cdr L)))]
[(>(car L)1) (cons(help(car L)(list-expand(cdr L))))]))
In the help procedure, the base case is incorrect - if the output is a list then you must return a list. And in the recursive step, num is not a procedure, so it must not be surrounded by brackets:
(define (help num)
(if (<= num 0)
'()
(cons num (help (- num 1)))))
And in list-expand, both recursive steps are incorrect. You just need to test whether the list is empty or not, calling help with the correct number of parameters; use append to combine the results, because we're concatenating sublists together:
(define (list-expand L)
(if (empty? L)
'()
(append (help (car L)) (list-expand (cdr L)))))
That should work as expected, but please spend some time studying Scheme's syntax, you still have trouble with the basics, for instance, when and where to use brackets...
(list-expand '(3 2))
=> '(3 2 1 2 1)
Just for fun - a non-recursive solution in Racket:
(append-map (lambda (n) (stream->list (in-range n 0 -1))) '(3 2))
;; or:
(append-map (lambda (n) (for/list ((x (in-range n 0 -1))) x)) '(3 2))
Returning:
'(3 2 1 2 1)

Insert element to circular list using scheme

I have a circular list, eg: #0=(1 2 3 4 . #0#).
What I want to do is to insert a new element (x) into this list so that the outcome is #0=(x 1 2 3 4 . #0#). I have been trying using this code (x is the circular list):
(define (insert! elm)
(let ((temp x))
(set-car! x elm)
(set-cdr! x temp)))
However, I think that set-cdr! is not working like I want it to. What am I missing here? Maybe I am way off?
The easiest way to prepend an element to a list is to modify the car of the list, and set the cdr of the list to a new cons whose car is the original first element of the list and whose cdr is the original tail of the list:
(define (prepend! x list) ; list = (a . (b ...))
(set-cdr! list (cons (car list) (cdr list))) ; list = (a . (a . (b ...)))
(set-car! list x)) ; list = (x . (a . (b ...)))
(let ((l (list 1 2 3)))
(prepend! 'x l)
(display l))
;=> (x 1 2 3)
Now, that will still work with circular lists, because the cons cell (i.e., pair) that is the beginning of the list remains the same, so the "final" cdr will still point back to object that is the beginning. To test this, though, we need some functions to create and sample from circular lists, since they're not included in the language (as far as I know).
(define (make-circular list)
(let loop ((tail list))
(cond
((null? (cdr tail))
(set-cdr! tail list)
list)
(else
(loop (cdr tail))))))
(define (take n list)
(if (= n 0)
'()
(cons (car list)
(take (- n 1)
(cdr list)))))
(display (take 10 (make-circular (list 1 2 3))))
;=> (1 2 3 1 2 3 1 2 3 1)
Now we can check what happens if we prepend to a circular list:
(let ((l (make-circular (list 1 2 3))))
(prepend! 'x l)
(display (take 15 l)))
;=> (x 1 2 3 x 1 2 3 x 1 2 3 x 1 2)
Since you're trying to prepend an element to a circular list, you need to do two things:
Insert a new cons cell at the front of the list containing the additional element. This is easy because you can just perform a simple (cons elm x).
You also need to modify the recursive portion of the circular list to point at the newly created cons cell, otherwise the circular portion will only include the old parts of the list.
To perform the latter, you need a way to figure out where the "end" of the circular list is. This doesn't actually exist, since the list is, of course, circular, but it can be determined by performing an eq? check on each element of the list until it finds an element equal to the head of the list.
Creating a helper function to do this, a simple implementation of insert! would look like this:
(define (find-cdr v lst)
(if (eq? v (cdr lst)) lst
(find-cdr v (cdr lst))))
(define (insert! elm)
(set! x (cons elm x))
(set-cdr! (find-cdr (cdr x) (cdr x)) x))

Abstract List Functions in Racket/Scheme - Num of element occurrences in list

So I'm currently stuck on a "simple?" function in Racket. It's using the Intermediate Student with lambda language.
Some restrictions on this are that NO recursion is allowed, neither are local functions. It's plain and simple abstract list functions.
What this function is supposed to do is to take in a list of numbers, and output a list of pairs in which each pair has the first element as the number with the second element being the number it has occurred in the list.
Examples:
(1 1 2 3) => ((1 2) (2 1) (3 1))
(2 3 4 3) => ((2 1) (3 2) (4 1))
I have a function that produces the number of occurrences by inputting a list of numbers and a number which is:
(define (occurrences lon n)
(length (filter (lambda (x) (= x n)) lon)))
My approach, which was clearly wrong was:
(define (num-pairs-occurrences lon)
(list (lambda (x) (map (occurrences lon x) (remove x lon)) x))
I thought the above would work, but apparently my lambda isn't placed properly. Any ideas?
It's a bit trickier than you imagine. As you've probably noticed, we must remove duplicate elements in the output list. For this, is better that we define a remove-duplicates helper function (also using abstract list functions) - in fact, this is so common that is a built-in function in Racket, but not available in your current language settings:
(define (remove-duplicates lst)
(foldr (lambda (e acc)
(if (member e acc)
acc
(cons e acc)))
'()
lst))
Now it's easy to compose the solution using abstract list functions:
(define (num-pairs-occurrences lon)
(map (lambda (e) (list e (occurrences lon e)))
(remove-duplicates lon)))
The above might return and output list in a different order, but that's all right. And before you ask: yes, we do need that helper function. Please don't ask for a solution without it...
An easy, self-contained solution would be:
(define (num-pairs-occurences lst)
(foldl (lambda (e r)
(if (or (null? r) (not (= (caar r) e)))
(cons (list e 1) r)
(cons (list e (add1 (cadar r))) (cdr r))))
null
(sort lst >)))
Basically, you sort the list first, and then you fold over it. If the element (e) you get is the same as the first element of the result list (r), you increment the count, otherwise you add a new sublist to r.
If you sort by > (descending), you can actually use foldl which is more memory-efficient. If you sort by < (ascending), you need to use foldr which is less efficient.

How to find the number of repeated characters in list in Scheme

i am trying to make a function in Scheme which returns how many times a character repeats in a list.
For example if i have (list 2 6 'a 'b 'a 'a 2)
the result must be ((2 . 2) (6 . 1) (a . 3) (b . 1))
it didnt need to be written in the most efficient way,just want to be easy and simple for understanding.
Thanks in advance for helping me :)
Since this appears to be homework, you posted no code whatsoever, and we know nothing about your constraints and your current knowledge of Scheme, it's hard to answer.
Basically, you can do this efficiently with a hash map, or less efficiently with 2 nested loops. I'll explain the latter for you to get started.
I'll assume you know how to loop through the list.
So basically you need to
1) loop over your list
2) for each element of the list (let's call it e)
3) loop over the list once more, counting how many of (e) you find
4) assemble (e) and the result of your counting loop
The results of step 4) need to be assembled in a result list.
If you do this, the result will be something like
'((2 . 2) (6 . 1) (a . 3) (b . 1) (a . 3) (a . 3) (2 . 2))
which is close... but not correct because you counted some elements a few times.
So in addition to the above you need a way of keeping track of every element you already encountered, and steps 3) and 4) need to be done only if you encounter a new element. Keeping track could be through another list, or simply by checking your current result list, depending on your code.
If you have any code to show, please update your question and we can help more.
EDIT
OK, since GoZoner has posted code, I have 2 alternative versions for you. I hope you study all of these and make up your own mind, instead of simply copying one.
First, the version I described; as opposed to GoZoner's version, it does not use mutable lists but is slower than the mutable version:
(define (how-many lst)
(let loop ((lst2 lst) (res '()))
(if (empty? lst2)
(reverse res)
(let ((c (car lst2)))
(loop (cdr lst2)
(if (assoc c res)
res
(cons (cons c (count (lambda (e) (eq? e c)) lst)) res)))))))
=> '((2 . 2) (6 . 1) (a . 3) (b . 1))
If you want to use a mutable structure (and I would, too), I recommend mutable hash tables. The following example is in Racket but is trivial to adapt to R6RS Scheme hash tables if required:
(define (how-many lst)
(let ((res (make-hash)))
(for-each (lambda (e) (hash-update! res e add1 0)) lst)
(hash->list res)))
=> '((6 . 1) (a . 3) (b . 1) (2 . 2))
Just note that hash tables do not respect order, so you'll get the same result but the pairs will probably in a different order (and even vary from one call to the next).
Something like this:
(define (character-count list)
(assert (list? list))
(let looking ((list list) (rslt '()))
(cond ((null? list) rslt)
((assoc (car list) rslt) =>
(lambda (pair)
(set-cdr! pair (+ 1 (cdr pair)))
(looking (cdr list) rslt)))
(else (looking (cdr list)
(cons (cons (car list) 1) rslt))))))
> (character-count '(2 a 2 a b c 2))
((c . 1) (b . 1) (a . 2) (2 . 3))
I get an 'A'?!

Scheme - Recursion : Sum consecutive elements of a list

I'm trying to write a function using Scheme that :
take a list of integers with more than two elements as a parameter
sum the n-th-element and (n+1)-th-element
return this list
Result should be as follows :
> (SumNeighbors (list 1 2 3 4))
(3 5 7)
I think I get the way to add elements but my recursion is totally wrong...
(define (SumNeighbors lst)
(if (not (null? (cdr lst)))
(append (list (+ (car lst) (car (cdr lst)))) (SumNeighbors (cdr lst)))))
Any help would be appreciated.
The solution to this problem follows a well-known pattern. I'll give you some hints, it'll be more fun if you find the answer by your own means:
(define (SumNeighbors lst)
(if <???> ; if there's only one element left
<???> ; we're done, return the empty list
(cons ; otherwise call `cons`
(+ <???> <???>) ; add first and second elements
(SumNeighbors <???>)))) ; and advance recursion
Notice the following:
Your solution is lacking the base case - what happens when the list we're traversing only has one element left? it's time to finish the recursion! and because we're building a list as the output, what should be the value returned?
We normally use cons to build an output list, not append. That's the natural way to build a list
The part of this procedure that falls outside the solution template is the fact that we stop when there's a single elment left in the list, not when the list is empty (as is the usual case)
You'll see that many procedures that iterate over an input list and return a list as output follow the same solution template, it's very important that you learn how and why this works, it's the foundation for writing solutions to other similar problems.
#!r6rs
(import (except (rnrs base) map)
(only (srfi :1) map))
(define (sum-neighbors lst)
(map + lst (cdr lst)))
The higher order function map as defined in SRFI-1 supports uneven lenght arguments. It will stop at the shortest list.
If you call (sum-neighbors '(1 2 3 4)) it will become (map + (1 2 3 4) (2 3 4)) which is the same as (cons (+ 1 2) (cons (+ 2 3) (cons (+ 3 4) '())))