David
David

Reputation: 113

Building a 2D List

Looking for a function that would do something akin to the following:

   (foo 3 2) => '( ( (1 1) (1 2) (1 3) )
                   ( (2 1) (2 2) (2 3) ) )

Would there be any built-in function in DrRacket that accomplishes that?

Upvotes: 1

Views: 2803

Answers (4)

Trace.Zhou
Trace.Zhou

Reputation: 1

(define (build-2d row col) (build-list row (lambda(x) (build-list col (lambda(y) (list (+ x 1) (+ y 1))))))

Upvotes: 0

Eli Barzilay
Eli Barzilay

Reputation: 29556

The main tool that you want to use to get such things in Racket is the various for loops. Assuming that you want to create a list-based matrix structure, then this is one way to get it:

#lang racket
(define (foo x y)
  (for/list ([i y])
    (for/list ([j x])
      (list (add1 i) (add1 j)))))

And since people raised the more general question of how to make foo create a matrix of any dimension, here's a generalized version that works with any number of arguments, and still returns the same result when called as (foo 3 2):

#lang racket
(define (foo . xs)
  (let loop ([xs (reverse xs)] [r '()])
    (if (null? xs)
      (reverse r)
      (for/list ([i (car xs)])
        (loop (cdr xs) (cons (add1 i) r))))))

(Note BTW that in both cases I went with a simple 0-based iteration, and used add1 to get the numbers you want. An alternative way would be to replace

(for/list ([i x]) ... (add1 i) ...)

with

(for/list ([i (in-range 1 (add1 x)]) ... i ...)

)

Upvotes: 6

Cam
Cam

Reputation: 15244

I can't answer your question as-is because I don't understand how the nested lists should work for >2 arguments. AFAIK there is no built-in function to do what you want.

To start you off, here is some code that generates output without nested lists. As an exercise try adjusting the code to do the nested listing. And see if there's a way you can make the code more efficient.

;;can take in any number of arguments
(define (permutations . nums)
  (foldl
   (lambda (current-num acc)
     (append-map
      (lambda (list-in-acc)
        (for/list ((i (build-list current-num (curry + 1))))
          (append list-in-acc (list i))))
      acc))
   (list (list))
   (reverse nums)))

Example 1:

> (permutations 3 2)
'((1 1) (1 2) (1 3) (2 1) (2 2) (2 3))

Example 2:

> (permutations 10)
'((1) (2) (3) (4) (5) (6) (7) (8) (9) (10))

Example 3:

> (permutations 2 3 4)
'((1 1 1)
  (1 1 2)
  (1 2 1)
  (1 2 2)
  (1 3 1)
  (1 3 2)
  (2 1 1)
  (2 1 2)
  (2 2 1)
  (2 2 2)
  (2 3 1)
  (2 3 2)
  (3 1 1)
  (3 1 2)
  (3 2 1)
  (3 2 2)
  (3 3 1)
  (3 3 2)
  (4 1 1)
  (4 1 2)
  (4 2 1)
  (4 2 2)
  (4 3 1)
  (4 3 2))

Upvotes: 0

Overflowed
Overflowed

Reputation: 96

Code:

(define (foo-makey const max data)
  (let* ((i (length data))
         (newy (- max i))
         (newpair (cons const newy)))
    (if (= max i)
        data
        (foo-makey const max
                   (cons newpair data)))))

(define (foo-makex xmax ymax data)
  (let* ((i (length data))
         (newx (- xmax i)))        
    (if (= xmax i)
        data
        (foo-makex xmax ymax
                   (cons (foo-makey newx ymax '()) data)))))

(define (foo x y)
  (foo-makex y x '()))

Output:

> (foo 3 2)
'(((1 . 1) (1 . 2) (1 . 3)) ((2 . 1) (2 . 2) (2 . 3)))

Upvotes: 0

Related Questions