Scheme Function (DrRacket) - scheme

So, i'm trying to write the following function in scheme, and to be able to run it on DrRacket. The problem is as follows,
make5 - takes two integers, and returns a 5-digit integer constructed of the rightmost 3 digits of the first input, and the leftmost 2 digits of the second input. For example, (make5 561432 254) would return 43225.
Negative signs on either input number should be ignored - that is, (make5 561432 -254) would also return 43225.
If the first number has less than three digits or the last three digits start with zeros, and/or the second number has less two digits, your
function should return -2. Note: you may want to define some auxiliary functions.
So far this is the function I've been able to write.
(define (make5 x y)
(cond ((< (length x) 3) -2)
((< (length y) 2) -2)
(((modulo (abs(x)) 1000) 0) -2)
(((modulo (abs(y)) 1000) 0) -2)
(else (append (list-tail x 3) (cons (first(y)second(y)))))))
I'm getting the error...
application: not a procedure;
expected a procedure that can be applied to arguments
Any advice would be appreciated. I'm new to scheme and still trying to grasp everything.

Don't wrap your arguments in parentheses - (abs(x)) means "call the procedure x and pass the result to abs.
(cons (first(y)second(y)) means "cons these four things: the value of first; the result of calling the procedure y; the value of second; and the result of calling the procedure y".
(You've called procedures correctly in some places. Stick to the same pattern.)
You're also missing a comparison in a couple of conditions; (= (modulo (abs x) 1000) 0).
The inputs are not lists, they're integers, so you can't apply length, first, or any such things to them.
The result should be an integer, not a list, so you can't construct it using append and cons, you should only use arithmetic.
These facts about integers should get you started:
A number has fewer than five digits if it is smaller than 10000.
The last four digits of a non-negative number n is (modulo n 10000).
If x is 12 and y is 34, x * 100 + y is 1234.
To get the three leftmost digit in an integer, you can divide by 10 repeatedly until you have a number less than 1000.
Also note that the second number only has one condition on its digits while the first has two, and that the note about defining auxiliary functions was not left there as a challenge for you to do without them.
For instance, if you had the auxiliary functions
(left-digits n x), which produces the leftmost n digits of x, and
(right-digits n x), which produces the rightmost n digits of x
you could write (it's also probably not a coincidence that the description uses the words "if" and "or"):
(define (make5 x y)
(if (or ( ... ))
-2
(+ (* 100 (right-digits 3 x)) (left-digits 2 y))))
Since you want to ignore the sign of the numbers, it's convenient to take care of abs once at the start, using let:
(define (make5 signed-x signed-y)
(let ((x (abs signed-x))
(y (abs signed-y)))
(if (or ( ... ))
-2
(+ (* 100 (right-digits 3 x)) (left-digits 2 y)))))
"All" that's left now is filling in the conditions and writing the two digit-extracting functions.

Related

How to write functions of functions in Scheme

I am supposed to write a function called (nth-filtered f n), where f is a function of one variable and n is a natural number, which evaluates to the nth natural number such that f applied to that number is #t.
If we called
(nth-filtered even? 1) we would get 2
(nth-filtered prime? 10) we would get 29
How do I make it so that it works for any sequential function? What should I think about when approaching this type of problem?
A variable is a variable and + is also a variable. The main difference between a function and some other data type is that you can wrap a function name in parentheses with arguments and it will become a new value.
eg.
(define (double fun)
(lambda (value)
(fun (fun value))))
(define (add1 v)
(+ 1 v))
(define add2 (double add1))
(add2 1) ; ==> 3
Now the contract doesn't say so you deduct by looking that you do (fun ...) that fun needs to be a function. Imagine this:
(define test (double 5)) ; probably works OK
(test 1)
The last one fails since you get application: 5 is not a procedure or something similar. The error message is not standardized.
How to attack your task is by making a helper that has the same arguments as your function but in addition the current number that I guess starts at 1. As I demonstrated you use the function variable as a function and recurse by always increasing the number and reducing n when the f call was #t. The actual function will just use the helper by passing all the parameters in addition to your state variable.
Your problem requires a fold, which is the standard way to iterate other a list while keeping a record of things done so far.
Here a very rackety method using for/fold:
(define (nth-filtered predicate index)
(for/fold ([count 0]
[current #f] #:result current)
([n (in-naturals 1)]) ; we start at 1 but we could start at 0
#:break (= count index)
(values (if (predicate n) (add1 count) count)
n)))
for/fold takes a list of initial state. Here we define count as the number of times the given predicate returned #t and current as the currently tested value.
Then it takes a list of iterators, in this case we only iterate infinitely over (in-naturals).
To make it stop, we provide a #:break condition, which is "when the number of truthy predicates (count) is equal to the requested amount (index)".
for/fold requests that it's body finishes with a list of values for each "state" variable, in order to update them for the next iteration. Here we provide two values: one is the new count, the other is just the current n.
You can try it out, it works as you requested:
> (nth-filtered even? 1)
2
> (require math/number-theory)
> (nth-filtered prime? 10)
29
> (nth-filtered prime? 5)
11

Racket variable memory

Given this code:
(define (wrapper n)
(define (sum-ints)
(set! n (+ n 1))
(display n)(newline)
(if (= n 3)
n
(+ n (sum-ints))))
(sum-ints))
Calling this procedure with n = 0
(wrapper 0) =>
1
2
3
6
I had expected the process to increment n to a value of 3, and then as it returns, add 3 to 3 to 3 for an output of 3 3 3 9.
Does the inner procedure store a shadow copy of n?
Oog, mutation is nasty. The issue here is that "plus" is evaluated left-to-right. Specifically, let's consider the case when n=2. The expression (+ n (sum-ints)) is evaluated left-to-right. First, the identifier + evaluates to the plus function. Then, n evaluates to 2. Then, the recursive call is made, and the result is 3. Then, we add them together and the result is 5.
You'll see the same result in Java, or any other language that defines left-to-right evaluation of subexpressions.
Solution to this particular problem, IMHO: don't use mutation. It's needed in only
about 10% of the cases that people want to use it.

Scheme procedure with 2 arguments

Learned to code C, long ago; wanted to try something new and different with Scheme. I am trying to make a procedure that accepts two arguments and returns the greater of the two, e.g.
(define (larger x y)
(if (> x y)
x
(y)))
(larger 1 2)
or,
(define larger
(lambda (x y)
(if (> x y)
x (y))))
(larger 1 2)
I believe both of these are equivalent i.e. if x > y, return x; else, return y.
When I try either of these, I get errors e.g. 2 is not a function or error: cannot call: 2
I've spent a few hours reading over SICP and TSPL, but nothing is jumping out (perhaps I need to use a "list" and reference the two elements via car and cdr?)
Any help appreciated. If I am mis-posting, missed a previous answer to the same question, or am otherwise inappropriate, my apologies.
The reason is that, differently from C and many other languages, in Scheme and all Lisp languages parentheses are an important part of the syntax.
For instance they are used for function call: (f a b c) means apply (call) function f to arguments a, b, and c, while (f) means apply (call) function f (without arguments).
So in your code (y) means apply the number 2 (the current value of y), but 2 is not a function, but a number (as in the error message).
Simply change the code to:
(define (larger x y)
(if (> x y)
x
y))
(larger 1 2)

Racket - creating a water density function with certain restrictions

I am attempting to solve the following problem:
Lately, Finn has been very curious about buckets of ice water and their properties. He has been reviewing the density of water and ice. It turns out the density of water in both states depends on many factors, including the temperature, atmospheric pressure, and the purity of the water.
As an approximation, Finn has written the following function to determine the density of the water (or ice) in kg/m3 as a function of temperature t in Celsius (−273.15 ≤ t ≤ 100):
water-density(t) = ( 999.97 if t ≥ 0 ;
916.7 if t < 0 )
Write a function water-density that consumes an integer temperature t and produces either 999.97 or 916.7, depending on the value of t. However, you may only use the features of Racket given up to the end of Module 1.
You may use define and mathematical functions, but not cond, if, lists, recursion, Booleans, or other things we’ll get to later in the course. Specifically, you may use any of the functions in section 1.5 of this page: http://docs.racket-lang.org/htdp-langs/beginner.html except for the following functions, which are not allowed: sgn, floor, ceiling, round.
This is what I have so far:
(define (water-density t)
(+ (* (/ (min t 0) (min t -0.000001)) -83.27) 999.97))
This code does definitely work as long as the given temperature is not between -0.000001 and 0, but it will not work for temperatures between that range. What can I do to avoid this problem? Dividing by zero is the biggest problem I have here.
This is a somewhat.... interesting way of going about teaching programming, and I have a feeling this class is going to cause more StackOverflow questions to appear in the future, but you can do it by combining max and min to make a function that returns either 1 or 0 depending on whether its input is negative:
(define (negative->boolint n))
(- 0
(min 0
(max (inexact->exact (floor n))
-1))))
This function takes a number, rounds it down with (inexact->exact (floor n)), then the combination of max and min "bounds" the number to be between -1 and 0, then subtracts that result from 1. Since after conversion to an integer the number can never be between -1 and 0, the bounding just results in 0 for positives and zero and -1 negatives. The subtraction part means the function returns (- 0 0) for all positive numbers and zero and returns (- 1 -1) for all negative numbers. By combining the result of this function with some arithmetic, you can get the behavior you want:
(define (water-density t)
(- 999.97
(* 83.27
(negative->boolint t))))
If t is positive or zero, then the result of (* 83.27 (negative->boolint t)) will just be zero. Otherwise, the difference of the two densities will be subtracted, giving you the correct result.
This works because it's just taking advantage of max and min's built-in conditional functionality to do conditional arithmetic. You could probably achieve the same with some level of hackery for round or abs or other statements that have conditional logic.
EDIT
My apologies, I missed the part of your question about not being able to use the rounding functions. Want you want is still doable however, by using two base functions for simulating conditionals: abs and expt. Getting conditionals from abs is fairly straightforward, you can divide a number by its absolute value to get it's sign. The reason you need expt is because it lets you get around the division by zero issue with abs, because (expt 0 x) is 0 for all positive numbers, 1 for zero, and undefined for negative numbers. We can use this to make a zero->boolint function:
(define (zero->boolint x)
(expt 0 (abs x)))
With this, we can add its result to the numerator and denominator to get around division by zero in (/ x (abs x)). Since this causes the division by zero case to return 1, we now have a nonnegative->boolint function:
(define (nonnegative->boolint x)
(/ (+ 1
(/ (+ (zero->boolint x) x)
(+ (zero->boolint x) (abs x))))
2))
The inner division takes care of dividing a number by its absolute value to return -1 for negatives and 1 for positives and zero. The outer addition by 1 and then division by 2 turns this into 0 for negatives and 1 for positives and zero. In order to get a negative->boolint function, we just need some sort of not operation - which in the case of 1 for true and 0 for false is just subtracting the value from 1. So we can define negative->boolint based on only the conditional logic of abs and expt as:
(define (negative->boolint x)
(- 1 (nonnegative->boolint x))
This works as expected with the definition of water-density. Also, please don't ever do this in real world code. No matter how "clever" it may seem at the time.

How to count number of digits?

(CountDigits n) takes a positive integer n, and returns the number of digits it contains. e.g.,
(CountDigits 1) → 1
(CountDigits 10) → 2
(CountDigits 100) → 3
(CountDigits 1000) → 4
(CountDigits 65536) → 5
I think I'm supposed to use the remainder of the number and something else but other then that im really lost. what i tried first was dividing the number by 10 then seeing if the number was less then 1. if it was then it has 1 digit. if it doesnt then divide by 100 and so on and so forth. but im not really sure how to extend that to any number so i scrapped that idea
(define (num-digits number digit)
(if (= number digit 0)
1
Stumbled across this and had to provide the log-based answer:
(define (length n)
(+ 1 (floor (/ (log n) (log 10))))
)
Edit for clarity: This is an O(1) solution that doesn't use recursion. For example, given
(define (fact n)
(cond
[(= n 1) 1]
[else (* n (fact (- n 1)))]
)
)
(define (length n)
(+ 1 (floor (/ (log n) (log 10))))
)
Running (time (length (fact 10000))) produces
cpu time: 78 real time: 79 gc time: 47
35660.0
Indicating that 10000! produces an answer consisting of 35660 digits.
After some discussion in the comments, we figured out how to take a number n with x digits and to get a number with x-1 digits: divide by 10 (using integer division, i.e., we ignore the remainder). We can check whether a number only has one digit by checking whether it's less than 10. Now we just need a way to express the total number of digits in a number as a (recursive) function. There are two cases:
(base case) a number n less than 10 has 1 digit. So CountDigits(n) = 1.
(recursive case) a number n greater than 10 has CountDigits(n) = 1+CountDigits(n/10).
Now it's just a matter of coding this up. This sounds like homework, so I don't want to give everything away. You'll still need to figure out how to write the condition "n < 10" in Scheme, as well as "n/10" (just the quotient part), but the general structure is:
(define (CountDigits n) ; 1
(if [n is less than 10] ; 2
1 ; 3
(+ 1 (CountDigits [n divided by 10])))) ; 4
An explanation of those lines, one at a time:
(define (CountDigits n) begins the definition of a function called CountDigits that's called like (CountDigits n).
In Racket, if is used to evaluate one expression, called the test, or the condition, and then to evaluate and return the value of one of the two remaining expressions. (if test X Y) evaluates test, and if test produces true, then X is evaluated and the result is returned, but otherwise Y is evaluated and the result is returned.
1 is the value that you want to return when n is less than 10 (the base case above).
1+CountDigits(n/10) is the value that you want to return otherwise, and in Racket (and Scheme, and Lisp in general) it's written as (+ 1 (CountDigits [n divided by 10])).
It will be a good idea to familiarize with the style of the Racket documentation, so I will point you to the appropriate chapter: 3.2.2 Generic Numerics. The functions you'll need should be in there, and the documentation should provide enough examples for you to figure out how to write the missing bits.
I know this is old but for future reference to anyone who finds this personally I'd write it like this:
(define (count-digits n acc)
(if (< n 10)
(+ acc 1)
(count-digits (/ n 10) (+ acc 1))))
The difference being that this one is tail-recursive and will essentially be equivalent to an iterative function(and internally Racket's iterative forms actually exploit this fact.)
Using trace illustrates the difference:
(count-digits-taylor 5000000)
>(count-digits-taylor 5000000)
> (count-digits-taylor 500000)
> >(count-digits-taylor 50000)
> > (count-digits-taylor 5000)
> > >(count-digits-taylor 500)
> > > (count-digits-taylor 50)
> > > >(count-digits-taylor 5)
< < < <1
< < < 2
< < <3
< < 4
< <5
< 6
<7
7
(count-digits 5000000 0)
>(count-digits 5000000 0)
>(count-digits 500000 1)
>(count-digits 50000 2)
>(count-digits 5000 3)
>(count-digits 500 4)
>(count-digits 50 5)
>(count-digits 5 6)
<7
7
For this exercise this doesn't matter much, but it's a good style to learn. And of course since the original post asks for a function called CountDigits which only takes one argument (n) you'd just add:
(define (CountDigits n)
(count-digits n 0))

Resources