Outputting different levels in a nested list - scheme

Quick question trying to figure this out before an exam I have.
If I have a nested list such as
(list 1 (list 2 3 ( list 4 (list 6))))
How would I write a function that would give me the lowest level only or the 3rd level?
For example the lowest level would output '(6) and the 3rd would output '(4).
I was debating maybe using a flattem but then I wouldn't know the levels.
Any help would be greatly appreciated.

Use recursive descent and pass the current level as an extra argument.
(define (collect s-exp level) ...)
1. If s-exp is empty return '()
2. If s-exp is a pair, (cons a d), then
2a. if a is a pair, then recurse on a with an increased level
2b. if level is below 3
3a recurse on a
3b recurse on d
3c. append the results from 3a and 3b
2c if level is 3
4a recurse on d
4b append (list a) with the result from 4a

Related

iterate through a list of lists of strucs in Racket?

given a list of the following form:
(define lst (list
(list
(make-route-section 32 'ordinary-road 23 0.45)
(make-route-section 54 'ordinary-road 92 0.83)
(make-route-section 14 'street 8 0.82)
(make-route-section 44 'ferry 34 0.64)
(make-route-section 96 'ferry 249 0.41)
)(
list
(make-route-section 92 'ordinary-road 12 0.44)
(make-route-section 98 'highway 45.243 0.3)
(make-route-section 44 'ordinary-road 34.4 0.64)
(make-route-section 39 'street 6 0.8)
)(
list
(make-route-section 62 'highway 82 0.35)
(make-route-section 58 'street 4 0.46)
(make-route-section 50 'highway 81 0.24)
(make-route-section 75 'highway 67.3 0.39)
)
)
A route section is the following:
(define-struct route-section (id kind length eco-index))
(define-struct traffic-jam (section-id delay))
How would I, for example filter out certain structs with given ids (first field of the struct) with a list like (list 32 62) and it would return me the second element of the outer list. What confused me especially is, when I entered (second lst) it returned the second element of the first list of the whole list.
How would I add up the lengths of the route sections? I feel so dumb, even using higher order functions I could't iterate through the nested list.
Here's how to sum the length of the route.
A route is a list of segments, each segment is a list of sections, which are structures.
To sum a list of numbers a good approach is (foldl + 0 <list>). But we don't have a list of numbers, we have a list of segments. So we want to get a number from each segment. We could use foldl again. But each element of the segment isn't a number: it's a section. So a good way of taking a list of somethings and getting a list of something-elses is to use (map <function-to-turn-something-into-something-else> <list-of-somethings>).
route-section-length will take a section object and return its length, so that's the function we want to map. So we could start, on a segment, to turn it into a list of lengths of its sections:
(map route-section-length <segment>)
And now we have a list of numbers for each segment, and we can use foldl:
(foldl + 0 (map route-section-length <segment>))
And this will turn a segment into a number. Well, we have a list of segments, so we want to turn them into a list of numbers, which we can do by mapping a function whose body is the expression above over the list:
(map (λ (segment)
(foldl + 0 (map route-section-length segment)))
route)
OK, that gives us a list of numbers, which we now need to add up, again using foldl:
(foldl + 0
(map (λ (segment)
(foldl + 0 (map route-section-lenght segment)))
route))
And that, wrapped in a definition, is what we want.
Also: indent your code properly.

Parsing strings representing lists of integers and integer spans

I am looking for a function that parses integer lists in Emacs Lisp, along the lines of Perl's Set::IntSpan. I.e., I would like to be able to do something like this:
(parse-integer-list "1-3, 4, 8, 18-21")
⇒ (1 2 3 4 8 18 19 20 21)
Is there an elisp library somewhere for this?
The following does what you want:
(defun parse-integer-list (str)
"Parse string representing a range of integers into a list of integers."
(let (start ranges)
(while (string-match "\\([0-9]+\\)\\(?:-\\([0-9]+\\)\\)?" str start)
(push
(apply 'number-sequence
(seq-map 'string-to-int
(seq-filter
'identity
(list (match-string 1 str) (match-string 2 str)))))
ranges)
(setq start (match-end 0)))
(nreverse (seq-mapcat 'nreverse ranges))))
The code loops over the incoming string searching for plain numbers or ranges of numbers. On each match it calls number-sequence with either just a number for a plain match or two numbers for a range match and pushes each resulting number sequence into a list. To account for push building the result backwards, at the end it reverses all ranges in the list, concatenates them, then reverses the result and returns it.
Calling parse-integer-list with your example input:
(parse-integer-list "1-3, 4, 8, 18-21")
produces:
(1 2 3 4 8 18 19 20 21)

How to solve this programming situation using Clojure in a functional manner?

I have a programming problem that I know how I might tackle in Ruby, but don’t know the best way in Clojure (and figure there may be an elegant way to do this taking a functional mindset).
The problem can be simplified as thus:
I have a 3 litre bucket, filled with water. There is a hole in the bottom of the bucket, that is leaking 10 mL/s (i.e. it will take 300 seconds / 5 minutes to empty). I have a glass of water with a 100 mL capacity that I can use to pour in new water to the bucket.
I can only pour the entire contents of the glass into the bucket, no partial pours. The pour occurs instantaneously.
Project out a set of time steps where I can pour glasses of water into the bucket.
I know there is a pretty obvious way to do this using algebra, but the actual problem involves a “leak rate” that changes with time, and "new glass volumes" that don't always equal 100 mL and as such isn’t simple to solve in a closed form.
The Ruby way to solve this would be to keep track of the bucket volume using a “Bucket instance”, and test at numerous time steps to see if there bucket has 100 mL of room. If so, dump the glass, and add to the water in the “bucket instance”. Continue the time steps, watching the bucket volume.
I hope what I have described is clear.
One of the most important concepts of functional programming is that any mutation without external side effects can be offloaded onto immutable function parameter bindings.
Here the time of the simulation and the level of the bucket are the primary function parameters, and they are updated for each recursive call. The other parameters are modeled as functions of time. We could picture each of these functions actually being a lazy sequence based on the time deltas just as the fill-times function itself is. Or piecewise linear equations modeled with lookups in a vector, or whathaveyou.
user>
(defn fill-times
[time level
{:keys [sample-rate calc-bucket-size calc-leak-rate calc-glass-size]
:as params}]
(loop [t time l level]
(let [input-capacity (calc-glass-size time)
bucket-capacity (calc-bucket-size time)
has-room (> (- bucket-capacity l) input-capacity)
leak-delta (* (calc-leak-rate) sample-rate -1)]
(if has-room
(lazy-seq (cons t (fill-times t (+ l input-capacity)
params)))
(recur (+ t sample-rate) (+ l leak-delta))))))
#'user/fill-times
user> (take 50 (fill-times 0 0 {:sample-rate 1
:calc-bucket-size (constantly 3000)
:calc-leak-rate (constantly 10)
:calc-glass-size (constantly 100)}))
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 11 21 31 41 51 61 71 81 91 101 111 121 131 141 151 161 171 181 191 201)
When there is sufficient room, the glass is dumped (and of course is filled instantly) and we make a note of the time, calling the function again to get the following times. When there is not room, we recur, updating the time and the bucket level. The result is a (hypothetically infinite) lazy sequence of times at which the glass can be emptied (assuming that the glass is filled instantly, and dumped instantly).
I don't have a lot of experience with Clojure, but one way to think of it is a lazy seq of state values at time steps. Lazily compute each state value from the previous state value.
This is a recurrence equation, also known as a difference equation. It computes new values as a function of previous values without overwriting them.
A state value could be just the bucket level or a tuple holding the (time, bucket_level, pour_in_count).

Sum of numbers in a list using Scheme

I want to sum the numbers in a list without using recursion. I know you can sum a list of numbers like this
(+ num1 num2 ... numN)
but what if you have a list L which equals to '(num1 num2 ... numN)
is there a way to make + take the numbers in this list as arguments. I need to do this without recursion or helper functions.
Sure, just use apply:
(apply + '(1 2 3 4 5 6)) ; same as (+ 1 2 3 4 5 6)
(apply + 1 2 3 '(4 5 6)) ; ditto
(apply + 1 2 3 4 5 '(6)) ; ditto
(apply + 1 2 3 4 5 6 '()) ; ditto
The general answer to the question you seem to be asking -- how to take a list and use it as the arguments -- is apply, as Chris Jester-Young answered.
However, for this particular question, there might some other considerations. You may want to sum lists of arbitrary size. However, implementations often have some limit of the number of arguments you can call a function with. A more reliable solution may be to use some kind of fold function (various implementations have different fold functions) to fold + over the list.

Sort two list with the elements in an increasing order

The question requires me to Complete the Scheme function merge, which consumes two lists of sorted numbers (in an increasing order) and produces a list of numbers which consists of all the two consumed lists in sorted order.
For example,
(merge (list 1 4 5 9) (list -1 2 4)) => (list -1 1 2 4 4 5 9)
(merge (list 1 4 5 9) empty) => (list 1 4 5 9)
(merge empty (list 1 4 5 9)) => (list 1 4 5 9)
(merge empty empty) => empty
Thanks for helping out!!
Since this smells like homework, I won't write any code, but I will tell you that what are doing is part of the merge sort algorithm. Remember these two things:
In functional languages like Scheme, you are asking the question what value do I need to produce rather than what do I need to do
In Scheme, you often write more than one procedure to accomplish a single task
If you remember these two things and figure out which part of merge sort you need to implement, it should become fairly easy to figure out.

Resources