Sort two list with the elements in an increasing order - sorting

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.

Related

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)

Generate a random number, excluding a single number

I'm writing a Monty Hall simulator, and found the need to generate a number within a range, excluding a single number.
This seemed easy, so I naively wrote up:
(The g/... functions are part of my personal library. Their use should be fairly clear):
(defn random-int-excluding
"Generates a random number between min-n and max-n; excluding excluding-n.
min-n is inclusive, while max-n is exclusive."
[min-n max-n excluding-n rand-gen]
(let [rand-n (g/random-int min-n max-n rand-gen)
rand-n' (if (= rand-n excluding-n) (inc rand-n) rand-n)]
(g/wrap rand-n' min-n (inc max-n))))
This generates a random number within the range, and if it equals the excluded number, adds one; wrapping if necessary. Of course this ended up giving the number after the excluded number twice the chance of being picked since it would be picked either if it or the excluded number are chosen. Sample output frequencies for a range of 0 to 10 (max exclusive), excluding 2:
([0 0.099882]
[1 0.100355]
[3 0.200025]
[4 0.099912]
[5 0.099672]
[6 0.099976]
[7 0.099539]
[8 0.100222]
[9 0.100417])
Then I read this answer, which seemed much simpler, and based on it, wrote up:
(defn random-int-excluding
"Generates a random number between min-n and max-n; excluding excluding-n.
min-n is inclusive, while max-n is exclusive."
[min-n max-n excluding-n rand-gen]
(let [r1 (g/random-int min-n excluding-n rand-gen)
r2 (g/random-int (inc excluding-n) max-n rand-gen)]
(if (g/random-boolean rand-gen) r1 r2)))
Basically, it splits the range into 2 smaller ranges: from the min to the excluded number, and from excluded number + 1 to the max. It generates random number from these ranges, then randomly chooses one of them. Unfortunately though, as I noted under the answer, this gives skewed results unless both the partitions are of equal size. Sample output frequencies; same conditions as above:
([0 0.2499497]
[1 0.2500795]
[3 0.0715849]
[4 0.071297]
[5 0.0714366]
[6 0.0714362]
[7 0.0712715]
[8 0.0715285]
[9 0.0714161])
Note the numbers part of the smaller range before the excluded number are much more likely. To fix this, I'd have to skew it to pick numbers from the larger range more frequently, and really, I'm not proficient enough in maths in general to understand how to do that.
I looked at the accepted answer from the linked question, but to me, it seems like a version of my first attempt that accepts more than 1 number to exclude. I'd expect, against what the answerer claimed, that the numbers at the end of the exclusion range would be favored, since if a number is chosen that's within the excluded range, it just advances the number past the range.
Since this is going to be one of the most called functions in the simulation, I'd really like to avoid the "brute-force" method of looping while the generated number is excluded since the range will only have 3 numbers, so there's a 1/3 chance that it will need to try again each attempt.
Does anyone know of a simple algorithm to chose a random number from a continuous range, but exclude a single number?
To generate a number in the range [a, b] excluding c, simply generate a number in the range [a, b-1], and if the result is c then output b instead.
Just generate a lazy sequence and filter out items you don't want:
(let [ignore #{4 2}]
(frequencies
(take 2000
(remove ignore (repeatedly #(rand-int 5))))))
Advantage to the other approach of mapping to different new values: This function will also work with different discrete random number distributions.
If the size of the collection of acceptable answers is small, just put all values into a vector and use rand-nth:
http://clojuredocs.org/clojure.core/rand-nth
(def primes [ 2 3 5 7 11 13 17 19] )
(println (rand-nth primes))
(println (rand-nth primes))
(println (rand-nth primes))
~/clj > lein run
19
13
11
Update
If some of the values should include more than the others, just put them in the array of values more than once. The number of occurrances of each value determines its relative weight:
(def samples [ 1 2 2 3 3 3 4 4 4 4 ] )
(def weighted-samples
(repeatedly #(rand-nth samples)))
(println (take 22 weighted-samples))
;=> (3 4 2 4 3 2 2 1 4 4 3 3 3 2 3 4 4 4 2 4 4 4)
If we wanted any number from 1 to 5, but never 3, just do this:
(def samples [ 1 2 4 5 ] )
(def weighted-samples
(repeatedly #(rand-nth samples)))
(println (take 22 weighted-samples))
(1 5 5 5 5 2 2 4 2 5 4 4 5 2 4 4 4 2 1 2 4 1)
Just to show the implementation I wrote, here's what worked for me:
(defn random-int-excluding
"Generates a random number between min-n and max-n; excluding excluding-n.
min-n is inclusive, while max-n is exclusive."
[min-n max-n excluding-n rand-gen]
(let [rand-n (g/random-int min-n (dec max-n) rand-gen)]
(if (= rand-n excluding-n)
(dec max-n)
rand-n)))
Which gives a nice even distribution:
([0 0.111502]
[1 0.110738]
[3 0.111266]
[4 0.110976]
[5 0.111162]
[6 0.111266]
[7 0.111093]
[8 0.110815]
[9 0.111182])
Just to make Alan Malloy's answer explicit:
(defn rand-int-range-excluding [from to without]
(let [n (+ from (rand-int (dec (- to from))))]
(if (= n without)
(dec to)
n)))
(->> #(rand-int-range-excluding 5 10 8)
repeatedly
(take 100)
frequencies)
;{6 28, 9 22, 5 29, 7 21}
No votes required :).

Implementation of Reverse algorithm LISP

I am trying to implement the reverse algorithm in LISP. I am fairly new to the language so any help would be appreciated.
I have the following code in LISP, it seems logical to me but it doesn't output anything when I run it on terminal. This is what my rev.lisp file looks like:
(defun rev (list)
(if (atom list)
(append (rev (cdr list))
(list (rev (car list))))))
I run it on my terminal as:
%clisp rev.lisp
%
I am expecting the output 6 5 4 3 2 but it doesn't return anything.
You already have an answer, but here are some remarks.
Depending on your background and preferences, recursive algorithms are sometimes best understood with a trace of execution.
The TRACE macro can help you debug your code.
The exact output varies among implementation (here, I am using SBCL).
Since I would like to show you how many times APPEND is called and because tracing standard functions in not allowed1, I am defining a simple function around it and redefining your code to use it:
(defun append* (&rest args) (apply #'append args))
The result of TRACE is the following:
CL-USER> (rev '(2 3 4 5 6))
0: (REV (2 3 4 5 6))
1: (REV (3 4 5 6))
2: (REV (4 5 6))
3: (REV (5 6))
4: (REV (6))
5: (REV NIL)
5: REV returned NIL
5: (REV 6)
5: REV returned 6
5: (APPEND* NIL (6))
5: APPEND* returned (6)
4: REV returned (6)
4: (REV 5)
4: REV returned 5
4: (APPEND* (6) (5))
4: APPEND* returned (6 5)
3: REV returned (6 5)
3: (REV 4)
3: REV returned 4
3: (APPEND* (6 5) (4))
3: APPEND* returned (6 5 4)
2: REV returned (6 5 4)
2: (REV 3)
2: REV returned 3
2: (APPEND* (6 5 4) (3))
2: APPEND* returned (6 5 4 3)
1: REV returned (6 5 4 3)
1: (REV 2)
1: REV returned 2
1: (APPEND* (6 5 4 3) (2))
1: APPEND* returned (6 5 4 3 2)
0: REV returned (6 5 4 3 2)
(6 5 4 3 2)
Basics
First off, we see that REV is sometimes called on ATOM elements. Even though your implementation unwrap elements with CAR and wrap them back again with LIST, it makes little sense to do so. Reversing a list is a function that is applied on lists, and if you happen to pass a non-list argument, it should raise a red flag in your head. In order to build a recursive function for lists, it is generally sufficient to focus on the recursive definition of the datatype.
The LIST type is defined in Lisp as (OR NULL CONS), which is the union of the NULL type and the CONS type. In other words, a list is either empty or a cons-cell.
There are many ways to distinguish between both cases which differs mostly in style. Following the above approach with types, you can use ETYPECASE, which dispatches on the type of its argument and signals an error if no clause matches:
(defun rev (list)
(etypecase list
(null <empty>)
(cons <non-empty> )))
You could also use ENDP.
The reverse of an empty list is an empty list, and you are in the case where you can simply use WHEN and focus and the non-empty case:
(defun rev (list)
(when list
<non-empty>))
Above, we don't check that LIST is a cons-cell, it could be anything. However, the way we use it below can only apply on such objects, which means that runtime checks will detect errorneous cases early enough.
(defun rev (list)
(when list
(append* (rev (rest list))
(list (first list)))))
The above is quite similar to your code, except that I don't call REV on the first element. Also, I use FIRST and REST instead of CAR and CDR, because even though they are respective synonyms, the former better convey the intent of working with lists (this is subjective of course, but most people follow this rule).
Append
What the trace above shows that you might have missed when only reading the code is that APPEND is called for all intermediate lists. This is quite wasteful in terms of memory and processing, since APPEND necessarily has to traverse all elements to copy them in a fresh list. If you call APPEND n times, as you are doing since you iterate over a list of n elements, you end up with a quadratic algorithm (n2).
You can solve the memory issues by reusing the same intermediate list with NCONC in place of APPEND. You still have to iterate many times this list, but at least the same underlying cons cells are reused. Typically, a recursive reverse is written with an additional parameter, an accumulator, which is used to store intermediate results and return it at the deepest level:
(defun reverse-acc (list acc)
(etypecase list
;; end of input list, return accumulator
(null acc)
;; general case: put head of input list in front
;; of current accumulator and call recursively with
;; the tail of the input list.
(cons (reverse-acc (rest list)
(cons (first list) acc)))))
The above example is called with an empty accumulator. Even though it could be possible to let this function accessible directly to users, you might prefer to hide this implementation detail and export only a function with a single argument:
(defun rev (list) (reverse-acc list nil))
(trace rev reverse-acc)
0: (REV (2 3 4 5 6))
1: (REVERSE-ACC (2 3 4 5 6) NIL)
2: (REVERSE-ACC (3 4 5 6) (2))
3: (REVERSE-ACC (4 5 6) (3 2))
4: (REVERSE-ACC (5 6) (4 3 2))
5: (REVERSE-ACC (6) (5 4 3 2))
6: (REVERSE-ACC NIL (6 5 4 3 2))
6: REVERSE-ACC returned (6 5 4 3 2)
5: REVERSE-ACC returned (6 5 4 3 2)
4: REVERSE-ACC returned (6 5 4 3 2)
3: REVERSE-ACC returned (6 5 4 3 2)
2: REVERSE-ACC returned (6 5 4 3 2)
1: REVERSE-ACC returned (6 5 4 3 2)
0: REV returned (6 5 4 3 2)
(6 5 4 3 2)
The shape of the trace is typical of recursive functions for which tail-call elimination is possible. Indeed, the recursive invocation of REVERSE-ACC inside itself directly returns the result we want and thus no intermediate memory is required to store and process intermediate result. However, Common Lisp implementations are not required by the standard to eliminate recursive calls in tail position and the actual behavior of a specific implementation might even depend on optimization levels. A conforming program thus cannot assume the control stack won't ever grow linearly with the size of the list.
Recursivity is best used on certain kinds of problems which are recursive by nature and where the height of the stack doesn't grow so fast w.r.t. the input. For iteration, use control structures like DO, LOOP, etc. In the following example, I used DOLIST in order to PUSH elements inside a temporary RESULT list, which is return at the end of DOLIST:
(defun rev (list)
(let ((result '()))
(dolist (e list result)
(push e result))))
The trace is:
0: (REV (2 3 4 5 6))
0: REV returned (6 5 4 3 2)
(6 5 4 3 2)
1. 11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming Programs
You are not printing anything, so you are not seeing anything.
Replace (rev '(2 3 4 5 6)) with (print (rev '(2 3 4 5 6))) and you will see (6 5 4 3 2) on the screen.

Scheme add columns in a matrix

I am trying to write a function that takes a matrix (represented as a list of lists) and adds the elements down the columns and returns a vector (represented as a list):
Example:
(define sample
'((2 6 0 4)
(7 5 1 4)
(6 0 2 2)))
should return '(15 11 3 10).
I was trying to use the (list-ref) function twice to obtain the first element of each column with no luck. I am trying something like:
(map (lambda (matrix) ((list-ref (list-ref matrix 0) 0)) (+ matrix))
The solution is simple if we forget about the indexes and think about higher-order procedures, try this:
(define sample
'((2 6 0 4)
(7 5 1 4)
(6 0 2 2)))
(apply map + sample)
=> '(15 11 3 10)
Explanation: map can take multiple lists as arguments. If we apply it to sample (which is a list of lists) and pass + as the procedure to do the mapping, it'll take one element from each list in turn and add them, producing a list with the results - effectively, adding all the columns in the matrix.

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.

Resources