solution for a homework in racket [closed] - racket

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
i'm new to racket Programming language.
i need to provide a solution in racket but i couldn't write something that works.
question :
Define a max-gap function that consumes five integers and returns the largest gap (in absolute value, i.e., a natural number) within any two (in the order in which they appear). For example, (max-gap 1 3 -1 1 1) would return 4. You might want to use the Racket functions max, abs.
output for example:
(test (max-gap 1 5 -1 6 22) => 16)

#lang racket
(require datalog)
(define mg-theory (make-theory))
(datalog mg-theory
(! (:- (max-gap-datalog A B C D E X)
(max A B C D E :- MX)
(min A B C D E :- MN)
(- MX MN :- X))))
(define (max-gap a b c d e)
(hash-ref (first
(datalog mg-theory
(? (max-gap-datalog a b c d e X)))) 'X))
Example:
> (max-gap 1 3 -1 1 1)
4
> (max-gap 1 5 -1 6 22)
23
If you post some of the attempts you've made, I will help you arrive at a more idiomatic solution than this one.

Related

how to convert number into strings [closed]

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 2 years ago.
Improve this question
I don't know what's wrong with my code or language, (/ 1 2) in racket will be calculated as 1/2, but it's printed as 0.5, I need to convert a number to string, so no slash, I know it's 1/2 cuz I saw the stepping.
I can't share my code I'm so sorry, this is an assignment question, but I'm asking general stuff so it's fine.
You can split a number into numerator and denominator, and then add the "/" between their string representation to get a fraction.
(define n1 1/2)
(define n2 (/ 1 2))
(define (frac->str n)
(string-append
(number->string (numerator n))
"/"
(number->string (denominator n))))
(frac->str n1)
; => "1/2"
(frac->str n2)
; => "1/2"

Little lisp challenge [closed]

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 have a string like "2d 6:36", and I want to multiply that amount of hours by a constant.
This means I want this to be calculated:
(2*24 + 6 + 36/60) * constant
or, in general
(d*24 + h + m/60)
Any help?
Edit: I only have the string not, the d, h and m.
You need parse your string in something useful, for example a list of integers, you can use cl-ppcre for this:
(defun parse-day-and-time (string)
"Get string like 3d 23:40 and return list (3 23 40)"
(multiple-value-bind (str matches)
(cl-ppcre:scan-to-strings "(\\d+)d ([0-9]|0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])" string)
(declare (ignore str))
(when (< (length matches) 3)
(error "Wrong day and time string: ~A" string))
(map 'list #'parse-integer matches)))
Then you can do yout calculation:
(defun mult-time (string-time coeff)
(destructuring-bind (days hours minutes)
(parse-day-and-time string-time)
(* coeff (+ (* 24 days) hours (/ minutes 60)))))
CL-USER> (mult-time "2d 6:36" 300)
16380
Of cause if you want to do some more calculations with your time, may be it will be better to represent it as amount of seconds, do your calculation with it, then return it in any string you want.
So I understand the data to be a human readable amount of time.. E.g. "2d 1:35" represent 2 days, 1 hour and 35 seconds or 595/12 hours. I'm tempted to let loose the spec for the string like this:
(defparameter *units* '(("w" . 168) ("d" . 24) (":" . 1)
("h" . 1) ("m" . 1/60) ("s" . 1/3600)))
(defun str-to-hours (str &optional (acc 0))
(or
(cl-ppcre:register-groups-bind (num unit rest)
("(\\d+)\\s*(\\D{0,1})\\D*(.*)" str :sharedp t)
(str-to-hours rest
(+ acc
(* (parse-integer num)
(or (cdr (assoc (string-downcase unit)
*units*
:test #'equal))
1/60)))))
acc))
(str-to-hours "2d 6:36") ; ==> 273/5 ~54.6
(str-to-hours "2D6H36M") ; ==> 273/5 ~54.6
(str-to-hours "2 weeks, 1 day, 3 hours, 7 minutes and 10 seconds") ; ==> 130723/360 ~363.11945
(* 10 (str-to-hours "2d6:36")) ; ==> 546

Adding two lists

I want to add two lists : (1 2 3) and (5 3 4) should yield (6 5 7).
The function should add the elements on the corresponding position, so even if I would have (9 1 2) + ( 5 2 6) , it should yield (14 3 8).
My function
(defun add(l r)
(setf return-value '())
(loop for i from 0 to (- (length l) 1)
do (setf return-value (cons (+(nth i l)(nth i r)) return-value))
)
(reverse return-value)
)
How could I create a simmilar function which would subtract the lists ?
If you are allowed to use the standard functions, then mapcar is your friend:
(mapcar #'+ '(1 2 3) (9 7 5))
==> (10 9 8)
Similarly for -.
Your function suffers from quadratic performance - you should not be using nth.
You should also bind return-value with let.
You should also use nreverse instead of reverse since you are constructing a fresh list anyway.
The more idiomatic way to write your function is
(defun addl (l r)
(loop for x in l and y in r collect (+ x y)))
Polynomial arithmetic
This seems like a follow up to your previous question, Decompose a list of numbers into digits,. There, you had a list of digits numbers, and they were the ai of a polynomial of the form
∑i=0… 10iai
where the n numbers in your list are the values of a0 to an-1, and everything after that is presumed to be zero. You were asking for a way to normalize the values such that each ai was in the range [0,9]. My answer to that question showed a few ways to do that.
Now, once you view numbers as a polynomial of this form, it's easy to see that you can simply piecewise add and subtract coefficients to the get the right, if not yet normalized, coefficients of the sum or difference. E.g.,
378 = 8 + 7×10 + 3×100&rightarrow; (8 7 3)
519 = 9 + 1×10 + 5×100&rightarrow; (9 1 5)
The sum is simply
(8+9) + (7+1)×10 + (3+5)×100 &rightarrow;(mapcar '+ x y) (17 8 8) &rightarrow;(number->digits (digits->number …)) (7 9 8)
The difference is simply
(8-9) + (7-1)×10 + (3-5)×100 &rightarrow;(mapcar '- x y) (-1 6 -2) &rightarrow;??? ???
What we don't have here is an appropriate normalization procedure. The one provided in the previous question doesn't work here. However, the list of digits is still correct, insofar as coefficients go, and the digits->number procedure produces the correct value of -141.
So, while you'll need to rethink what it means to show a list of digits for a negative number, you can do the correct type of addition and subtraction on your lists with the following, as long as both lists have the same length. If they don't have the same length, you'll need to pad the shorter one with zeros. A reimplementation of mapcar that supports this sort of operation might be useful here.
(defun sum (x y)
(mapcar '+ x y))
(defun difference (x y)
(mapcar '- x y))

Members in a list - LISP [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I need to write a program in Lisp to see the number of occurrences of a specific character in a list. For example the occurrences of 1 in the following list [1, 2, 3, 1,1]
A list in Lisp is a sequence of cons nodes: pairs of pointers - the first to the payload datum, and the second to the rest of the list. E.g. for [1,2,3,1,1],
.
/ \
1 .
/ \
2 .
/ \
3 ...... .
/ \
1 NIL
NIL is a special value signaling the empty list, such that the system knows not to try to explore it any further. In Scheme,
(define NIL '())
Recursive list processing paradigm is captured by the notion of fold, where each node . is "replaced" with a binary function f, and the special node NIL is replaced with some special "zero" value z, to create an application chain (f 1 (f 2 (f 3 (... (f 1 z) ...)))). In Scheme,
(define (myfold f z list)
(cond
((null? list) z) ; replace NIL with the initial ("zero") value
(else
(f ; combine
(car list) ; the payload datum, and the delayed,
(lambda () ; by creating a function to calculate it,
(myfold f z ; result of recursively folding
(cdr list))))))) ; the rest of list
That way, the combining function f must process two values: one is a node's payload datum, the other is the (delayed) result of recursively folding, with the same f and z, the rest of the list after that node.
(define (keep-equals v list)
(myfold
(lambda (a r) ; combine ...
(if (equal? v a)
(cons a ... ) ; the same thing goes over the dots, here
... )) ; and here
'() ; replace the NIL of the argument list with this
list))
Since the recursive folding results' calculation is delayed by creating a function to-be-called when the results are needed, we need to "force" that calculation to be performed, when we indeed need those results, by calling that function.
And if you want to count the number of occurrences instead of collecting them in a list, you just need to use a different combining function with a different initial ("zero") value.
In particular, we build a list by consing a value onto the rest of list (with NIL as the initial value, the empty list); whereas we count by incrementing a counter (with 0 as the initial value of that counter).
Calculating e.g. a list's length by folding, we essentially turn its elements each into 1: length [a,b,c,d,e] == 1 + (1 + (1 + (1 + (1 + 0)))). Here, the combining function will need to increment the counter conditionally, only when the payload data are such that we want to count them.
I like pretty well the answers already posted to this question. But it seems like they both involve a fair bit more than the necessary amount of work. On the other hand, given all the thought everyone's put into this, I'm almost embarrassed of how simple my answer is. Anyway, here's what I did:
(defun count-things-in (needle haystack)
"Count the number of NEEDLEs in HAYSTACK."
(reduce '+
(map 'list
#'(lambda (straw)
(if (equalp straw needle) 1 0))
haystack)))
(count-things-in 1 '(1 2 3 1 1))
;; => 3
It's pretty straightforward: you just map over HAYSTACK a function which returns 1 for an element which is EQUALP to NEEDLE or 0 for an element which isn't, and then reduce the resulting list by +. For the given example list, the map operation results in a list (1 0 0 1 1), which the reduce operation then treats as (1 + (0 + (0 + (1 + 1)))), which evaluates to 3.
Benefits of this approach include the use of an equality predicate loose enough to work with strings as well as numbers, and with numbers of different types but the same value -- that is, (equalp 1 1.0) => t; if you desire different behavior, use another equality predicate instead. Using the standard MAP and REDUCE functions, rather than implementing your own, also gives you the benefit of whatever optimizations your Lisp system may be able to apply.
Drawbacks include being not nearly as impressive as anyone else's implementation, and being probably not low-level enough to satisfy the requirements of the asker's homework problem -- not that that latter especially dismays me, given that this answer does satisfy the stated requirement.
I'm new to lisp myself but here is how I would do it. I haven't looked at the other answer yet from Will so I'll check that out after I post this. The member function has the utility of both telling you if it found something in a list, and also returning the rest of that list starting from where it found it:
CL-USER> (member '1 '(0 1 2 3))
(1 2 3)
You could then recursively call a function that uses member and increment a counter from returned values in a variable from a let:
(defun find1 (alist)
(let ((count 0))
(labels ((findit (list)
(let ((part (member '1 list)))
(if part
(progn (incf count)
(findit (rest part)))
0))
count))
(findit alist))))
Here is the result:
CL-USER> (find1 '(1 2 3 4 5))
1
CL-USER> (find1 '(1 1 2 3 4 5))
2
CL-USER> (find1 '(1 1 1 2 3 1 4 5 1 1))
6
You could get rid of that unattractive progn by using cond instead of if
UPDATE: Here is an updated and more elegant version of the above, based on the comments, that I think would qualify as tail recursive as well:
(defun find1 (alist &optional (accum 0))
(let ((part (member '1 alist)))
(if part
(find1 (rest part) (+ accum 1))
accum)))
Here it is in action:
CL-USER> (find1 '(1 2 3 4))
1
CL-USER> (find1 '(1 1 1 1))
4
CL-USER> (find1 '(1 1 0 1 1))
4
CL-USER> (find1 '(0 2 1 0 1 1 0 1 1))
5

Mapping multiple functions, in order, over a single list [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I would like to map three different functions, in order, over a single list. To demonstrate what I mean, say we want to do the following three mappings:
(map foo mylist)
(map bar mylist)
(map foobar mylist)
If we define mylist as '(1 2 3), and we run the above functions one at a time, we get:
(map foo mylist) ===> (foo1 foo2 foo3)
(map bar mylist) ===> (bar1 bar2 bar3)
(map foobar mylist) ===> (foobar1 foobar2 foobar3)
Instead, I would like the output to be in the following format:
===> ((foo1 bar1 foobar1) (foo2 bar2 foobar2) (foo3 bar3 foobar3))
How would you go about this?
You can nest two maps to achieve the desired effect:
(map (lambda (e)
(map (lambda (f) (f e))
myfuncs))
mylist)
In the above mylist is the input list and myfuncs is the list of functions. For example, these lists:
(define myfuncs (list sqrt square cube))
(define mylist '(1 2 3))
... Will produce this output:
'((1 1 1) (1.4142135623730951 4 8) (1.7320508075688772 9 27))