将列表的列表转换为图像
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)))))
就是这样。
好的,所以我正在尝试将数字列表转换为图像,其中每个数字代表一个块,该块具有分配给该数字的颜色。例如:
(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)))))
就是这样。