How does this recursive function work step by step:
(fn foo [n]
(if (< n 10)
[n]
(conj (foo (quot n 10))
(mod n 10))))
I have problem with understanding: lets say i give it as n the number 123, and it will return a vector of its digits. At the last step when arrived to 1 and (< 1 10) it should go to the then-part [n], return [1] and come out of the recursion. So this doesn't happen, what am i missing in the play?
At the last step when arrived to 1 and (< 1 10) it does go to the then-part [n], return [1], but it does NOT come out of the recursion, only out of the innermost invocation.
The evaluation goes as follows:
(foo 123)
(conj (foo 12) 3)
(conj (conj (foo 1) 2) 3)
(conj (conj [1] 2) 3)
(conj [1 2] 3)
[1 2 3]
Related
I have this function that checks the cities in a csv file if they have over a population of 500000.
I saved all the found cities to a vector but now want to loop over the vector twice in order to find the pairs of cities that are close to each other(less than 500km)(i already have a function that checks if two cities are close)
Here is what I have so far:
(defn closest-city-pairs []
(with-open [rdr (reader)]
(vec
(for [line (drop 1 (line-seq rdr))
:let [y (string/split line #",")]
:when (= true (large(y 0)))]
(let [newVec (conj [] (y 0))]
(for[x newVec
y newVec
:when (= true (close x y))]
(let [newNewVec (conj [] (x y))]
(println newNewVec))))))))
It doesn't seem to want to print but my logic and all the parentheses seem to make sense and in order? Any help would be great
(require '[clojure.math.combinatorics :as comb])
(require '[clojure.data.csv :as csv])
(with-open [r (io/reader "cities.csv")]
(let [cities (->> (csv/read-csv r) (into [] (comp cat (filter large-city?))))]
(filter close-to-each-other? (comb/combinations cities 2))))
Here is an outline of what you can do, written as a unit test:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(def nums [1 2 3 11 12 13])
(defn close?
[x y]
(<= (Math/abs (- x y)) 5))
(dotest
(let [close-pairs (vec
(for [x nums
y nums
:when (and (not= x y)
(close? x y))]
[x y]))]
(spyx close-pairs))
)
with result:
close-pairs => [[1 2] [1 3] [2 1] [2 3] [3 1] [3 2]
[11 12] [11 13] [12 11] [12 13] [13 11] [13 12]]
so we get a lot of duplicates. We can eliminate them by simply sending the output into a set, then removing duplicate sets:
(let [close-pairs (vec
(distinct
(for [x nums
y nums
:when (and (not= x y)
(close? x y))]
#{x y})))]
(spyx close-pairs))
with result:
close-pairs => [#{1 2} #{1 3} #{3 2} #{12 11} #{13 11} #{13 12}]
You can avoid the set trick (and the work duplication) if you get fancier with the for expression, and use indexes for each value. See the docs for the indexed function
(indexed [:a :b :c]) => ([0 :a] [1 :b] [2 :c])
And we can then use the :when clause like so:
(dotest
(let [nums-indexed (indexed nums)
close-pairs (vec
(for [[ix x] nums-indexed
[iy y] nums-indexed
:when (and (< ix iy)
(close? x y) )]
[x y]))]
(spyx close-pairs)))
with result:
close-pairs => [[1 2] [1 3] [2 3] [11 12] [11 13] [12 13]]
One could reduce the duplicate looping even further with judicious use of the :while clause, but that is left as an exercise for the reader.
P.S. You'll need to add [tupelo "0.9.169"] to :dependencies in your project.clj to access the spyx and indexed functions.
I am going through the book Structure and Interpretation of Computer Programming, which uses Scheme, and I just got through a portion on recursion. I wrote a program for exercise 1.11:
A function f is defined by the rule that f(n) = n if n<3 and f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) if n> 3. Write a procedure that computes f by means of a recursive process. Write a procedure that computes f by means of an iterative process.
I wrote the code at repl.it and when I run the procdure with the input 2, it gives me the error: Error: 2 is not a function [fRecurse, (anon)]. Can somebody explain to me what this means and how I can fix it? Why is it expecting my input to be a function?
Code:
(define (fRecurse n)(
(cond ((< n 3) n)
((>= n 3)
(+ (procRecurse (- n 1))
(* 2 (f (- fRecurse 2)))
(* 3 (f (- fRecurse 3))))))))
(fRecurse 2)
The error is due to an extra pair of parentheses before (cond...). To fix the issue, we simply remove the extra pair of parentheses:
(define (fRecurse n)
(cond ((< n 3) n)
((>= n 3)
(+ (fRecurse (- n 1))
(* 2 (fRecurse (- n 2)))
(* 3 (fRecurse (- n 3)))))))
(fRecurse 2)
And some additonal fixes I made to your example to make it work correctly:
Change f to fRecurse
Change procRecurse to fRecurse
Change (* 2 (f (- fRecurse 2))) to (* 2 (fRecurse (- n 2)))
Change (* 3 (f (- fRecurse 3))) to (* 3 (fRecurse (- n 3)))
See the updated repl.it
I having trouble with this function,
I would like a function which
returns a list of number inferior for a given a number.
What I did so far,
(defun inf (n l)
(cond
((not l) 0)
((>= n (car l))(cons n (inf n(cdr l))))
(cons (car l) (inf n (cdr l))) ))
But it keeps returns
(inf 12 '(12 5 3))
(12 12 10)
Instead of :
(inf 12 '(12 5 3 53 45))
(12 5 3)
What did I miss ?
First of all, the function you posted does not behave the way you claim.
The 1st invocation returns (12 12 12 . 0) (because you return 0 instead of nil in the 1st cond clause)
and the second invocation raises an exception
COND: variable CONS has no value
because you got cond syntax wrong.
Second, the question summary, question text, and the attempted
implementation, specify three different problems.
Here is a fix for your code (I replaced
car and cdr with
first and
rest for pedagogical reasons):
(defun inf (n l)
(cond
((not l) ()) ; return empty list
((>= n (first l))
(cons n (inf n (rest l))))
(t
(cons (first l) (inf n (rest l))))))
If this is, in fact, what you want, you can implement in a more
idiomatic way:
(defun inf-1 (n l)
(and l (cons (max n (first l)) (inf-1 n (rest l)))))
or even
(defun inf-2 (n l)
(mapcar (lambda (x) (max n x)) l))
If you actually want the list of numbers less than the given one, you
can use remove:
(remove 12 '(12 5 3 100) :test #'<=)
==> (5 3)
A not-so-obvious way to solve the same problem using Common Lisp's existing functions is to pass a comparison operator to REMOVE.
(remove 10 '(0 3 5 11 22 10 22 3 2) :test #'<)
The above removes all elements "equal" to 10 according to #'<, which are thus all elements u such that (< 10 u) holds. In other words, all elements strictly above 10:
(0 3 5 10 3 2)
It turns out that there is an example of this in the section linked above:
(remove 3 '(1 2 4 1 3 4 5) :test #'>) => (4 3 4 5)
Edit: since this is now the accepted answer, note also that this approach is probably hard to read, be careful when using it (add a comment, etc.).
I am basically new to Scheme, and this is my second attempt to solve a certain problem.
So what I am trying to do basically is sum each parameter we pass into the function, with an appropriate value
for example:
(sum 3 1 2 0 2) ;would return 228
Here is my code:
(define (sum one five ten twenty fifty hundred)
(+ (* 1 one)(* 5 five) (* 10 ten) (* twenty 20) (* 50 fifty) (* 100 hundred))
I think a possible solution is using the lambda function, but I could't know how to implement it.
Here is one way you can calculate the numbers by sending in only 5 arguments instead of 6:
(define sum
(lambda (L skip) ;stores yourList and the number you want to skip
(define loop
(lambda (L L2 total) ;yourList, (1,5,10...) list, running total
(cond
((null? L) (list total)) ;print the total when finish yourList
;if the next number is the skip number, just move on to next value
((= (car L2) skip) (loop L (cdr L2) total))
;otherwise, increase total and send in both lists, minus the head, to the loop
(else (loop (cdr L) (cdr L2) (+ total (* (car L) (car L2)) )))
)
)
)(loop L (list 1 5 10 20 50 100) 0) ;initial values of loop
)
)
;send in your list of numbers, plus the value place you want to skip
(sum (list 3 1 2 0 2) 20) ; ==> 228
I would be much easier, though, to just fill in all the places that you don't want with a 0. Once you have 6 arguments, the following code will work.
(define sum
(lambda (one five ten twenty fifty hundred)
(+ (* 1 one) (* 5 five) (* 10 ten) (* 20 twenty) (* 50 fifty) (* 100 hundred) )
)
)
(sum 3 1 2 0 0 2)
The OP wants to be able to pass fewer arguments than there are parameters. In this specific case, it's best to use keyword (named) arguments. Here's how you might do this (in Racket syntax):
(define (total-bills #:ones (ones 0)
#:fives (fives 0)
#:tens (tens 0)
#:twenties (twenties 0)
#:fifties (fifties 0)
#:hundreds (hundreds 0))
(+ ones (* fives 5) (* tens 10) (* twenties 20) (* fifties 50) (* hundreds 100)))
(The 0 after each of the variable names are the default values, that is, what the value would be if you don't specify it.)
Example usage:
> (total-bills #:ones 3 #:fives 1 #:tens 2 #:hundreds 2)
228
If you want to use standard scheme with a similar scheme as Chris' answer in plain old Scheme you need to plan how to identify which currency your number is in. Perhaps by sending them in pairs would be both simpler to implement and simpler to use:
#!r6rs
(import (rnrs))
(define (total-bills . args)
(fold-left (lambda (acc x)
(+ acc (apply * x)))
0
args))
(total-bills '(5 1) '(2 10) '(3 100)) ; ==> 325
(apply total-bills '((1 3) (5 1) (10 1) (20 2))) ; ==> 58
You can make a procedure that makes a specialized procedure based on currencies you pass to it:
#!r6rs
(import (rnrs))
(define (make-currency-procedure . currencies)
(lambda amounts
(fold-left (lambda (acc currency amount)
(+ acc (* currency amount)))
0
currencies
amounts)))
(define small-bills (make-currency-procedure 1 5 10 20))
(define large-bills (make-currency-procedure 10 100 1000 10000))
(small-bills 3 1 1 2) ; ==> 58
(small-bills 0 1 0 1) ; ==> 25
(large-bills 3 1 1 2) ; ==> 21130
(large-bills 0 1 0 1) ; ==> 10100
I have a function that takes 2 lists as input and I would like to make it so that everything in the first list, is multiplied with everything in the second list, and then the sum is calculated.
Here's my function so far:
(defun multiply(a b)
(if (eq a nil)
0
(progn
(* (car a) (car b))
(multiply (car a) (cdr b)))
))
Currently all I'm trying to get it to do is take the first number from the first list, and multiply one by with everything in the second list. However I get this error from when the function is re-called within the function:
(This is what I inputted, '(1 2 3) and '(4 5 6))
The value 1 is not of type list.
(MULTIPLY 1 '(5 6))
Any help would be much appreciated.
Is loop acceptable?
Case 1
If the result should be 90 as in
(+ (* 1 4) (* 1 5) (* 1 6) (* 2 4) (* 2 5) (* 2 6) (* 3 4) (* 3 5) (* 3 6))
then you could do
(defun multiply (a b)
(loop for i in a
sum (loop for j in b
sum (* i j))))
Case 2
If the result is supposed to be 32 as in
(+ (* 1 4) (* 2 5) (* 3 6))
then it would be
(defun multiply (a b)
(loop
for i in a
for j in b
sum (* i j)))
If you want to multiply two lists per element, you should just be able to use mapcar:
(mapcar #'* '(3 4 5) '(4 5 6))
As to the error in your existing function, this line should be:
...
(multiply (cdr a) (cdr b)))
...
What you describe sounds like the dot product:
(defun dot (l1 l2)
(reduce #'+ (mapcar #'* l1 l2)))
The above solution is nice because it is purely functional, but, alas, it creates an unnecessary intermediate list. Of course, a Sufficiently Smart Compiler should be able to eliminate that, but, practically speaking, you are better off using loop:
(defun dot (l1 l2)
(loop for x in l1 and y in l2 sum (* x y)))
Note also that using lists to represent mathematical vectors is not a very good idea, use vectors instead.
I would modify multiply as
(defun multiply(a b)
(if (eq a nil)
0
(+
(* (car a) (car b))
(multiply (cdr a) (cdr b)))))
When you call
(multiply '(1 2 3) '(4 5 6))
it will return the sum
32
(define (*2Ls L1 L2)
(apply map * (list L1 L2)))