Is there anything wrong in my racket language function? - functional-programming

I am giving the input as
(with-output-to-file "output"
(lambda ()
(print (append-longer-string "second" "first"))))
and my desired output is "firstsecond"
this is the logic I wrote in racket
(define (append-longer-string str1 str2)
(if (> (string-length str1) (string-length str2))
(string-append str1 str2)
(if (= (string-length str1) (string-length str2))
(string-append str1 str2)
(string-append str2 str1))))
but here I am getting Output as secondfirst only.
if anyone know the please help me. will be appreciated and thank you in advance.

Related

Simulating binary addition - DrRacket Intermediate Student with Lambda

As the title says, I'm a college student using DrRacket with Intermediate Student With Lambda language. My assignment is an algorithm that, given a string containing a binary number, displays as output the next number, operating only on the binary representation (thus, not converting to decimal, adding +1 and re-converting to binary). I've skipped the first three weeks of my course since I was abroad and now I'm trying to catch up and, as long I've understood, the professor's main goal now is to make us exercise on recursion (moreover, we are not allowed to use lists or cicles like the ones that are possible with do, only functions that are defined through lambda expressions).
I took several tries at the assignment and now my code looks like this:
; function called by the user
(define bin-succ
(lambda (bin) ; not-empty string of "0"s and "1"s
(let ( (k (- (string-length bin) 1)) (post (make-string 0)) )
(position bin k post)
)
)
)
; actual recursive function of the code: it searches from the least significant
; bit to the most significant bit if there is any "0" in the string
(define position
(lambda (bin k post)
(cond ( (= k -1)
(string-append "1" post) )
( (char=? (string-ref bin k) #\0)
(string-append (substring bin 0 k) "1" post) )
( (char=? (string-ref bin k) #\1)
((position bin (- k 1) post)
(string-append "0" post)) )
)
)
)
At the moment, the algorithm works with numbers which last digit is 0, such as 0, 10, 11010, etc..., but when I declare as input a number ending in 1, the program highlights the last part of the code, in particular
((position bin (- k 1) post)
(string-append "0" post))
and returns the error:
function call: expected a function after the open parenthesis, but received "11"
I've tried to use begin to make a list of expressions in a different function called by the third cond's case, that would re-call the function position, thus making the algorithm recursive again, but no luck since it says that begin isn't a defined function.
I may be overlooking something really easy (mostly due to the introductory classes I've skipped) or I may have taken this problem with an uncorrect mindset, but either way I'm stuck and I appreciate any helpful input.
Just a final question: also the use of else in the last cond case isn't accepted, can anyone explain me why? The fact that DrRacket uses multiple languages is puzzling me quite a lot since lots of documentation online isn't working with my current setup.
Maybe you've been looking at Racket documentation not ISL+ (Intermediate Student With Lambda) documentation so far? See https://docs.racket-lang.org/htdp-langs/intermediate-lam.html for the ISL+ documentation. Pressing f1 on a term from DrRacket takes you to documentation in the context of the language you're using.
((position bin (- k 1) post)
(string-append "0" post))
This is function application. You're trying to apply (as an argument): (string-append "0" post) to a function (position bin (- k 1) post). However, position returns a String.
You can simply pass over the new post to the recursive call. And you can use else in the last clause too. This is the working code:
; String -> String
(define (bin-succ bin)
(position bin (- (string-length bin) 1) ""))
; String Number String -> String
(define (position bin k post)
(cond [(= k -1)
(string-append "1" post)]
[(char=? (string-ref bin k) #\0)
(string-append (substring bin 0 k) "1" post)]
[else
(position bin (- k 1) (string-append "0" post))]))
A cleaner solution would be to not have a counter:
(define (bin-succ bin)
(cond [(string=? bin "1") "10"]
[(string=? (last bin) "0") (string-append (all-but-last bin) "1")]
[else (string-append (bin-succ (all-but-last bin)) "0")]))
(define (last str)
(substring str (sub1 (string-length str)) (string-length str)))
(define (all-but-last str)
(substring str 0 (sub1 (string-length str))))

Recursion in Drracket

I am asked to write a racket function repeat-str that consumes a string s with length of n, and produces a new list with length of n. If n is 0, the empty list is produced. If n is greater than 0, the first string in the list contains n copies of n and the second would be n-1 and so fourth.
Ex: (repeat-str "cat") => (list "catcatcat" "catcat" "cat")
what I have:
(define (repeat-str s)
(cond
[(zero? (string-length s)) empty]
[(equal? (string-length s) 1) s]
[else (make-list (string-length s) s)
(repeat-str (make-list (sub1 (string-length s)) s))]))
I am trying to recall the the function to get n-1 on the second list but I am unsure how to do the recursion part. This is so I can get 3 separate lists and then append them all at the end.
** cannot use:
- a placeholder function
- lambda
- replicate function
Using beginning student with list abbreviations
Thank you.
Here's one way:
(define (repeat-str str)
(define (sub cnt rep)
(if (zero? cnt)
null
(cons rep (sub (- cnt 1) (string-append rep str)))))
(reverse (sub (string-length str) str)))
One can also use for/list with available built-in functions:
(define (f s)
(reverse
(for/list ((i (string-length s)))
(apply string-append (make-list (add1 i) s)))))
Testing:
(f "cat")
Output:
'("catcatcat" "catcat" "cat")

Scheme Recursion Loop Incorrect Values and Variable Binding

I started a question here about a hangman game I am working on.
Recursive Scheme Function Value Error
I feel that the hangman portion is confusing people from my real issue and question. My problem is, I call various defined functions from within my recursion loop and get incorrect values. When I call these same function by themselves (not in a recursive loop) they work as expected. I know it is either something I am overlooking or a variable binding issue is going on that I need a workaround for.
First here a reproduction of the problem code:
(define (recurse a_list a_number)
(cond ((= a_number 0)
(display "Zero Condition.")
)
(else
(display "\n\n")
(display-list a_list ",")
(display "\n")
(display (car a_constant))
(display "\n")
(display "If the above letter is in the list, result should be true\n")
(display (contains? a_list (car a_constant)))
(display "\n")
(display "Enter a letter:")
(recurse (cons (symbol->string (read)) a_list) (- a_number 1))
)
)
)
Here are my definitions used inside the recursive loop:
(define (display-list a_list separater)
(if (null? a_list)
(display "")
(begin
(display (car a_list))
(if (null? (cdr a_list))
(display "")
(display separater))
(display-list (cdr a_list) separater)
)
)
)
(define (contains? list item)
;(display "\n")
;(display list)
;(display "\n")
;(display item)
;(display "\n")
(cond ((empty? list)
#f
)
((eq? (first list) item)
#t
)
(else
(contains? (rest list) item)
)
)
)
(define a_constant '("n" "o" "t" "w" "o" "r" "k" "i" "n" "g"))
(define test_li_1 '("n" "b"))
(define test_li_2 '("a" "b"))
This is what I ran:
> (contains? a_constant (car test_li_1))
#t
> (contains? a_constant (car test_li_2))
#f
It works as expected.
When I run the recursive Loop this is what I get:
> (recurse test_li_2 2)
a,b
n
If the above letter is in the list, result should be true
#f
Enter a letter:n
n,a,b
n
If the above letter is in the list, result should be true
#f
In my mind, the first output is correct, but the second one is not.
When I run with test_li_1 it always evaluates to true which, it should since 'n' is always in my a_list. What I have put together through several tests, is the recursive function keeps using my initially passed in list and does not use the appended version for function calls, which is not what I want it to do. I also think that is not how it should work right? Shouldn't my passed in value be used and not a value from several recursive levels up? I'm testing this all in Dr. Racket with #lang racket in case that matters.
The problem reported occurs because you're using eq? to test for string equality. From the documentation:
(eq? v1 v2) → boolean? : Return #t if v1 and v2 refer to the same object, #f otherwise.
So you see, eq? is testing for identity, not for equality. For that, you should use string=? or equal?. Modify the contains? procedure as follows, and it'll work:
(define (contains? list item)
(cond
((empty? list) #f)
((string=? (first list) item) #t)
(else (contains? (rest list) item))))
When you call (symbol->string (read)) and enter in a, you get a fresh string "a". This is a new string object that is not eq? to any "a" in your program. Try this to see the problem:
(eq? (symbol->string (read)) "a")
If you enter in a, this will output #f because the two string items are separate objects. You've run afoul of string interning. All instances of "a" written in your source code are stored as references to one object upon compilation, so (eq? "a" "a") will evaluate to true. When you (read) input as strings, those strings will be freshly created objects and won't be equal to any other strings. There are two ways you can fix this:
Use string=? for comparison instead of eq? (as in Oscar's answer)
Use lists of characters instead of lists of single-character strings, e.g. '(#\a #\b #\c) is the string "abc". From the Racket documentation of characters:
Two characters are eqv? if they correspond to the same scalar value. For each scalar value less than 256, character values that are eqv? are also eq?
Letter characters (a-z and A-Z) have values less than this in Racket's Unicode encoding, so any letter characters you read in will not run afoul of the eq? issue. This brings up another point - you should be sanitizing your input from read. The read procedure is not guaranteed to return a string, in particular if I enter in 1 instead of a string, it returns the number 1, not the string "1". You should add some logic to handle bad input, or this will crash your program.

Need a little help for this scheme "leet-speak"

I wrote a program below for "Define a procedure leet-speak takes a string and returns the result of changing all s's to fives, all e's to threes, all l's to ones, and all o's to zeros. Do not write any recursive code to do this. Simply make use of string->list, map, and list->string."
The error I got is:
~ (leet-speak "leet speak neat speak")
Exception: attempt to apply non-procedure (1 3 3 #\t #\space 5 ...)
Here is my definition for leet-speak:
(define leet-speak
(lambda (y)
(list->string
((map
(lambda (x)
(cond
[(eq? #\l x) 1]
[(eq? #\s x) 5]
[(eq? #\o x) 0]
[(eq? #\e x) 3]
[else x])
) (string->list y )))))
I really can't find out where the problem is.
You have too many parentheses around the map. Remove the extra so that there's only one parenthesis before map, and you should be good to go.
Your cond also needs to return the character corresponding to the number, not the number itself. Also, consider using a case instead of the cond you have.
All up, here's how it would look:
(define (leet-speak str)
(list->string
(map (lambda (x)
(case x
[(#\l) #\1]
[(#\s) #\5]
[(#\o) #\0]
[(#\e) #\3]
[else x]))
(string->list str))))

Scheme - do iterative - return value

I trying to write a function which gets an integer number , represented by string , and check if all his chars are digits and return #t \ #f accordingly . Thats the code -
(define (splitString str) (list->vector (string->list str)))
(define myVector 0)
(define flag #t)
(define (checkIfStringLegal str) (
(set! myVector (splitString str))
(do ( (i 0 (+ i 1)) ) ; init
((= i (vector-length myVector)) flag) ; stop condition
(cond ((>= 48 (char->integer (vector-ref myVector i)) ) (set! flag #f))
((<= 57 (char->integer (vector-ref myVector i)) )(set! flag #f))
)
)
)
)
Few explanations -
(list->vector (string->list str)) - convert string the char list .
(vector-ref myVector i) - char from the myVector at place i .
Its run OK , but when I try to use this func , like (checkIfStringLegal "444") I get -
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
#t
Try this:
(define (checkIfStringLegal str)
(andmap char-numeric?
(string->list str)))
This is how the procedure works:
It transforms the string into a list of characters, using string->list
It validates each character in the list to see if it's a number, applying the predicate char-numeric? to each one
If all the validations returned #t, andmap will return #t. If a single validation failed, andmap will return #f immediately
That's a functional-programming solution (and after all, this question is tagged as such), notice that your intended approach looks more like a solution in a C-like programming language - using vectors, explicit looping constructs (do), mutation operations (set!), global mutable definitions ... that's fine and it might eventually work after some tweaking, but it's not the idiomatic way to do things in Scheme, and it's not even remotely a functional-programming solution.
EDIT:
Oh heck, I give up. If you want to write the solution your way, this will work - you had a parenthesis problem, and please take good notice of the proper way to indent and close parenthesis in Scheme, it will make your code more readable for you and for others:
(define (splitString str) (list->vector (string->list str)))
(define myVector 0)
(define flag #t)
(define (checkIfStringLegal str)
(set! myVector (splitString str))
(do ((i 0 (+ i 1)))
((= i (vector-length myVector)) flag)
(cond ((>= 48 (char->integer (vector-ref myVector i)))
(set! flag #f))
((<= 57 (char->integer (vector-ref myVector i)))
(set! flag #f)))))
Even so, the code could be further improved, I'll leave that as an exercise for the reader:
Both conditions can be collapsed into a single condition, using an or
The exit condition should be: end the loop when the end of the vector is reached or the flag is false

Resources