Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am messing around in language and need some help. I would like to create a swap function that swaps the first with the second. So if (swap '(a b c d e g))
should return (b a d c e g). I dont want to store any values doing it. Is there a function or way to do it in scheme? I have no idea if I would define a list like
(DEFINE list1 (LIST 'a 'b 'c 'd 'e ))
then not sure what to do
The trick is to process two elements at a time, swapping them and advancing two elements in the recursion. This is what I mean:
(define (swap lst)
; if the list is empty or has a single element
(cond ((or (null? lst) (null? (cdr lst)))
; then return that list
lst)
; otherwise build a new list
(else
; by first adding the second element
(cons (cadr lst)
; and then adding the first element
(cons (car lst)
; finally, advance the recursion over two elements
(swap (cddr lst)))))))
I believe the sample output in the question is wrong, where does the f come from? For example the results I'd expect would be:
(swap '(a b c d e g))
=> '(b a d c g e)
(swap '(a b c d e))
=> '(b a d c e)
(swap '(a))
=> '(a)
(swap '())
=> '()
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am losing my mind over evaluating this code to find the error. I am not sure why I am getting an undefined function. Would someone please guide me to understand why? thanks!
O is supposed to be an object, and L a list. I am trying to attach O to the end of the list and return the list
(defun my_attach(O L)
(cond ((eq L nil )
O )
(t (cons (car L) (my-attach O (cdr L)) )
)
)
)
If you have copied correctly your code in the post, you have used two different names for the same function: my_attach (_ is the underscore character) and my-attach (- is the dash character).
Simply use the same name. For instance:
(defun my-attach(O L)
(cond ((eq L nil ) O)
(t (cons (car L) (my-attach O (cdr L))))))
But note that this will not produce the desired result (in fact it does not produce a proper list). Rather, you should use (list O) instead of O in the terminal case:
CL-USER> (defun my-attach(O L)
(cond ((eq L nil) O)
(t (cons (car L) (my-attach O (cdr L))))))
MY-ATTACH
CL-USER> (my-attach 3 '(1 2))
(1 2 . 3)
CL-USER> (my-attach 3 '())
3
CL-USER> (defun my-attach(O L)
(cond ((eq L nil) (list O))
(t (cons (car L) (my-attach O (cdr L))))))
MY-ATTACH
CL-USER> (my-attach 3 '(1 2))
(1 2 3)
CL-USER> (my-attach 3 '())
(3)
Finally, a note about the common writing conventions for Common Lisp programs:
it is preferred to use lower case identifiers;
compound words in identifiers are separated by -, not by _ as in other languages;
it is preferred to use if when there are only two cases in a conditional statement;
check for a value which is nil is commonly done with the predicate null;
the parentheses at the end of an expression are usually written on the same line of the last part of the expression.
So your function could be rewritten as:
(defun my-attach (o l)
(if (null l)
(list o)
(cons (car l) (my-attach o (cdr l)))))
So I've been trying to solve this problem:
Given an element E and a list L insert E into every position in the list L (so the result is a list of lists). Example:
(insert-everywhere 'a '(b c)) would give ((a b c) (b a c) (b c a))
This is easy enough but there is one other condition in my problem that is making it difficult for me - if an element of L is a list itself then the element must also be inserted into every position in the sublist. For example:
(insert-everywhere 'd '(a (b c))) would return: ((d a (b c)) (a d (b c)) (a (d b c)) (a (b d c)) (a (b c d)) (a (b c) d)).
This is the code I have so far (which I mostly lifted from here):
#lang racket
(define (insert-at pos elmt lst)
(if (empty? lst) (list elmt)
(if (list? (car lst)) (insert-everywhere elmt (car lst))
(if (= 1 pos)
(cons elmt lst)
(cons (first lst)
(insert-at (- pos 1) elmt (rest lst)))))))
(define (insert-everywhere sym lst)
(remove-duplicates
(map (lambda (i)
(insert-at i sym lst))
(range 1 (+ 2 (length lst))))))
where this line: (if (list? (car lst)) (insert-everywhere elmt (car lst)) is supposed to handle the sublists but it isn't working. (If I run (insert-everywhere 'd '(a (b c))) with the above code I get ((d a (b c)) (a (d b c) (b d c) (b c d))))
If anyone has suggestions on how to approach this differently I'd be happy to hear.
I wouldn't do indexing as it is very inefficient. Rather reverse the input list and build the list from end to beginning making the results in reverse order. You have a current list that you add elements to with cons that you use to add new additions to the results and each level each result that existed gets the one element added too.
As parameters you have state. When i made a reference I used result and cur and typically my iteration did like this for (insert-everywhere 'd '(a b c)):
lst cur results
(c b a) () ((d))
(b a) (c) ((d c) (c d))
(a) (b c) ((d b c) (b d c) (b c d))
() (a b c) ((d a b c) (a d b c) (a b d c) (a b c d)))
Now adding support for sublists are just doing the same with them and then do a map such that you create one result per sublist in the result, adding cur in addition to adding it as an element.
Notice all new results are just cur with an added inserted element and all th erest gets a new element in fron which is the first element of the input. cur will grow and it is shared so only the elements up to the inserted element will be unique to that sub result.
I have a working implementation, but it's no fun getting the solution prematurely. Have fun.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
INPUT: (A (B (D (E) (F))) (C) (K))
I currently have two functions, which give me an OUTPUT of:
A
B
C
K
B
D
D
E
F
E
NIL
However I need outputs like this:
a: b c k
b: d
c:
k:
d: e f
e:
f:
or
a
b s k
d
e f
(defun print-children (s)
(cond ((null (caar (cdr s))) nil)
(t (print (caar (cdr s))) (print-children (cdr s)))))
(defun print-tree (s)
(cond ((null s) nil)
((atom (car s)) (print (car s)) (print-children s) (print-tree (cdr s)))
(t (print-tree (car s)))))
Node
The first thing you should define: some data structure functions for the node.
nodep thing -> is thing a node?
node-name node -> return the name of the node
node-childrennode -> return the children of the node
Breadth first
Then I would define a function to traverse a tree in breadth-first order.
breadth-first tree fn &optional queue
This function would call FN on all elements of the tree in breadth-first order.
if there are no nodes, end
take the first node off the queue as current node
push the node children of the current node to the end of the queue
call the function FN on the current node
call itself with the tree fn queue
Write this loop above as a recursive function.
Call BREADTH-FIRST
CL-USER 76 > (breadth-first '(A (B (D (E)
(F)))
(C)
(K))
(lambda (node)
(princ (node-name node))
(princ ":")
(mapc (lambda (child)
(princ (node-name child)))
(node-children node))
(terpri)))
A:BCK
B:D
C:
K:
D:EF
E:
F:
I have the following code for even list:
(define (even xs)
(cond
((null? xs) '())
((eq? (cdr xs) '()) '())
(else (cons (cadr xs) (even (cddr xs))))))
;(even-list '(a b c d)) produces (b d)
How can I do the same for odd list that produce (a c) if (odd-list '(a b c d)) is enetered.
I'm sure you're asked to write this out fully, on your own. For that, do note that (in the code you provide) you're checking whether the cdr is empty list, because you're taking the cadr as your first element.
For odds, you don't need the cadr. The first element is at an odd position already.
But there's also a simple trick you could use.
Question: what effect does (cons 1 xs) have on the length of xs?
Structure Definition:
(define-struct movie (title genre stars))
;; title is a nonempty string
;; genre is a nonempty string
;; stars us a list of nonempty strings
I am trying to write a scheme function that consumes a list of movies and produces the genre that occurs most often.
So far, I have the following:
(define (popular-gnere movies)
(local
[(define acc movies genre)
(cond
[(empty? movies) genre]
[(equal? genre (movie-genre (first movies)))
(acc (rest movies genre)))
I'm stuck as to how I can keep count of how many times a specific genre has appeared in a given list of movies.
I understand that accumulated recursion in this case would be most efficient but am having trouble completing my accumulator.
Why don't you fix your parentheses problem and indent the code properly. Press CRTL+i. Where the identation is wrong you probably have missing parentheses. Press Run to evaluate and you'd get proper error messages. When you have something that doesn't produce errors, update this question.
The answer your question you add more parameters to your local procedures than the global. That way you hae a parameter that can hold a count that you increase when you find the search element in the current element.eg.
(define (length lst)
(define (length-aux lst cnt)
(if (null? lst)
cnt
(length-aux (cdr lst) (add1 cnt))))
(length-aux lst 0))
Or better with named let
(define (length lst)
(let length-aux ((lst lst) (cnt 0))
(if (null? lst)
cnt
(length-aux (cdr lst) (add1 cnt)))))
EDIT
I recommend having at least 4 helper procedures that takes each their part of a problem. (Less if you make use racket's own remove, count, and argmax). Note that there are probably many other ways to solve this but this is how I would have solved it without a hash table.
Since you are only interested in genre the first thing to imagine is that you can do (map movie-genre lst) so that you get a list of genres to work with in your main helper.
In your main helper you can build up a list of cons having genre and count. To do that you use a helper count that (count 'c '(a b c d c c a) 0) ==> 3 and you just take the first genre and count the list for those as the first accumulated value, then process the result of (remove 'c '(a b c d c c a) '()) ==> (a d b a) on the rest of the list.
When processing is done you have in your accumulator ((a . 4) (b . 6) ...) and you need a helper (max-genre 'a 4 '((b . 6) (c . 20) (d . 10))) ; ==> c
The main helper would look something like this:
(define (aux lst acc)
(if (null? lst)
(max-genre (caar acc) (cdar acc) (cdr acc))
(aux (remove (car lst) lst '())
(cons (cons (car lst) (count (car lst) lst 0)) acc))))
Now you could do it a lot simpler with a hash table in one pass. You'd still have to have max-genre/argmax after reading all elements once.
First you need to settle on a key-value datatype. You could use association lists, but hash tables are a more efficient choice.
Let's start with a short list:
(define-struct movie (title genre stars))
(define films
(list
(make-movie "Godfater" "Crime" '("Marlon Brando" "Al Pacino"))
(make-movie "Rambo" "Thriller" '("Sylvester Stallone"))
(make-movie "Silence of the Lambs" "Crime" '("Jodie Foster" "Anthony Hopkins"))))
and create an empty hash table
(define h (make-hash))
Now we process every film, updating the hash table as we go:
> (for-each (lambda (e) (hash-update! h e add1 0)) (map movie-genre films))
> h
'#hash(("Thriller" . 1) ("Crime" . 2))
Now we need to find the highest count:
> (hash-values h)
'(1 2)
> (define most (foldl (lambda (e r) (if (> e r) e r)) 0 (hash-values h)))
> most
2
So 2 is our highest count. Now we create a list of all genres with count 2:
> (hash->list h)
'(("Thriller" . 1) ("Crime" . 2))
> (foldl
(lambda (e r) (if (= (cdr e) most) (cons (car e) r) r))
null
(hash->list h))
'("Crime")
Putting it all together:
(define (count-by-genre lst)
(define h (make-hash))
(for-each (lambda (e) (hash-update! h e add1 0)) (map movie-genre lst))
(define most (foldl (lambda (e r) (if (> e r) e r)) 0 (hash-values h)))
(foldl
(lambda (e r) (if (= (cdr e) most) (cons (car e) r) r))
null
(hash->list h)))
But this is quite inefficient, for several reasons:
after updating the hash table, we have to re-iterate over it, create a list and then apply foldl just to find the highest value, whereas we could have just kept note of it while updating the hash table
then again we create a full list (hash->list) and a final result list using foldl.
Lots of consing and stuff. An alternative, more efficient version using Racket-specific for constructs, could be:
(define (count-by-genre lst)
(define h (make-hash))
(define most
(for/fold ((highest 0)) ((e (in-list (map movie-genre lst))))
(define new (add1 (hash-ref h e 0)))
(hash-set! h e new)
(max highest new)))
(for/fold ((res null)) (((k v) (in-hash h)))
(if (= v most) (cons k res) res)))