I am trying to create a procedure that has a user input a non-empty string and then returns a random letter from the input in a substring of length one.
i.e.
(pick-at-random "word")
~"w"
(pick-at-random "word")
~"r"
So far I've got:
(define pick-at-random
(lambda (s)
(substring s (random(string-length s)) ())))
This gives me the position of the letter I want to display and I feel like where the () is, I should have some variable representing the start value of the substring and then add one to it. However, I don't know how to do this. Simply put, I am asking how I can limit the substring to length one while using the random function in the start value.
You may use let to bind the random number to a variable.
(define pick-at-random
(lambda (s)
(let ((index (random (string-length s))))
(substring s index (+ index 1)))))
Here's an alternative answer without using substring, in this way you don't need to save the index in a let binding. It's a more functional (and hence, idiomatic) solution to the problem:
(define (pick-at-random s) ; read the following lines from bottom to top
(string ; convert single character to string
(string-ref s ; access character in string, given an index
(random (string-length s))))) ; generate a random valid index in the string
(pick-at-random "word")
> "d" ; random result
The previous procedure generates a random valid index and then picks the character in that position within the string. As the last step, it turns back the single character into a string of length one.
The prior two answers are fine. Alternatively, you could break this problem into two problems:
Develop the function "nth-char" that accepts a word and an index, and returns a string containing the nth character of the word.
Develop the function "pick-at-random" that does what you describe. (Incidentally, I think a name such as "random-char" is somewhat better than "pick-at-random".)
This decomposition solves the problem you describe, by making it an argument to another function.
"Under the hood", this is the same solution as the one that uses "let".
Related
How does following code work? This code is from Racket documentation https://docs.racket-lang.org/plot/renderer2d.html?q=2d%20renderers#%28part.2.D.Line_.Renderers%29 (see function points on this page). This is not usual function definition statement. What does the underscore stand for here?
(define xs (build-list 5 (λ _ (random))))
The xs gets following value:
> xs
'(0.9520057193043618 0.1339193598495859 0.0019128879992944899 0.7511052254656998 0.4442323053722083)
A lambda can either have a list of identifiers as parameter names (such as (lambda (a b c) the-body )) or a single identifier (such as (lambda args the-body), which will then hold the list of all arguments.
The function given to build-list takes one parameter (the current index). It is customary to name parameters _ when you don't intend to use their value.
So since we don't care about the current index when creating a random list, the parameter is named _. This could also be written as (lambda (_), but since we don't care about any of the (one) parameters, we can just write (lambda _ as well.
I am looking for a way to output a character
a number of times using format. Is this possible? Can someone fill
in the _?_'s, so that the example works?
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
should return
=> "***"
It's nice to see so many solutions: ~A, ~<, and ~{ so far.
The ~#{ iteration construct provides a concise solution:
(format nil "~v#{~A~:*~}" 3 #\*)
(format nil "~a~:*~a~:*~a~:*" #\*)
"***"
Or elaborating a bit on Joshua Taylor's answer:
(format nil "~v{~a~:*~}" 3 '(#\*))
Would be one way of doing this. Don't be confused by the asterisks in the format directive, they are control characters, not characters being printed.
In terms of efficiency, however, this:
(make-string 3 :initial-element #\*)
would be a preferred way to achieve the same effect.
If you use the ~A directive, you can get this in exactly the form that you suggested, i.e.,
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
with three format arguments. However, if you use ~<, you can actually do this with just two format arguments. If you don't need this string inside of some other string that's already being generated by format, you could also just make the string using make-string.
Using Tilde A (~A)
You could print the character and specify a minimum width and the same character as the padding character. E.g., using ~v,,,vA and two arguments, you can ensure that some number of characters is printed, and what the padding character is.
CL-USER> (let ((n 3))
(format nil "~v,,,vA"
n ; number of characters that must be printed
#\* ; character to use as padding
#\*)) ; character to print with ~A
"***"
CL-USER> (let ((n 3))
(format nil "~v,,,vA" n #\* #\*))
"***"
CL-USER> (let ((n 10))
(format nil "~v,,,vA" n #\* #\*))
"**********"
This uses the full form of ~A:
~mincol,colinc,minpad,padcharA is the full form of ~A, which allows
control of the padding. The string is padded on the right (or on the
left if the # modifier is used) with at least minpad copies of
padchar; padding characters are then inserted colinc characters at a
time until the total width is at least mincol. The defaults are 0 for
mincol and minpad, 1 for colinc, and the space character for padchar.
as well as v:
In place of a prefix parameter to a directive, V (or v) can be used.
In this case, format takes an argument from args as a parameter to the
directive. The argument should be an integer or character. If the arg
used by a V parameter is nil, the effect is as if the parameter had
been omitted. # can be used in place of a prefix parameter; it
represents the number of args remaining to be processed. When used
within a recursive format, in the context of ~? or ~{, the # prefix
parameter represents the number of format arguments remaining within
the recursive call.
Using Tilde Less Than (~<)
There's also a less commonly used format directive, tilde less than, that's used for justification. it takes a format string and makes s
~mincol,colinc,minpad,padchar<str~>
This justifies the text produced by processing str within a field at
least mincol columns wide. str may be divided up into segments with
~;, in which case the spacing is evenly divided between the text
segments.
We can (ab)use this by passing an empty format string and just specifying the width and the padding character:
CL-USER> (let ((n 3))
(format nil "~v,,,v<~>"
n ; width
#\*)) ; padding character
"***"
CL-USER> (let ((n 5))
(format nil "~v,,,v<~>" n #\*))
"*****"
Just make a string
Of course, unless you need this special string inside of some other string that you're already formatting, you should do what wvxvw suggested, and just use make-string:
(make-string 3 :initial-element #\*)
Other alternatives
format is very flexible, and as this and other answers are pointing out, there are lots of ways to do this. I've tried to stick to ones that should do this in one pass and not do explicit iterations, but this can be done with format iterations, too, as Lars Brinkhoff and wvxvw have pointed out.
Like the answer of Lars, but we write the character wih ~C, instead of using the printer with ~A:
(format nil "~v#{~C~:*~}" 3 #\*)
Writing a character with something like write-char is a simpler operation than printing a Lisp object. The printer has a lot of context to observe and has to find the right way to print the object. OTOH, something like WRITE-CHAR just writes a single character to a stream.
I am looking for a way to output a character
a number of times using format. Is this possible? Can someone fill
in the _?_'s, so that the example works?
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
should return
=> "***"
It's nice to see so many solutions: ~A, ~<, and ~{ so far.
The ~#{ iteration construct provides a concise solution:
(format nil "~v#{~A~:*~}" 3 #\*)
(format nil "~a~:*~a~:*~a~:*" #\*)
"***"
Or elaborating a bit on Joshua Taylor's answer:
(format nil "~v{~a~:*~}" 3 '(#\*))
Would be one way of doing this. Don't be confused by the asterisks in the format directive, they are control characters, not characters being printed.
In terms of efficiency, however, this:
(make-string 3 :initial-element #\*)
would be a preferred way to achieve the same effect.
If you use the ~A directive, you can get this in exactly the form that you suggested, i.e.,
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
with three format arguments. However, if you use ~<, you can actually do this with just two format arguments. If you don't need this string inside of some other string that's already being generated by format, you could also just make the string using make-string.
Using Tilde A (~A)
You could print the character and specify a minimum width and the same character as the padding character. E.g., using ~v,,,vA and two arguments, you can ensure that some number of characters is printed, and what the padding character is.
CL-USER> (let ((n 3))
(format nil "~v,,,vA"
n ; number of characters that must be printed
#\* ; character to use as padding
#\*)) ; character to print with ~A
"***"
CL-USER> (let ((n 3))
(format nil "~v,,,vA" n #\* #\*))
"***"
CL-USER> (let ((n 10))
(format nil "~v,,,vA" n #\* #\*))
"**********"
This uses the full form of ~A:
~mincol,colinc,minpad,padcharA is the full form of ~A, which allows
control of the padding. The string is padded on the right (or on the
left if the # modifier is used) with at least minpad copies of
padchar; padding characters are then inserted colinc characters at a
time until the total width is at least mincol. The defaults are 0 for
mincol and minpad, 1 for colinc, and the space character for padchar.
as well as v:
In place of a prefix parameter to a directive, V (or v) can be used.
In this case, format takes an argument from args as a parameter to the
directive. The argument should be an integer or character. If the arg
used by a V parameter is nil, the effect is as if the parameter had
been omitted. # can be used in place of a prefix parameter; it
represents the number of args remaining to be processed. When used
within a recursive format, in the context of ~? or ~{, the # prefix
parameter represents the number of format arguments remaining within
the recursive call.
Using Tilde Less Than (~<)
There's also a less commonly used format directive, tilde less than, that's used for justification. it takes a format string and makes s
~mincol,colinc,minpad,padchar<str~>
This justifies the text produced by processing str within a field at
least mincol columns wide. str may be divided up into segments with
~;, in which case the spacing is evenly divided between the text
segments.
We can (ab)use this by passing an empty format string and just specifying the width and the padding character:
CL-USER> (let ((n 3))
(format nil "~v,,,v<~>"
n ; width
#\*)) ; padding character
"***"
CL-USER> (let ((n 5))
(format nil "~v,,,v<~>" n #\*))
"*****"
Just make a string
Of course, unless you need this special string inside of some other string that you're already formatting, you should do what wvxvw suggested, and just use make-string:
(make-string 3 :initial-element #\*)
Other alternatives
format is very flexible, and as this and other answers are pointing out, there are lots of ways to do this. I've tried to stick to ones that should do this in one pass and not do explicit iterations, but this can be done with format iterations, too, as Lars Brinkhoff and wvxvw have pointed out.
Like the answer of Lars, but we write the character wih ~C, instead of using the printer with ~A:
(format nil "~v#{~C~:*~}" 3 #\*)
Writing a character with something like write-char is a simpler operation than printing a Lisp object. The printer has a lot of context to observe and has to find the right way to print the object. OTOH, something like WRITE-CHAR just writes a single character to a stream.
How to create a function in Dr. Racket consumes a string str and produces true if str has at least a vowel and false if str has no vowels.
The vowels are the following set of characters: A, a, E, e, I, i, O, o, U, u.
For example:
(has-vowel? "whatever") => true
(has-vowel? "trythnks") => false
#ÓscarLópez
This is what I have come up with so far. THe function can whether the first letter is a vowel or not. My problem now is, how do I get the function to check the other letters?
I keep getting this error in Scheme (rest: expects a non-empty list; given "string")
I'm don't know exactly how to fix it. Any help/suggestions is most welcome. Thanks.
This looks like homework, so I'll give you some hints to get started. First, let's split the problem in two procedures - the first one will transform the string into a list of characters, and will also define the list of characters we're looking for. Fill-in the blanks:
(define (has-vowel? str)
(any-in-list ; helper procedure, we'll get to this later
(<???> str) ; how to transform a string into a list of chars?
'(#\A #\a <???>))) ; list of vowels
With the above procedure in place, we can write our helper procedure, any-in-list. It's a general solution for determining if any of the elements in one list is in the other - think about it as a predicate that tells if the intersection of two lists is non-empty:
(define (any-in-list lst check)
(cond (<???> <???>) ; if lst is empty, we didn't find any element, return #f
(<???> #t) ; return #t if the first element in lst is in check
(else (any-in-list <???> check)))) ; else advance the recursion over lst
The tricky part is in the second line of any-in-list. How do we determine if an element is in another list? we could write another helper procedure for this, but a quick look at the documentation will get you right on track. And don't forget to test your code, this should work as expected:
(has-vowel? "whatever")
=> #t
(has-vowel? "trythnks")
=> #f
One solution would be to:
convert the string to a list of characters (string->list)
Iterate over the list and check for vowel characters (characters)
I want it to extract all the words that have a letter e in them.
eg.
(ewords '(i e ee o oo)) -> '(e ee)
Berkeley's 61a lecture uses (first 'word) to extract the first character of the word. However DrScheme screams at me when I try to do that. How do take the first character of the word? like
(first 'word)->'w.
You'll need to convert it to a string explicitly:
(first (symbol->string 'word)) -> "w"
(I'm not sure off the top of my head whether first operates on strings. You can use string->list to convert to a list and then take the first if it doesn't.)
EDIT: It might be easier to pass around strings instead of symbols in the first place -- to designate a string, use double quotes (e.g. (ewords '("i" "e" "ee" "o" "oo")).) I don't know if this is your intent, but since you're learning, I thought I should mention the distinction.
Symbols are primarily meant to be atomic values, i.e., they are not usually taken apart and examined. If you really want to do it you must first do some type conversions:
; #\a -> a
(define (char->symbol chr)
(string->symbol (list->string (list chr))))
; abc -> (a b c)
(define (symbol->list sym)
(map char->symbol
(string->list (symbol->string sym))))
You can now use first:
> (first (symbol->list 'word))
w
It depends, what is the data definition for a "word"?
Is it a sequence of characters (aka a string)? Is it a list of characters? A list of strings? A list of symbols?
Here is a function that meets your criteria, but as you can see, it is convoluted and I wonder if it is what you really want:
; symbol->list-of-symbols : symbol -> (ListOf symbol)
; To destructure a symbol into a list of its constituent parts
(define (symbol->list-of-symbols sym)
(map (lambda (s) (string->symbol (string s)))
(string->list (symbol->string sym))))