Reputation: 107
I've been trying hard to do this and it's just frustrating that I can't actually do it. I'm even embarrassed of posting the code I wrote. I'm new to recursion so I need some help over here. What I'm trying to do is to define a function star like this:
> (star 5)
*
**
***
****
*****
It should print * and then ** in the next line and so on up to the number you put. A classic beginner exercise but much more difficult in Racket with recursion. Thank you.
Upvotes: 3
Views: 8981
Reputation: 235984
You didn't post your attempted solution, so I can only give you some hints, hoping that you reach the answer by your own; just fill-in the blanks ;).
It'll be easier if we split the problem in two parts. First, figure out how to create a string that's a repetition of another string n
times - let's write a helper procedure for this:
(define (repeat s n)
(cond ((zero? n) <???>) ; base case
(else
(string-append s
(repeat s <???>))))) ; advance recursion
Notice that we can also use make-string
for a simpler answer, as demonstrated in @ThrowawayAccount3Million's answer. Anyway, the result should look like this:
(repeat "*" 3)
=> "***"
Now we just have to call it in the right place from our star
procedure:
(define (star n)
(cond ((not (zero? n))
(star <???>) ; advance recursion
(displayln (repeat <???> <???>))))) ; call helper
And that's it!
(star 5)
=> *
**
***
****
*****
Upvotes: 2
Reputation: 2671
To iterate from 1 to 5 using nothing but recursion:
(let loop ((n 1))
(cond ((> n 5)
(void))
(else
(displayln ...)
(loop (+ 1 n)))))
The above is equivalent to defining a function called loop
and then calling it, like this:
(define (loop n)
(cond ((> n 5)
(void))
(else
(displayln ...)
(loop (+ 1 n)))))
(loop 1)
This can appear inside the body of another function:
(define (stars num-stars)
(define (loop ...
To print n stars:
(displayln (make-string n #\*))
Racket isn't raw Scheme, and it has a looping construct of its own, which you could also use:
(for ((n (in-range 1 6)))
(displayln ...))
There's also a library that implements the loop
construct from Common Lisp/Maclisp (which also has implementations for Chicken Scheme and EMACS Lisp):
(require (planet jphelps/loop)) ;; Download, install, and
;; use the library.
(loop for n from 1 to 5
do (displayln ...))
Upvotes: 2
Reputation: 31147
Here is one way to write a loop with a recursive function call:
(define (loop from to f done)
(if (< from to)
(begin
(f from)
(loop (+ from 1) to f done))
(done)))
If from
is smaller than to
then loop calls a function f
with the argument from
, and then calls loop
with from+1
. If from
is equal to to
the loop is done and the function done
is called.
Example:
> (loop 0 5 display newline)
01234
Let's define a helper that displays a single star:
(define (display-star _)
(display "*"))
We can now define display-stars
that displays n
stars and finishes by printing a newline.
(define (display-stars n)
(loop 0 n display-star newline))
The original problem can now be solved like this:
> (loop 1 6 display-stars void)
*
**
***
****
*****
The complete program:
#lang racket
(define (loop from to f done)
(if (< from to)
(begin
(f from)
(loop (+ from 1) to f done))
(done)))
(define (display-stars n)
(loop 0 n display-star newline))
(loop 1 6 display-stars void)
An alternative solution using the loop construct for
:
> (for ([i (in-range 1 6)])
(for ([j i])
(display "*"))
(newline))
*
**
***
****
*****
Upvotes: 1