2015-03-09 4 views
1

Итак, я пытаюсь превратить список списка чисел в изображение, где каждый номер представляет собой блок с цветом, присвоенным этому номеру. Например:Включите список списков в изображение

(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) 
    )) 

Я хочу, чтобы превратить его в это: picture (paint-picture allig palette 10) где 10 это размер квадратов, составляющих изображение, палитра цвета присваивается каждому номеру (т.е. 1 " синий "на этом рисунке), а 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))) 
+0

В какой библиотеке вы это делаете? HTDP? Если да, то какой язык (BSL/ISL/ASL)? Или что-то вроде Pict? –

+0

Я использую (требуется 2htdp/image) в ISL – Ryan

+0

Является ли это ISL с lambdas или просто ISL? –

ответ

1

Прямая вперед версия без каких-либо функций высшего порядка или каких-либо наворотов на всех - очень начинающий уровне, я надеюсь:

Это наиболее распространенное в рекурсию на структур в нем указаны, а не их размере , поэтому мы это сделаем.
Это может показаться неудобным вначале, если вы привыкли писать for-loops, но большую часть времени точная длина списка не имеет значения в Racket - вам все равно, пусто или нет.

Во-первых, читаемость помощник:

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

Пройдя через ряд «картина» по строкам, мы должны либо пустой список, или мы не делаем.
Если он пуст, ничего не рисуйте.
В противном случае краска первую строку выше остальной части картины:

(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))))) 

И это все.

+0

Я действительно очень ценю прогулку! Спасибо! – Ryan

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)) 

(Обратите внимание, что я добавил Transparent к передней pal, так что я не должен смещаться индекс на 1.)

Он также работает для #lang htdp/isl+ (но по какой-то причине, он показывает структура вместо отображения изображения напрямую). Конечно, причина, по которой Алексис Кинг спрашивала, используете ли вы ISL + vs plain ISL, заключается в том, что выражения, которые я использовал выше, запрещены в простой 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)) 
+0

Хе-хе, у меня хакерская версия, которая работает в ISL без lambdas. Но это хороший ответ без каких-либо ограничений, ха-ха. –

+0

Я просто добавил версию, которая работает в простой ISL. :-) –

+0

Первоначально я тоже пробовал что-то подобное, но я думаю, что часть задания состоит в том, что палитру нужно передать «paint-image», что делает вещи раздражающими. –

1

Вот набор функций, которые реализуют то, что вы ищете в простом 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 функция, которая реализует частичное применение функции для двоичных функций (т.е. функций с арностью 2) в простом ISL. Я не уверен, что это предположительно для работы в ISL, но это так. Может быть, это ошибка, ха-ха?

+0

Мы еще не изучили масштабирование, матрицу или функцию, но я видел, что вы упомянули локальный в комментариях выше, был бы способ использовать это, чтобы обойти это. Мне просто нужно иметь возможность удалить следующий элемент для каждого элемента в списке списков. – Ryan

+0

@ Ryan Matrix ничего особенного, я просто использовал его для ссылки на список списков. Использование 'let' в основном стилистично - оно просто вводит новые привязки для использования внутри тела блока let. Наконец, «масштаб» просто масштабирует изображение, поэтому я не думаю, что это ужасно необоснованно использовать его. –

+0

@AlexisKing Я тоже обычно предпочитаю отвечать на вопросы с «профессиональными» реализациями. –

Смежные вопросы