将列表的列表转换为图像

Turn list of list into image

好的,所以我正在尝试将数字列表转换为图像,其中每个数字代表一个块,该块具有分配给该数字的颜色。例如:

(define allig
  '((1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    (1 1 1 1 1 1 1 2 2 2 2 1 1 1 1 1 1 1 1)
    (1 1 1 1 1 1 2 4 5 5 5 2 1 1 1 2 2 1 1)
    (1 1 1 1 2 2 2 5 5 3 2 5 2 2 2 5 5 2 1)
    (1 1 2 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 2)
    (2 2 5 5 2 5 4 5 5 2 3 2 3 2 3 2 3 2 1)
    (5 5 5 5 5 5 5 5 2 1 2 1 2 1 2 1 2 1 1)
    (4 5 2 5 4 5 2 5 2 1 1 1 1 1 1 1 1 1 1)
    (5 5 5 5 5 5 5 5 2 1 1 1 1 1 1 1 1 1 1)
    (2 5 4 5 2 5 4 5 5 2 1 2 1 2 1 2 1 2 1)
    (5 5 5 5 5 5 5 5 5 5 2 3 2 3 2 3 2 3 2)
    (5 5 2 2 2 2 2 2 5 5 5 5 5 5 5 5 5 5 2)
    (5 5 2 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1)
    (5 5 5 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    (2 5 5 5 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    (1 2 5 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    (1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
    ))

我想把它变成这样: (paint-picture allig palette 10) 其中 10 是构成图像的正方形的大小,调色板是分配给每个数字的颜色(即 1 在这张图片中是 "blue"),allig 是数字列表的列表。

到目前为止,我有办法获取颜色,制作第一列,然后一遍又一遍地重复该列以使图片 Col x Row 变大。我的问题是我不知道如何获取每个连续的列,只有第一列。

我已经差不多完成了,我只是停留在最后一部分,所以任何帮助都会很棒。

这是我的:

    (define (make-column painting)
      (cond
        [(zero? (length painting)) (square 0 "solid" "red")]
        [else (above (square 30 "solid" 
    (get-color (first (first painting)) pal))
                     (make-column (rest painting)))]))


    ;puts images side by side to make a row
    (define (make-row n img1 img2)
      (cond
        [(zero? n ) (square 0 "solid" "red")]
        [else (beside img1 (make-row (sub1 n) img2 img1))]))


    ;makes a row of columns, I'm stuck as to how to make it recursive
    ; to get the next column since it is a list of a list
    (define (paint-picture painting)
      (cond
        [(zero? (length painting) ) (square 0 "solid" "red")]
        [else (make-row (length (first painting)) 
                        (make-column painting)
 ; this should be the recursive next col part  (paint-picture painting))]))

(define pal (list "blue" "dark gray" "white" "green" "dark green"))

(define (get-color n colors) (list-ref colors (- n 1)))

这适用于 #lang racket

(define pal '(Transparent Blue DarkGray White Green DarkGreen))

(apply above (map (lambda (row)
                    (apply beside (map (lambda (col)
                                         (square 4 'solid (list-ref pal col)))
                                       row)))
                  allig))

(请注意,我在 pal 前面添加了 Transparent,这样我就不必将索引移动 1。)

它也适用于 #lang htdp/isl+(但由于某些原因,它显示结构而不是直接显示图像)。当然,Alexis King 之所以问您使用的是 ISL+ 还是普通 ISL,是因为我在上面使用的 lambda 表达式在普通 ISL 中是被禁止的。

这是一个适用于普通 ISL 的版本:

(define pal '(Transparent Blue DarkGray White Green DarkGreen))

(define (make-pixel col)
  (square 4 'solid (list-ref pal col)))

(define (make-row row)
  (apply beside (map make-pixel row)))

(apply above (map make-row allig))

这是一组函数,可以在没有任何全局状态的普通 ISL 中实现您正在寻找的内容。

; (a b -> c) a -> (b -> c)
(define (partial f x)
  (let ([g (lambda (y) (f x y))])
    g))

; (listof string?) integer? -> image?
(define (pixel palette c)
  (let ([color (list-ref palette (sub1 c))])
    (square 1 "solid" color)))

; (listof string?) (listof integer?) -> image?
(define (row->image palette lst)
  (let* ([pixel/palette (partial pixel palette)]
         [pixels (map pixel/palette lst)])
    (apply beside pixels)))

; (listof string?) (listof (listof integer?)) -> image?
(define (matrix->image palette lst)
  (let* ([row/palette->image (partial row->image palette)]
         [rows (map row/palette->image lst)])
    (apply above rows)))

; (listof (listof integer?)) (listof string?) integer? -> image?
(define (paint-picture matrix palette size)
  (scale size (matrix->image palette matrix)))

棘手的一点是 partial 函数,它在普通 ISL 中实现了二进制函数(即具有 arity 2 的函数)的部分函数应用程序。我不确定这是否 应该 在 ISL 中工作,但确实如此。也许这是一个错误,哈哈?

一个简单的版本,没有任何高阶函数或任何花里胡哨的东西 - 非常初学者水平,我希望:

最常见的是递归列表的结构,而不是它们的大小,所以我们会这样做。
如果您习惯于编写 for 循环,一开始这看起来会很不舒服,但大多数时候列表的确切长度在 Racket 中是无关紧要的——您只关心它是否为空。

首先,一个可读性助手:

(define nothing (square 0 "solid" "red"))

逐行查看 "picture",我们要么有空列表,要么没有。
如果它是空的,什么也不画。
否则,在图片其余部分上方绘制第一行:

(define (paint-picture painting)
  (if (empty? painting)
      nothing
      (above (paint-row (first painting)) 
             (paint-picture (rest painting)))))

接下来,我们需要绘制一行。
这也有两种情况:
如果是空列表,什么也不画。
否则,绘制该行其余部分旁边的第一个像素:

(define (paint-row row)
  (if (empty? row)
      nothing
      (beside (square 30 "solid" (get-color (first row) pal)) 
              (paint-row (rest row)))))

就是这样。