How do i check a list has distinct objects(is a set?) or not Scheme - scheme

I am trying to write a function in scheme which is checking a list is a set or not.
In C algorithm would be like this:
int count = sizeof(array) / sizeof(array[0]);
for (int i = 0; i < count - 1; i++) {
for (int j = i + 1; j < count; j++) {
if (array[i] == array[j]) {
//return false
}
}
}
(define set? (lambda (lst)
))

You use the [racket] tag, so I'm going to assume that you're using Racket. You can use the library function check-duplicates to check for duplicate elements. You can use remove-duplicates to remove them.

I assume that you want to know how you would do this if, for instance, the language didn't already have a set datatype (which Racket does) and a bunch of tools to deal with sets, including dealing with lists as sets. So lets reinvent things that already exist, starting with a function which tells you if something occurs in a list (in real life this is a bunch of functions with names like member):
(define (occurs? e l (test? eqv?))
;; does e occur in l, testing with test?
(cond [(null? l)
;; empty lists have no members
#f]
[(test? e (first l))
;; if e is the first element of l then it's in l
#t]
[else
;; if e is in the rest of l it's in l
(occurs? e (rest l) test?)]))
And now you can answer the question as to whether a list is a set. A list is a set if:
it is the empty list;
the first element of the list does not occur in the rest of the list, and the rest of the list is a set.
And this specification can be turned directly into code:
(define (list-set? l (test? eqv?))
;; is l a set?
(if (null? l)
;; the empty list is a set
#t
;; otherwise it is a set if ...
(and
;; .. the first element of it does not occur in the rest of it ...
(not (occurs? (first l) (rest l) test?))
;; ... and the rest of it is a set
(list-set? (rest l) test?))))

Basically what you are doing is having two cursors. i that starts at the beginning and goes towards next to last element and for each of those you have j that starts one next to i and goes to the end.
Here is how to make a loop:
(let name ((var 0) (var2 5))
(if (> var var2)
var
(name (+ (* 2 var) 1) (+ var2 1))))
Since we are talking about lists here and lists are chains of cons instead of having indexes you just use the bindings to the individual cons for iteration:
(define test '(1 2 3 4 5 6 7 8))
(let find-half ((hare test) (tortoise test))
(if (or (null? hare)
(null? (cdr hare)))
tortoise
(find-half (cddr hare) (cdr tortoise))))
So what is the named let? It's a recursive function. The above is the same as:
(define test '(1 2 3 4 5 6 7 8))
(define (find-half hare tortoise)
(if (or (null? hare)
(null? (cdr hare)))
tortoise
(find-half (cddr hare) (cdr tortoise))))
(find-half test test)
It might be easier if you could write your C solution with recursion? Eg.
int fori (int i) {
return i >= count - 1 ||
forj(i, i+1) && fori(i+1);
}
int forj (int i, int j) {
return j >= count ||
array[i] == array[j] && forj(i, j+1);
}
int result = fori(0);

Related

Knuth-Morris-Pratt algorithm in Scheme

This is the code to calculate the failure function (how many steps we have to go back) in Scheme, when we use the Knuth-Morris-Pratt algorithm:
(define (compute-failure-function p)
(define n-p (string-length p))
(define sigma-table (make-vector n-p 0))
(let loop
((i-p 2)
(k 0))
(cond
((>= i-p n-p)
(vector-set! sigma-table (- n-p 1) k))
((eq? (string-ref p k)
(string-ref p (- i-p 1)))
(vector-set! sigma-table i-p (+ k 1))
(loop (+ i-p 1) (+ k 1)))
((> k 0)
(loop i-p (vector-ref sigma-table k)))
(else ; k=0
(vector-set! sigma-table i-p 0)
(loop (+ i-p 1) k))))
(vector-set! sigma-table 0 -1)
(lambda (q)
(vector-ref sigma-table q)))
But I do not understand the part when k > 0. Can someone explain it please?
I see you're confused with the syntax of a named let. This post does a good job explaining how it works, but perhaps an example with more familiar syntax will make things clearer. Take this code in Python, it adds all integers from 1 to 10:
sum = 0
n = 1
while n <= 10:
sum += n
n += 1
print(sum)
=> 55
Now let's try to write it in a recursive fashion, I'll call my function loop. This is completely equivalent:
def loop(n, sum):
if n > 10:
return sum
else:
return loop(n + 1, n + sum)
loop(1, 0)
=> 55
In the above example, the loop function implements an iteration, the parameter n is used to keep track of the current position, and the parameter sum accumulates the answer. Now let's write the exact same code, but in Scheme:
(let loop ((n 1) (sum 0))
(cond ((> n 10) sum)
(else (loop (+ n 1) (+ n sum)))))
=> 55
Now we've defined a local procedure called loop which is then automatically called with the initial values 1 and 0 for its parameters n and sum. When the base case of the recursion is reached, we return sum, otherwise we keep calling this procedure, passing updated values for the parameters. It's exactly the same as in the Python code! Don't be confused by the syntax.
In your algorithm, i-p and k are the iteration variables, which are initialized to 2 and 0 respectively. Depending on which condition is true, the iteration continues when we call loop again with updated values for i-p and k, or it ends when the case (>= i-p n-p) is reached, at this point the loop exits and the computed value is in the variable sigma-table. The procedure ends by returning a new function, referred to as the "failure function".

How to make a list with generators in Scheme

I'm having problems with this problem because i don't know how to make a list with recursivity using generators. The idea is to create a function that receives a generator that generates n numbers and returns a list with those numbers.
This is my code
;GENERATOR THAT GENERATES "INFINITE NUMBERS OF FIBONACCI"
(define (fib)
(let ((a 0) (b 1))
(lambda ()
(let ((ret a))
(set! a b)
(set! b (+ ret b))
ret))))
;RETURNS A GENERATOR THAT GENERATES NUMBERS OF FIBONACCI UP TO N
(define (taking n g)
(let ((i 1))
(lambda ()
(if (> i n)
#f
(begin
(set! i (+ i 1))
(g))))))
Your definitions are fine! You just need to call them correctly to see it.
> (define t (taking 10 (fib)))
> (t)
0
> (t)
1
> (t)
1
> (t)
2
> (t)
3
> (t)
5
>
UPDATE
(define (generator->list n g)
(if (= n 0)
'()
(cons (g) (generator->list (- n 1) g))))
(generator->list 10 (fib))
So something like this:
(define (to-list gen)
(let loop ((l '()))
(let ((r (gen)))
(if r
(loop (cons r l))
(reverse! l)
))))
Untested. What this does is build up a list in reverse consing the truthy items. When it gets a falsy item, it stops and returns the reverse of the accumulation list.

Scheme - Replacing elements in a list with its index

I am trying to replace the elements in a scheme list with its position.
For example, calling:
(position '((a b) c))
should return:
'((0 1) 2)
So far, my code keeps the list format, but the index is not updating.
(define (position term1)
(define index 0)
(cond [(null? term1) '()]
[(list? term1) (cons (position (car term1)) (position(cdr term1)))]
[else (+ 1 index) index]))
When (position '((a b) c)) is called, it returns
'((0 0) 0)
Can anybody explain why the index isn't updating?
There are a couple things wrong: first notice that every time you recursively call position, index is bound to zero.
Second, look at your else branch. (+ 1 index) evaluates to 1 (it does not change any variables) and index evaluates to 0. This branch can only evaluate to one thing, so what happens is the last one is returned and the rest are discarded. This is where your zeroes come from.
It seems like within your function you are trying to keep a global state (the current index) and modify it each time you label a leaf. The "modifying state" part is not good functional style, but if you are okay with that then take a look at set!.
Here is one solution using CPS:
#lang racket
(define (index xs [i 0] [continue (λ (xs i) xs)])
(match xs
[(cons x xs) (index x i
(λ (js j)
(index xs j
(λ (ks k)
(continue (cons js ks) k)))))]
['() (continue '() i)]
[x (continue i (+ i 1))]))
; Example
;(index '((a b) (c d) x (e (f g) h)))
; '((0 1) (2 3) 4 (5 (6 7) 8))
Here (index xs i continue) replaces the elements in xs with their indices, the count starts from i. Let's say the result of indexing xs is js, then continue is called with the indexing result and the next index to be used: (continue js j).
Daenerys Naharis already pointed out what's wrong, so let me point out some features of Scheme and Racket you may be unaware of that you could use in a solution that maintains functional style.
This is called a named let:
(let loop ((index 0)
(result '()))
(if (= index 10)
(reverse result)
(loop (+ 1 index) (cons index result)))
Within the let form, loop is bound as a function that takes all the local variables as arguments. Calling it recursively calls the let form itself. This way you can make index an argument without making it an argument of position. You can also put the result in an argument, which allows you to make the call to loop a tail call.
The other feature is less widespread among existing Scheme implementations: Optional arguments. In Racket, they're defined like this:
(define (position term1 (index 0)) ...)
Then position can be called with or without the index argument.
An example using mutation that maintains it's own state so that each item of each list has a unique id.
Example Usage:
> (position '((a b) c))
'((0 1) 2)
> (position '((a b) c (d (e))))
'((3 4) 5 (6 (7)))
Example Implementation:
#lang racket
(provide position)
(define base -1)
(define (indexer)
(set! base (add1 base))
base)
(define (position list-of-x)
(cond [(null? list-of-x) null]
[else
(define head (first list-of-x))
(cond [(list? head)
(cons (position head)
(position (rest list-of-x)))]
[else (cons (indexer)
(position (rest list-of-x)))])]))

how to create nested loop in scheme

I am new to scheme and I am trying to create nested loops whose code in C will look like this:-
for(i = -1, a = 0; i > -5, a < 5; i--, a++)
{
for(j = i, b = 0; j < (abs(i)), b < 5; j++, b++)
{
<do something>
}
}
I tried similar thing in scheme with this concept:-
(let oloop( (i -1) (a 0))
(display i)(display a) (newline)
(if (and (> i -5) (< a 5)) (oloop((- i 1) (+ a 1))))))
I am not able to nest all four loops plus above code is not working.
Please suggest.
One way to write these nested loops is to use to do looping construct, which takes 3 arguments: The variables to bind (with initial value, and update forms), the termination condition, and the body forms:
(do ((i -1 (- i 1)) ; Count i downwards from -1
(a 0 (+ a 1))) ; Cound a upwards from 0
((or (= i -5) (= a 5))) ; Stop when i = -5 or a = 5
;; Body of outer loop
(do ((j i (+ j 1)) ; Count j upwards from i
(b 0 (+ b 1))) ; Count b upwards from 0
((or (= (abs i) j) (= b 5))) ; Stop when j = abs(j) or b = 5
;; Body of inner loop: Do something
))
If you insist of doing it by recursion, using named lets, it can be done like this, having the drawback that the forms updating the variables are located far away from the initialization and termination forms:
(let outer ((i -1) (a 0))
(if (and (> i -5) (< a 5))
(begin
(let inner ((j i) (b 0))
(if (and (< j (abs i)) (< b 5))
(begin
; Do something
; then loop
(inner (+ j 1) (+ b 1)))))
(outer (- i 1) (+ a 1)))))
Where is the equivalent of i-- in your Scheme sample?
(+ i 1)
I'm a bit rusty on my Scheme, but I don't think that's it.
Also, I'm not sure where you're getting this base case from in your C program?
(< i 10)
If you're using Racket, there's a pretty straightforward way to implement C-style loops, using iterations and comprehensions. The code looks almost the same:
(for [(i (in-range -1 -5 -1))
(a (in-range 0 5))]
; body of the outer loop
; do something with i a
(for [(j (in-range i (abs i)))
(b (in-range 0 5))]
; body of the inner loop
; do something with i a j b
(display (list i a j b))))

Finding the product of each of the (n-1) subsets of a given array

I'm sorry for deleting the original question, here it is:
We have a bag or an array of n integers, we need to find the product of each of the (n-1) subsets. e.g:
S = {1, 0, 3, 6}
ps[1] = 0*3*6 = 0;
ps[2] = 1*3*6 = 18; etc.
After discussions, we need to take care of the three cases and they are illustrated in the following:
1. S is a set (contains one zero element)
for i=1 to n
if s[i]=0
sp[i] = s[1] * s[2] * ...* s[i-1] * s[i+1] *.....*s[n]
else
sp[i] = 0;
2. S is a bag (contains more than one zero element)
for i=1 to n
sp[i] = 0;
3. S is a set (contains no zero elements)
product = 1
for i=1 to n
product *= s[i];
for i=1 to n
sp[i] = product / s[i];
Thanks.
If the set is very large, it may be convenient to:
compute the product P of all the elements beforehand, and then
for each element x, obtain a (n-1) product as P/x
If the set contains zero (i.e. P=0, x=0), you must deal with it as a special case.
EDIT. Here is a solution in Scheme, taking into account andand's answer. I'm a complete beginner - can someone help me improve the following code (make it more efficient, more readable, more lisp-ish)? (Feel free to edit my answer.)
#!/usr/bin/env guile !#
(use-modules (ice-9 pretty-print))
(define (count-zeros l)
(cond ((null? l) 0)
((= 0 (car l)) (+ 1 (count-zeros (cdr l))))
(else (count-zeros (cdr l)))))
(define (non-zero-product l)
(define (non-zero-product-loop l product)
(cond ((null? l) product)
((= 0 (car l)) (non-zero-product-loop (cdr l) product))
(else (non-zero-product-loop (cdr l) (* (car l) product)))))
(non-zero-product-loop l 1))
(define (n-1-products l)
(let ((nzeros (count-zeros l)))
(cond ((> nzeros 1)
(map (lambda (x) 0) l))
((= 1 nzeros)
(map (lambda (x) (if (= 0 x) (non-zero-product l) 0)) l))
(else
(map (lambda (x) (/ (non-zero-product l) x)) l)))))
(pretty-print (n-1-products '(1 2 3 4 5)))
(pretty-print (n-1-products '(0 1 2 3 4)))
(pretty-print (n-1-products '(0 1 2 3 0)))
You need to explicitly consider the three cases:
1) No zeros: Precompute the product of all of the elements and divide out the desired set element from that product.
2) One zero: Precompute the product of the non-zero elements. The answer is always 0 except when you remove the single zero element, in which case it's the precomputed product.
3) More than one zero: The answer is always 0.
This assumes that you have a data type that can contain the products... that is, you need to be careful that your product doesn't exceed the maximum value of the type you're using to store it.
For the actual implementation, always precompute the product of the non-zero elements and keep track of how many zeros there are. If the "set" is dynamic (its values change) you'll need to update the product and the zero count. When asked for a particular subset product, consider the various cases and act accordingly.
Set product = 1;
for item in set:
if item index == argument index
ignore
else
product *= item
If I understand your question, this is the trivial solution. It should be easy to implement in any programming language.
You can solve this in O(N), using O(1) additional space (not counting the O(N) output array), without even using division. Here's the algorithm in Java.
static int[] products(int... nums) {
final int N = nums.length;
int[] prods = new int[N];
int pi = 1;
for (int i = 0; i < N; i++) {
prods[i] = pi;
pi *= nums[i];
}
int pj = 1;
for (int j = N-1; j >= 0; j--) {
prods[j] *= pj;
pj *= nums[j];
}
return prods;
}
//...
System.out.println(
Arrays.toString(products(1, 2, 3, 4, 5))
); // prints "[120, 60, 40, 30, 24]"
See also
Interview Q: given an array of numbers, return array of products of all other numbers (no division)
Assuming you can use Python:
You can use the combinations method from the itertools module to lazily generate the various subsets of the set in question. Once you have that, you can use reduce and operator.mul to generate the product of each one.

Resources