My question is how do i code for
(triangle 5) produces (list "*****" "****" "***" "**" "*")
Note: (5 astericks 4, then 3 then 2 then 1). So far I have:
(define (triangle n)
(cond
[(zero? n) empty]
[else (cons n (triangle (sub1 n)))]))
But that only gives me (list 5 4 3 2 1). Please keep note that this uses only the basic of scheme beginner lists and abbreviations. Thanks!
It's always a good idea to split a complex problem in simpler, shorter subparts. In this case, we can simplify the general solution by first writing solutions to subproblems, like this:
First, build a procedure that creates a list of strings, where a string is "*****" or "****" or ... or "*"
Second, write a repeat helper procedure that given a string and a number, repeats the string that many times - for example: (repeat "*" 3) will return "***"
It's easy to see how the first subproblem can be expressed in terms of the second one. Because this looks like a homework, you shouldn't be asking for complete solutions here. It'll be more useful for you to reach the answer by yourself, here's the general idea, fill-in the blanks:
(define (triangle n)
(cond [<???> <???>] ; if n is zero return the empty list: '()
[else ; otherwise
(cons <???> ; cons n repetitions of * (using `repeat`)
(triangle <???>))])) ; and advance the recursion
(define (repeat str n)
(cond [<???> <???>] ; if n is zero return the empty string: ""
[else ; otherwise
(string-append <???> ; append the given string
(repeat <???> <???>))])) ; and advance the recursion
If you look at it carefully, both procedures share exactly the same structure. What changes is the value returned in the base case (an empty list and an empty string) and the procedure used for sticking together the partial answers (cons and string-append).
If you're just looking for how to convert numbers to string, you can use the (number->string x).
However, since you're looking to have the numbers represented as asterisks, it may be better for you to keep them as numbers until you've constructed a string of asterisks. In that case, you probably want a method like:
(define (num-to-asterisks x)
(make-string x #\*))
Try this:
(define (triangle n)
(let building ((i 0) (r '()))
(if (= i n)
r
(building (+ i 1)
(cons (string-append "*" (if (null? r) "" (car r)))
r)))))
this is nicely tail-recursive; builds up the result list by adding "*" to the first element of the result list.
Related
I'm trying to write code where it creates a string list increasing order with using only recursion and nothing else.
How should I go about doing this?
(define (create-list n st)
(cond [(zero? n) ""]
[else (string-append "X" (create-list (sub1 n) st))]))
(define (stair n)
(cond [(equal? n 0) empty]
[else (cons (create-list n "x") (stair (- n 1)))]))
;; (stair 4) --> (list "XXXX" "XXX" "XX" "X")
Desired output: (list "X" "XX" "XXX" "XXXX")
Replace
(cons (create-list n "x") (stair (- n 1)))
with
(append (stair (- n 1)) (list (create-list n "Q")))
(Note that create-list doesn't actually use the st argument.)
All Scheme lists are created from end to beginning. You want to create ("XXXX") first, then ("XXX" "XXXX") etc. Whenever you do (cons "X" (recursion ....)) then (recursion ...) needs to finish before the cons while the most efficient is by using an accumulator. Using append each step smell wrong since append is O(n) so if you do do that each step then you have O(n^2). With a couple of thousand elements you'll start noticing the difference.
You don't need create-list, which doesn't create a list but a string, since Scheme has make-string that does what you want:
(make-string 3 #\X) ; ==> "XXX"
So here is stair:
(define (stair n)
(define (xs n)
(make-string n #\X))
(let helper ((n n) (acc '()))
(if (zero? n)
acc
(helper (- n 1)
(cons (xs n) acc)))))
So in this case if you wanted it in the reverse order you would have used different name than n and gone upward until this and n were passed. Sometimes you don't have the luxury to choose, eg, if you were to copy a list, then often you can building the reverse, then reverse the result. Sometime you need to use memory and need the continuations, but this will restrict how deep your structures can be before the program stops working. In rackets case it doesn't stop until you have depleted the whole heap memory you have supplied it.
I have a question regarding finding the largest list in a group of lists in scheme.
For example, we define:
(define manylsts (list (list 9 (list 8 7)) 6 (list 5 (list 4 3 2) 1)))
How would I go about finding the largest list in manylsts?
Thank you
You make a procedure that evaluates to zero if it's argument is not a list. (eg. 9), then if its a list you foldl over the elements using length of the argument as accumulator with a lambda that does max between the recursion of the first argument with the accumulator. It would look something like this:
(define (max-children tree)
(if <??>
(foldl (λ (x acc)
(max <??> (max-children <??>)))
(length <??>)
<??>)
0))
Of course there are many ways of doing this, including explicit recursion, but this was the first thing I though of.
I will answer this question as you asked it.
You said you want to
finding the largest list in manylsts
Since you included a non-listed element inside manylsts you want to have a definition that tells you how big is an element (if is a list).
So I wrote the function elemenlen that returns the length of a list if the given element is a list and 0 otherwise.
(define elemenlen
(λ (a)
(if (list? a) (length a) 0)
))
Then I decided I was going to sort them in order of length and then return the first element. So I need a function that returns a boolean value to use it with sort function included in racket/base.
(define list<
(λ (listA listB)
(< (elemenlen listA) (elemenlen listB))))
(define list>
(λ (listA listB)
(not (list< listA listB))))
The first function returns #t if listA is smaller than listB. The second function returns #t if listA is bigger than listB.
Lastly, biggestElement does the whole trick, sorts the elements in list L in descending order (based on length) and returns the first element.
(define biggestElement
(λ (L)
(car (sort L list>)
)))
The function is used like this:
>(biggestElement '((3 2 1) 1 (1 (2 3) 3))
'(1 (2 3) 3)
That is just one way of doing it, there are other ways of doing it, keep it up and tell us if it helped you.
As you see, I decomposed the big problem into little problems. This is a very handy way of doing your DrRacket homework.
I am new to Racket, and I am trying to write a recursive function that takes a number n and returns the sum of the squares of the first n integers. For example, (this-function 3) returns 14 because 14 is 9 + 4 + 1 + 0.
I tried creating two separate functions, one that squares each number and returns a list of the squared numbers, and a second that sums up the list. The function the squares each number is:
(define (squared my-list)
(cond [(empty? my-list) empty]
[(zero? my-list) 0]
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
which if I run (squared 3) returns (cons 9 (cons (cons 4 (cons (cons 1 (cons 0 empty)) empty)) empty)).
When I run the second function (the sum function):
(define (sum numbers)
(cond
[(empty? numbers) 0]
[else (+ (first numbers) (sum (rest numbers)))]))
and run (sum (squared 3)) I get an error message because (squared 3) returns an extra "cons" in the list.
How can I fix this?
Your logic in squared is a little bit off. I'll explain the issues clause-by-clause.
[(empty? my-list) empty]
This doesn't make any sense since my-list will never even be a list. In fact, my-list is poorly named. The parameter squared takes is a number, not a list. This clause can be completely removed.
[(zero? my-list) 0]
This is what the actual terminating case should be, but it shouldn't return 0. Remember, squared has to return a list, not a number. This case should return empty.
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
Finally, this clause is far too complicated. You have the right idea—to cons the new number onto the rest of the list—but you're cons'ing too many times. Remember, the result of (squared (sub1 my-list)) is itself a list, and the second argument of cons is the rest of the list. You don't need the extra cons—you can just eliminate it completely.
Combining these changes, you get this, which does what you want:
(define (squared my-list)
(if (zero? my-list) empty
(cons (expt my-list 2)
(squared (sub1 my-list)))))
(I also replaced cond with if since cond is no longer necessary.)
That said, this code is not very Racket-y. You had a good idea to break up your function into two functions—in functional programming, functions should really only ever do one thing—but you can break this up further! Specifically, you can leverage Racket's built-in higher-order functions to make this type of thing extremely easy.
You can replace your entire squared function by appropriately combining map and range. For example, the following creates a list of the squares from 0–3.
(map (curryr expt 2) (range 4))
(You need to call (range 4) because the list generated by range goes from 0 to n-1.)
Next, you can easily sum a list using apply. To sum the above list, you'd do something like this:
(apply + (map (curryr expt 2) (range 4)))
That gives you the appropriate result of 14. Obviously, you could encapsulate this in its own function for clarity, but it's a lot clearer what the above code is doing once you learn Racket's functional constructs.
(However, I'm not sure if you're allowed to use those, since your question looks a lot like homework. Just noted for future reference and completeness.)
The most straightforward solution is to use the closed form:
(define (sum-of-squares n)
(* 1/6 n (+ n 1) (+ n n 1)))
Credit: WolframAlpha
one function for providing a list of squares and one function for summing up the list is not necessary.
This will do the trick, and is recursive as required.
(define (my-sq n)
(cond [(zero? n) 0]
[else
(+ (* n n) (my-sq (- n 1)))]))
(my-sq 3) -> 14
Ok, so I'm trying to write a function that finds the distance between two elements in a list, s and t.
For example, if s = bob and t = pizza:
(d 'bob 'pizza '(bob blah blah pizza))
it would return: 3
This is what I have so far.
(define dist
(lambda (s t line)
(cond
[(equal? s (car line))
[(equal? t (car (cdr line)))
1]]
[else (add1 (dist s t (cdr line)))])))
For some reason, it's not working. Help?
Thanks!
The proposed code in the question is not going to work, it's just checking if the two elements are contiguous in the list. Let's try a different approach altogether - split the problem in smaller subproblems, begin by defining a procedure that returns the index of an element in a list, counting indexes from zero:
(define (index-of elt lst)
<???>) ; ToDo
With the above procedure in place, and assuming that both s and t are present in the list and t appears after s, it's easy to find the solution to the question:
(define dist
(lambda (s t line)
(- (index-of t line)
(index-of s line))))
For example:
(dist 'bob 'pizza '(bob blah blah pizza))
=> 3
For extra credit, consider the cases where one or both of the elements are not present in the list (so index-of should return a value indicating this, say, #f), or when s appears after t in the list.
When you are taking (cdr line) in the last step you are throwing away bob even if bob is the first element.
You need to take care of 3 and maybe 4 cases.
Where s and t match the first two elements you do fine.
Where s matches and t doesn't you need to add 1 to a recursive call using line with the 2nd element removed. Something like (cons (car line) (cdr (cdr line))).
Where s doesn't match you need to remove the car of line and try again.
Unless you are sure s and t will both occur and in order you need a terminating condition(s) to take care of running out of line.
Here is a solution that iterates down the list looking for 's' and 't' each time. When both have been seen, the result is returned; otherwise, continue looking:
(define (dist s t line)
(let looking ((l line) (n 0) (i #f))
(and (not (null? l))
(let ((item (car l)))
(if (or (equal? item s)
(equal? item t))
(if (not i)
(looking (cdr l) (+ n 1) n) ; found first, continue
(- n i)) ; found second, done
(looking (cdr l) (+ n 1) i)))))); continue looking
Hi I am trying to write a program where given a list of lists check to see if they are equal in size and return #t if they are.
So for example if i were to write (list-counter? '((1 2 3) (4 5 6) (7 8 9))) the program would return #t, and (list-counter? '((1 2 3) (4 5 6) (7 8))) would return #f.
SO far this is what I have done:
(define list-counter?
(lambda (x)
(if (list? x)
(if (list?(car x))
(let (l (length (car x))))
(if (equal? l (length(car x))))
(list-counter?(cdr x))
) ) ) ) )
I think where I am going wrong is after I set the length of l to the length of the first list. Any help would be appreciated.
There are several ways to solve this problem. For instance, by hand and going step-by-step:
(define (all-lengths lists)
(if (null? lists)
'()
(cons (length (car lists))
(all-lengths (cdr lists)))))
(define (all-equal? head lengths)
(if (null? lengths)
true
(and (= head (car lengths))
(all-equal? head (cdr lengths)))))
(define (list-counter? lists)
(let ((lengths (all-lengths lists)))
(all-equal? (car lengths) (cdr lengths))))
Let me explain the above procedures. I'm dividing the problem in two steps, first create a new list with the lengths of each sublist - that's what all-lengths does. Then, compare the first element in a list with the rest of the elements, and see if they're all equal - that's what all-equal? does. Finally, list-counter? wraps it all together, calling both of the previous procedures with the right parameters.
Or even simpler (and shorter), by using list procedures (higher-order procedures):
(define (list-counter? lists)
(apply = (map length lists)))
For understanding the second solution, observe that all-lengths and all-equal? represent special cases of more general procedures. When we need to create a new list with the result of applying a procedure to each of the elements of another list, we use map. And when we need to apply a procedure (= in this case) to all of the elements of a list at the same time, we use apply. And that's exactly what the second version of list-counter? is doing.
You could write an all-equal? function like so:
(define (all-equal? list)
;; (all-equal? '()) -> #t
;; (all-equal? '(35)) -> #t
;; (all-equal? '(2 3 2)) -> #f
(if (or (null? list) (null? (cdr list)))
#t
(reduce equal? list)
))
then do:
(all-equal? (map length listOfLists))
Alternatively you can do:
(define (lists-same-size? list-of-lists)
(if (== (length listOfLists) 0)
#t
(let*
(( firstLength
(length (car listOfLists)) )
( length-equal-to-first?
(lambda (x) (== (length x) firstLength)) )
)
(reduce and #t (map length-equal-to-first? listOfLists))
)
)))
What this says is: if the list length is 0, our statement is vacuously true, otherwise we capture the first element of the list's length (in the 'else' part of the if-clause), put it in the closure defined by let's syntactic sugar (actually a lambda), and use that to define an length-equal-to-first? function.
Unfortunately reduce is not lazy. What we'd really like is to avoid calculating lengths of lists if we find that just one is not equal. Thus to be more efficient we could do:
...
(let*
...
( all-match? ;; lazy
(lambda (pred list)
(if (null? list)
#t
(and (pred (first list)) (all-match? (cdr list)))
;;^^^^^^^^^^^^^^^^^^^ stops recursion if this is false
)) )
)
(all-match? length-equal-to-first? listOfLists)
)
)))
Note that all-match? is already effectively defined for you with MIT scheme's (list-search-positive list pred) or (for-all? list pred), or in Racket as andmap.
Why does it take so long to write?
You are forced to write a base-case because your reduction has no canonical element since it relies on the first element, and list manipulation in most languages is not very powerful. You'd even have the same issue in other languages like Python. In case this helps:
second method:
if len(listOfLists)==0:
return True
else:
firstLength = len(listOfLists[0])
return all(len(x)==firstLength for x in listOfLists)
However the first method is much simpler to write in any language, because it skirts this issue by ignoring the base-cases.
first method:
if len(listOfLists)<2:
return True
else:
return reduce(lambda a,b: a==b, listOfLists)
This might sound a bit weird, but I think it is easy.
Run down the list, building a new list containing the length of each (contained) list, i.e. map length.
Run down the constructed list of lengths, comparing the head to the rest, return #t if they are all the same as the head. Return false as soon as it fails to match the head.