Has anyone tried generating anagrams in scheme???
I have a list ( A B C D E F) and need to create anagrams of length 4. Like 'AAAA','ABCD','BCBC' etc.
I am totally confused. :(
Could someone please give me an heads-up on how I could go about it??
Hmm... Recently I solved very similar task - create anagrams of length N from (0 1). Here is my solution. May be it helps you:
;;
;; (define (generate n)) -> create list of string where
;; * length of each string is n
;; * each symbol of string is '0' or '1'
;; * the list has all possible combinations of symbols '0' and '1'
(define (generate n)
(generate-engine (list "0" "1") n))
(define (generate-engine lst n)
(cond
[(= n 1) lst]
[else (generate-engine (append (add-to-list lst "0") (add-to-list lst "1")) (- n 1))])
)
(define (add-to-list lst symbol)
(cond
[(empty? lst) empty]
[else (cons (add-to-element (first lst) symbol) (add-to-list (rest lst) symbol))]))
(define (add-to-element element symbol)
(string-append element symbol)
)
;; example
(generate 3)
Result:
(list "000" "100" "010" "110" "001" "101" "011" "111")
For each i = 0..x where x is the length of the anagram, generate a random number r such that 0 <= r <= n where n is the number of elements in the list of letters. Now use r as an index into the list of letters and concatenate it to the result.
Base case
Anagrams of length 1 are just the items in the list. Return the list.
Recursive case
Anagrams of length n are each of the items in the list appended to all of the anagrams of length (- n 1).
From that you ought to be able to cook up some example of the base case and recursive case. You'll probably need a helper function.
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.
Hi I am trying to implement a program in scheme shifting a list k times to the left.
For example:
(shift-k-left ’(1 2 3) 2)
’(3 1 2)
I have managed to implement a code that do shift left once here:
(define shift-left
(lambda (ls)
(if (null? ls)
'()
(append (cdr ls)
(cons (car ls)
'())))))
I want to use shift left as a function on shift-k-left.
Here is a solution using circular-list from srfi/1.
(require srfi/1)
(define (shift xs k)
(define n (length xs))
(take (drop (apply circular-list xs) k) n))
Using your shift-left to shift k times:
If k is 0: do nothing
If k is not 0: shift k-1 times, and then shift-left the result.
That is,
(define (shift-left-k ls k)
(if (= k 0)
ls
(shift-left (shift-left-k ls (- k 1)))))
You may want to adjust to do something sensible for negative k.
The idea is to count down n while consing the cars of r to p and the cdrs to r then the base case becomes append r to the reverse of p. If we run into a null? r we reverse p and continue this wraps the rotation:
(define (shift-k-left l n)
; assume that n >= 0
(let loop ((n n) (p '()) (r l))
(if (= n 0)
(append r (reverse p))
(if (null? r)
(loop n '() (reverse p))
(loop (- n 1) (cons (car r) p) (cdr r))))))
Here is something similar:
(define (addn value n)
(let loop ((value value) (n n))
(if (zero? n)
value
(loop (add1 value) (- n 1)))))
(addn 5 3)
; ==> 8
Now you could make an abstraction:
(define (repeat proc)
(lambda (v n)
...))
(define addn (repeat add1))
(addn 5 3)
; ==> 8
(define shift-k-left (repeat shift-left))
(shift-k-left ’(1 2 3) 2)
; ==> (3 1 2)
Needless to say repeat looks a lot like add1 does.
NB: The naming is off. Your implementation is more "rotate" than "shift".
shift-left is actually more like cdr than your implemenation.
Hello I have this function that makes randomly: a, b, c or d.
(define random-abcd
(let ([n (random 4)])
(cond [(equal? n 0) 'A]
[(equal? n 1) 'B]
[(equal? n 2) 'C]
[else 'D])))
That means I have 4 possible random outputs. But I would like to build a recusrsive function that gives an output between a number I give as parameter.
For example:
random-my 3 -> gives and output between: a b or c
random-my 5 -> gives and output between: a b c d or e
Thank you!
You could pass a number n and you can do (random n) to get a random number r in the range [0,n>. Now The char number for #\a is 97 so if you do (integer->char (+ 97 r)) you get #\a for 0, #\b for 1, ...
You can get a string with (list->string (list #\a)) ; ===> "a".
You can get a symbol with (string->symbol "a") ; ==> a
I leave it to you to put it all together, however it's not recursive.
Try:
(list-ref '(a b c d e f) (random 6))
fun problem. one way i can think of to do this is to use a vector (since it's zero-indexed and random-access) and given a number, choose a random number smaller than that value. once you have the number, then use that as the index into the vector to get the character in the vector at that index. in essence, you're just randomly indexing into 'slices' of the vector and slice size is determined by input argument.
Recursive fn to produce a random list of n letters till nth letter:
(define (f n (ol '()))
(if (= n (length ol))
ol
(f n (cons (string (integer->char (+ 97 (random n)))) ol))))
Testing:
(f 5)
Output:
'("b" "d" "b" "e" "e") ; list will have random letters;
So I have an example list of elements like this
(define A (list 'a 'c 'd 'e 'f 'e 'a))
Now I want to make a ranking from this sample
(define (scan lst)
(foldl (lambda (element a-hash) (hash-update a-hash element add1 0))
(hash)
lst))
The result should be like this:
> #(('a . 2) ('f . 1) ('e . 2) ....)
Because `scan function will make a hash table containing unique keys and the number of repetitions of that key (if it catches an unindexed key it will create a new place for that new key, counting from 0).
Then I'd like to sort that hash-table because it's unsorted:
(define (rank A)
(define ranking (scan A))
(sort ranking > #:key cdr)))
So the result would look like this:
#(('a . 2) ('e . 2) ('f . 1) ...)
Now I'd like to truncate the hash-table and throw away the bottom at the threshold of n = 1 (aka only take the elements with more than 2 repetitions).
(define (truncate lst n)
(define l (length lst))
(define how-many-to-take
(for/list
([i l]
#:when (> (cdr (list-ref lst i))
n))
i))
(take lst (length how-many-to-take)))
So the result might look like this:
(('a . 2) ('e . 2))
However, at the big scale, this procedure is not very efficient, it takes too long. Would you have any suggestion to improve the performance?
Thank you very much,
Part 2:
I have this data structure:
(automaton x
(vector (state y (vector a b c))
(state y (vector a b c)) ...))
Then i generate randomly a population of 1000 of them. Then i scan and rank them using the above functions. If i just scan them as is, it already takes long time. If i try to flatten them into a list like this
(list x y a b c y a b c...)
it'd take even more time. Here is the flatten function:
(define (flatten-au au)
(match-define (automaton x states) au)
(define l (vector-length states))
(define body
(for/list ([i (in-range l)])
(match-define (state y z) (vector-ref states i))
(list y (vector->list z))))
(flatten (list x body)))
The scan function will look a bit different:
(define (scan population)
(foldl (lambda (auto a-hash) (hash-update a-hash (flatten-automaton auto) add1 0))
(hash)
population))
Yep, I believe I see the problem. Your algorithm has O(n^2) ("n-squared") running time. This is because you're counting from one to the length of the list, then for each index, performing a list-ref, which takes time proportional to the size of the index.
This is super-easy to fix.
In fact, there's really no reason to sort it or convert it to a list if this is what you want; just filter the hash table directly. Like this...
#lang racket
(define A (build-list 1000000 (λ (idx) (random 50))))
(define (scan lst)
(foldl (lambda (element a-hash) (hash-update a-hash element add1 0))
(hash)
lst))
(define ht (scan A))
(define only-repeated
(time
(for/hash ([(k v) (in-hash ht)]
#:when (< 1 v))
(values k v))))
I added the call to time to see how long it takes. For a list of size one million, on my computer this takes a measured time of 1 millisecond.
Asymptotic complexity is important!
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.