# \[SOLUTION\] Mexican Blanket (#127)

**URL:** <https://www.ruby-forum.com/t/solution-mexican-blanket-127/106465>\
**Category:** Ruby\
**Created:** [June 10, 2007, 10:43pm UTC](https://www.ruby-forum.com/t/solution-mexican-blanket-127/106465 "2007-06-10T22:43:15Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Justin\_E](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/a88e57/32.png) [@Justin\_E](https://www.ruby-forum.com/u/Justin_E)\
**Post date:** [June 10, 2007, 10:43pm UTC](https://www.ruby-forum.com/t/solution-mexican-blanket-127/106465/1 "2007-06-10T22:43:15Z")

</div>

Hello,

Here is my solution to the quiz. Looking at the pattern for a moment,  
each  
line of the pattern is really just the previous line, shifted over one  
pixel. Thus to draw the pattern we can first calculate what all of the  
pixels will be. Then we simply iterate over this list, drawing one line  
at a  
time. With that in mind, here is the code I used to create the gradient:

def create\_gradient(colors, width=5)  
pattern = []

for i in 0…(width)  
(width-i).times { pattern.push(colors[0]) }  
(i+1).times { pattern.push(colors[1]) }  
end

for i in 0…(width)  
(i+1).times { pattern.push(colors[2]) }  
(width-i-1).times { pattern.push(colors[1]) }  
end

pattern  
end

And this function creates solid bands of color:

def create\_solid(colors, width)  
pattern = []  
for color in colors  
width.times { pattern.push(color) }  
end  
pattern  
end

To draw ASCII we simply print each line in turn.

def draw\_ascii(pattern, width)  
for i in 0…(pattern.size-width+1)  
puts pattern.slice(i, width).join  
end  
end

And to draw a JPEG we get a bit fancier, but its the same basic idea.  
There  
must be a better way to code this, because it takes much too long to  
run.  
But anyway, here it is:

require ‘RMagick’  
include Magick

def draw(filename, pattern, width, height)  
canvas = Magick::ImageList.new  
canvas.new\_image(width, height, Magick::HatchFill.new(‘white’,  
‘white’))  
pts = Magick::Draw.new

for y in 0… height  
line = pattern.slice(y, width)

```
x = 0
for color in line
  pts.fill(color)
  pts.point(x, y)
  x = x + 1
end

```

end

pts.draw(canvas)  
canvas.write(filename)  
end

Finally, we draw the ASCII from the Quiz and a picture similar to the  
one  
that was posted.

# 1) Draw the ASCII representation

draw\_ascii(create\_gradient([‘R’, ‘B’, ‘Y’]), 28)

# 2) Draw a picture of the blanket

mex\_flag = create\_solid([‘rgb(0, 64, 0)’, ‘white’, ‘red’], 5)  
border = create\_solid([‘rgb(0, 64, 0)’], 25)

pattern = create\_gradient([‘red’, ‘blue’, ‘yellow’])  
pattern = pattern + mex\_flag  
pattern = pattern + border  
pattern = pattern + create\_gradient([‘black’, ‘red’, ‘orange’])  
pattern = pattern + border  
pattern = pattern + mex\_flag.reverse  
pattern = pattern + create\_gradient([‘red’, ‘purple’, ‘black’], 8)  
draw(“mexican\_blanket.jpg”, pattern, 100, 200)

Here is a picture of the final blanket, if anyone is interested:

> **[Google Sites: Sign-in](https://accounts.google.com/v3/signin/identifier?continue=https%3A%2F%2Fsites.google.com%2Fsite%2Fsites%2Fsystem%2Ferrors%2FWebspaceNotFound%3Fpath%3D%2Fjustinethier%2Fmexican_blanket.jpg&followup=https%3A%2F%2Fsites.google.com%2Fsite%2Fsites%2Fsystem%2Ferrors%2FWebspaceNotFound%3Fpath%3D%2Fjustinethier%2Fmexican_blanket.jpg&ifkv=AeDOFXggwE7oukNFFH77o1ezZTzFuPune8OkMlRdXGft5U6S_7mWvKVwfgWrZm3TZr58AUtgGiRa&passive=1209600&service=jotspot&flowName=GlifWebSignIn&flowEntry=ServiceLogin&dsh=S-872271947%3A1690882384240459)**
>
> Access Google Sites with a personal Google account or Google Workspace account (for business use).

Any thoughts? The code could probably be more clever, but I tried to  
make  
everything as easy to follow as possible.  
Thanks,

Justin

---

<div class="post-metadata">

**Author:** ![Justin\_E](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/a88e57/32.png) [@Justin\_E](https://www.ruby-forum.com/u/Justin_E)\
**Post date:** [June 10, 2007, 10:55pm UTC](https://www.ruby-forum.com/t/solution-mexican-blanket-127/106465/2 "2007-06-10T22:55:16Z")

</div>

Justin E. wrote:

> And to draw a JPEG we get a bit fancier, but its the same basic idea.  
> There  
> must be a better way to code this, because it takes much too long to run.  
> Nice solution! Regarding the speed, see my earlier reply to Jesse  
> Merriman. Instead of drawing a pixel at a time, create an array of Pixel  
> objects and then use import\_pixels or store\_pixels to “draw” a row at a  
> time. For that matter, both of these methods can handle arbitrary  
> rectangles so you can create as many rows as you want and stow them in  
> the image all at once. You could build the whole image in memory if  
> that’s what you wanted.

---

<div class="post-metadata">

**Author:** ![Justin\_E](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/a88e57/32.png) [@Justin\_E](https://www.ruby-forum.com/u/Justin_E)\
**Post date:** [June 12, 2007, 12:35am UTC](https://www.ruby-forum.com/t/solution-mexican-blanket-127/106465/3 "2007-06-12T00:35:59Z")

</div>

On Sunday 10 June 2007 16:54, Tim H. wrote:

> For that matter, both of these methods can handle arbitrary rectangles so you can create as many rows as you want and stow them in the image all at once. You could build the whole image in memory if that's what you wanted.

Though that does give a speed boost, its not much. Here’s a mod of the  
last version of draw\_blanket I posted:

def draw\_blanket blanket  
pixels = []  
blanket.each\_row\_with\_index do |row, y|  
row.split(//).each do |color\_char|  
pixels \<\< Magick::Pixel.from\_color(StringToColor[color\_char])  
end  
end  
store\_pixels 0, 0, blanket.width, blanket.height, pixels  
end

For a 800x800 image, on my box, this shaves about 1/20 second off a  
total  
run time of about 7 seconds.
