I have to get in racket in under O (n^2) time complexity longest suffix of two lists of different sizes.I am forbidden to use reverse on the lists or a helper prefix function and I need to get the result in the same order.
(define (common-suffix L1 L2)
(if (= (length L1) (length L2))
(if (= 0 (min (length L1) (length L2)))
'()
(if (equal? (car L1) (car L2))
(append (cons (car L1) null) (common-suffix (cdr L1) (cdr L2)))
(append (common-suffix (cdr L1) (cdr L2)) null)))
(if (< (length L1) (length L2))
(common-suffix L1 (cdr L2))
(common-suffix (cdr L1) L2))))
This is my implemantation and I only need to know if it's under O (N^2) time complexity. Thank you:)
Related
(define (oddrev ls)
(cond ((null? ls) ls)
((null? (cdr ls)) ls)
(else (cons (car ls) (oddrev (cdr (cdr ls)))))))
I have a scheme that returns odd array elements but I want to reverse the list at the end.
How would I do that??
The trivial solution is to add a layer of indirection:
(define (oddrev-helper ls)
(cond ((null? ls) ls)
((null? (cdr ls)) ls)
(else (cons (car ls) (oddrev-helper (cdr (cdr ls)))))))
(define (oddrev ls) (reverse (oddrev-helper ls)))
This looks wasteful, but is much more efficient than repeatedly appending a singleton list at the end.
But if you have encountered the way to transform a recursive process to an iterative by way of an accumulator and tail recursion, you will have noticed that list procedures have a habit of producing the result in reverse.
You can take advantage of this if you actually want the result in reverse.
(define (oddrev-helper ls acc)
(cond ((null? ls) acc)
((null? (cdr ls)) (cons (car ls) acc))
(else (oddrev-helper (cdr (cdr ls)) (cons (car ls) acc)))))
(define (oddrev ls) (oddrev-helper ls '()))
By tail recursion (and leaving out the usual reverseing at the end when returning.
(define (oddrev ls (acc '()))
(cond ((or (null? ls) (null? (cdr ls))) acc)
(else (oddrev (cdr (cdr ls)) (cons (car ls) acc)))))
Or by standard higher order functions:
(define (oddrev ls)
(reverse (filter odd? ls)))
Try out:
(oddrev '(1 2 3 4 5 6))
;; '(5 3 1)
change the line
(cond ((or (null? ls) (null? (cdr ls))) acc)
to:
(cond ((or (null? ls) (null? (cdr ls))) (reverse acc))
to let it return in the input order: '(1 3 5)
I need make a boolean function for evaluating two list,for example:
(define list1 '((1 2) (4 5) (8 6) (2 8)))
(define list2 '((1 2) (8 6)))
list2 is a sublist of list1, and must returned #t, but I don't know how do it, I try with this function for comparing two list
(define (sublist? lst1 lst2)
(if (null? lst2)
#f
(if(list? (car lst2))
(sublist? lst1 (car lst2))
(if (and(equal? car(lst1) (car lst2)) (equal? cdr(lst1) (car lst2)))
#t (sublist? lst1 (cdr lst2))))))
help :(
This sublist? behaves as a "subset?".
; sublist? : list list -> "boolean"
; return non-false if all elements of xs are in ys
(define (sublist? xs ys)
(or (null? xs) ; the empty list is a sublist of ys
(and ; for a non-empty list
(member (car xs) ys) ; the first element must be in ys
(sublist? (cdr xs) ys)))) ; and the rest of the elements as well.
This sublist? behaves as a "substring?"
; prefix? : list list -> boolean
; is xs a prefix of ys?
(define (prefix? xs ys)
(or (null? xs)
(and (equal? (car xs) (car ys))
(prefix? (cdr xs) (cdr ys)))))
; sublist? : list list -> boolean
; is xs a consecutive sublist of ys?
(define (sublist? xs ys)
(or (null? xs)
(prefix? xs ys)
(and (not (null? ys))
(prefix? xs (cdr ys)))))
A suggested solution:
(define list1 '((1 2) (4 5) (8 6) (2 8)))
(define list2 '((4 5) (8 6)))
(define (sublist? lst1 lst2)
(if (null? lst2)
#t
(if (and (null? lst1)
(not (null? lst2)))
#f
(if (list? (car lst2))
(or (and (sublist? (car lst1) (car lst2))
(sublist? (cdr lst1) (cdr lst2)))
(sublist? (cdr lst1) lst2))
(if (eq? (car lst1) (car lst2))
(sublist? (cdr lst1) (cdr lst2))
(sublist? (cdr lst1) lst2))))))
(sublist? list1 list2)
Explanation:
This is (not) simply handling all the edge-cases:
- If list2 is null - it is always a sublist of list1
- If we got to the end of list1 and list2 is not yet found - return false
- If (car list2) is a list - we need to check recursively two cases: if (car list1) equals to (car list2) or if (car list2) is somewhere else in (cdr list1)
- If (car list1) and (car list2) are the same - we'll check recursively with the rest of both lists: (cdr lst1) and (cdr lst2)
This answer was tested here
I have a list '(1 2 1 1 4 5) and want output list as '((1 3)(2 1)(4 1)(5 1)). I have written a small code but I am stuck with how to calculate the cardinality for each number and then put it as pair in list. Can anyone please look at my code and give some ideas?
(define set2bags
(lambda (randlist)
(cond ((null? randlist) '())
(else
(sort randlist)
(makepairs randlist)))))
(define makepairs
(lambda (inlist)
(let ((x 0)) ((newlist '()))
(cond ((zero? (car inlist)) '())
(else
(eq? (car inlist)(car (cdr inlist)))
(+ x 1)
(makepairs (cdr inlist))
(append newlist (cons (car inlist) x)))))))
Your current solution is incorrect - it doesn't even compile. Let's start again from scratch, using a named let for traversing the input list:
(define set2bags
(lambda (randlist)
(cond ((null? randlist) '())
(else (makepairs (sort randlist >))))))
(define makepairs
(lambda (inlist)
(let loop ((lst inlist)
(prv (car inlist))
(num 0)
(acc '()))
(cond ((null? lst)
(cons (list prv num) acc))
((= (car lst) prv)
(loop (cdr lst) prv (add1 num) acc))
(else
(loop (cdr lst) (car lst) 1 (cons (list prv num) acc)))))))
Now it works as expected:
(set2bags '(1 2 1 1 4 5))
=> '((1 3) (2 1) (4 1) (5 1))
The trick is keeping a counter for the cardinality (I called it num), and incrementing it as long as the same previous element (I named it prv) equals the current element. Whenever we find a different element, we add a new pair to the output list (called acc) and reset the previous element and the counter.
Your code is fairly hard to read without proper formating.
I notice a two branch cond, which is easier to read as an if.
In your else clause of set2bags, you call (sort randlist) but leave it as is. You actually want to use this in the next s-expression (makepairs (sort randlist))
So far a pretty good idea.
Now in makepairs you should have better abstraction, say let variables like-first and unlike-first. If the inlist is null, then the function should be the null list, else it's the pair with the car being the list of the car of like-first and the length of like-first and the cdr being the result of calling makepairs on the unlike-first list
(define (makepairs inlist)
(let ((like-first (filter (lambda (x) (equal? x (car inlist)) inlist))
(unlike-first (filter (lambda (x) (not (equal? x (car inlist))) inlist)))
(if (null? inlist)
'()
(cons (list (car inlist) (length like-first)) (makepairs unlike-first)))))
more effecient version
(define (makepairs inlist)
(if (null? inlist)
'()
(let loop ((firsts (list (car inlist)))
(but-firsts (cdr inlist)))
(if (or (null? but-firsts)
(not (equal? (car firsts) (car but-firsts))))
(cons (list (car firsts) (length firsts))
(makepairs but-firsts))
(loop (cons (car but-firsts) firsts) (cdr but-firsts))))))
]=> (makepairs (list 1 1 1 2 4 5))
;Value 17: ((1 3) (2 1) (4 1) (5 1))
If you have your own implementation of sort, say a mergesort you could write this right into the merge part for the best effeciency.
(define (set2bags lst)
(mergesort2bags lst <))
(define (mergesort2bags lst pred)
(let* ((halves (divide-evenly lst))
(first-half (car halves))
(other-half (cadr halves)))
(cond ((null? lst) '())
((null? (cdr lst)) (list (list (car lst) 1)))
(else
(merge-bags
(mergesort2bags first-half pred)
(mergesort2bags other-half pred)
pred)))))
(define (divide-evenly lst)
(let loop
((to-go lst)
(L1 '())
(l2 '()))
(if (null? to-go)
(list L1 L2)
(loop (cdr to-go) (cons (car to-go) L2) L1))))
(define (merge-bags L1 L2 pred)
(cond ((null? L1) L2)
((null? L2) L1)
((pred (caar L1) (caar L2))
(cons (car L1) (merge-bags (cdr L1) L2 pred)))
((equal? (caar L1) (caar L2))
(cons (list (caar L1) (+ (cadar L1) (cadar L2)))
(merge-bags (cdr L1) (cdr L2) pred)))
(else (cons (car L2) (merge-bags L1 (cdr L2) pred)))))
(mergesort2bags (list 1 2 1 1 4 5) <)
;Value 46: ((1 3) (2 1) (4 1) (5 1))
I'm thinking for very large datasets with a lot of repetition this method would pay off.
I'm trying to write a function to analyze game trees. The trees are represented by nested lists where each sub-list represents a branch. Basically, there are two things I want to figure out:
what is the minimax value of a nested list?
what is the index of that value?
I thought I had mostly solved the first problem, but my code keeps returning the wrong values--I've checked everything over and can't see what I've done wrong.
Any help would be much appreciated, thanks!
;MINIMAX*
(define minimax*
(lambda (l operation hilo)
(cond
((null? l) hilo)
((equal? operation 'max)
(cond
((null? (cdr l)) (if
(list? (car l))
(minimax* (car l) 'min hilo)
(if
(> (car l) hilo)
(car l)
hilo)))
(else (if
(list? (car l))
(if
(> (minimax* (car l) 'min hilo) hilo)
(minimax* (cdr l) 'max (minimax* (car l) 'min hilo))
(minimax* (cdr l) 'max hilo))
(if
(> (car l) hilo)
(minimax* (cdr l) 'max (car l))
(minimax* (cdr l) 'max hilo))))))
((equal? operation 'min)
(cond
((null? (cdr l)) (if
(list? (car l))
(minimax* (car l) 'max hilo)
(if
(< (car l) hilo)
(car l)
hilo)))
(else (if
(list? (car l))
(if
(< (minimax* (car l) 'max hilo) hilo)
(minimax* (cdr l) 'min (minimax* (car l) 'max hilo))
(minimax* (cdr l) 'min hilo))
(if
(< (car l) hilo)
(minimax* (cdr l) 'min (car l))
(minimax* (cdr l) 'min hilo))))))
(else (error "Invalid operation type, must be 'max or 'min")))))
You should change your approach a little bit. Instead of programming one fundamental procedure that makes the everything, you can implement some utility procedures.
For the minimax procedure it does not matter if the data comes in a tree or a list. So you can write yourself a procedure that converters your tree into a list like this one
(define (fringe t)
(cond ((null? t) t)
((pair? (car t)) (append (fringe (car t))
(fringe (cdr t))))
(else (cons (car t) (fringe (cdr t))))))
Checking for minimum or maximum is basically an iteration over a list or tree. So you could do that with fold. See http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/Reduction-of-Lists.html
So you can write your procedure like this:
(define (minimax op t)
(let ((flat-list (fringe t)))
(fold op (car t) (cdr t))))
For further reading Structure and Interpretation of Computer Programs. It is a great book for learning Scheme and programing in general.
I'm trying to write a function that merges and then sorts a list, but now I have two different functions; one that merges it and one that sorts it. So I'm trying to write another function, that calls either functions, so it can merge and sort a list at once in that function.
This is what I have:
;; this merges the list
(define (merge l1 l2)
(cond ((null? l1) l2)
((null? l2) l1)
((< (car l1) (car l2)) (cons (car l1) (merge (cdr l1) l2)))
(else (cons (car l2) (merge l1 (cdr l2))))))
;; this sorts the list
(define sort
(lambda (lst)
(if (null? lst)
'()
(insert (car lst)
(sort (cdr lst))))))
(define insert
(lambda (elt sorted-lst)
(if (null? sorted-lst)
(list elt)
(if (<= elt (car sorted-lst))
(cons elt sorted-lst)
(cons (car sorted-lst)
(insert elt (cdr sorted-lst)))))))
You define your merge-sort like this:
(define (merge-sort l1 l2) (sort (merge l1 l2)))
Example:
> (merge-sort (list 8 3 7 4 9 2) (list 5 1 0 6 4))
(0 1 2 3 4 4 5 6 7 8 9)
Why not use one already written for you :)