user3786933
user3786933

Reputation: 107

Any idea of printing in Racket?

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

Answers (3)

Óscar López
Óscar López

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

Throw Away Account
Throw Away Account

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

soegaard
soegaard

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

Related Questions