[QUIZ] Mexican Blanket (#127)

R

Ruby Quiz

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
on Ruby Talk follow the discussion. Please reply to the original quiz message,
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Scott Prager

I'm looking at this blanket my dad got in Mexico, and I'm noticing that it has
an interesting gradient. There are two colors (c1 and c2) and the outside c1 is
5 stitches wide, then a 1 stitch c2, 4 stitches c1, 2 stitches c2... It looks
something like this:

RRRRRBRRRRBBRRRBBBRRBBBBRBBB
RRRRBRRRRBBRRRBBBRRBBBBRBBBB
RRRBRRRRBBRRRBBBRRBBBBRBBBBB
RRBRRRRBBRRRBBBRRBBBBRBBBBBY
RBRRRRBBRRRBBBRRBBBBRBBBBBYB
BRRRRBBRRRBBBRRBBBBRBBBBBYBB
RRRRBBRRRBBBRRBBBBRBBBBBYBBB
RRRBBRRRBBBRRBBBBRBBBBBYBBBB
RRBBRRRBBBRRBBBBRBBBBBYBBBBY
RBBRRRBBBRRBBBBRBBBBBYBBBBYY
BBRRRBBBRRBBBBRBBBBBYBBBBYYB
BRRRBBBRRBBBBRBBBBBYBBBBYYBB
RRRBBBRRBBBBRBBBBBYBBBBYYBBB
RRBBBRRBBBBRBBBBBYBBBBYYBBBY
RBBBRRBBBBRBBBBBYBBBBYYBBBYY
BBBRRBBBBRBBBBBYBBBBYYBBBYYY
BBRRBBBBRBBBBBYBBBBYYBBBYYYB
BRRBBBBRBBBBBYBBBBYYBBBYYYBB
RRBBBBRBBBBBYBBBBYYBBBYYYBBY
RBBBBRBBBBBYBBBBYYBBBYYYBBYY
BBBBRBBBBBYBBBBYYBBBYYYBBYYY
BBBRBBBBBYBBBBYYBBBYYYBBYYYY
BBRBBBBBYBBBBYYBBBYYYBBYYYYB
BRBBBBBYBBBBYYBBBYYYBBYYYYBY
RBBBBBYBBBBYYBBBYYYBBYYYYBYY
BBBBBYBBBBYYBBBYYYBBYYYYBYYY
BBBBYBBBBYYBBBYYYBBYYYYBYYYY
BBBYBBBBYYBBBYYYBBYYYYBYYYYY

It goes on and on like that and when one color ends, another begins. When two
sets of gradients meet, there is a thick separator. Two gradients don't always
meet at the same color, but their opposite borders are usually the same. (ex:
black-to-yellow |separator| white-to-black) There is also the occasional
gradient of thick bars of equal length; ex: |green|-|yellow|-|red|. It looks
like this:

http://www1.istockphoto.com/file_thumbview_approve/2544046/2/

So the challenge is to make a pattern generator to generate the patterns as seen
in the ASCI and picture. It should, or rather NEEDS to, contain the Mexican flag
as it is respectful to the culture where this challenge comes from. For extra
credit, try to put them on a blanket of 200x100 pexels. And if you really need
extra credit to graduate, make the patterns symmetrical, however make the colors
in the patterns NOT symmetrical (ex: WWRW middle OBOO).
 
M

MenTaLguY

It should, or rather NEEDS to, contain the Mexican flag as it is respectful to
the culture where this challenge comes from.

By this, you mean the colors of the Mexican flag? The Mexican flag proper also includes a rather complex coat of arms in the center, which seems a little ambitious...

-mental
 
J

James Edward Gray II

By this, you mean the colors of the Mexican flag? The Mexican flag
proper also includes a rather complex coat of arms in the center,
which seems a little ambitious...

Yes. I'm pretty sure the author was referring to the colors.

James Edward Gray II
 
J

Joshua Ballanco

James said:
Yes. I'm pretty sure the author was referring to the colors.

James Edward Gray II

Oh, thank God! Now I might actually attempt this one... :-D
 
H

Harry Kakueki

So the challenge is to make a pattern generator to generate the patterns as seen
in the ASCI and picture.

# Here is my solution.
# I built a string to use for unpacking.
# Then I used the string to unpack.
# It should work for a blanket of any size if the
# 'colors' string is long enough.


# Code Start
colors = "GWRBYRGRRGRYBRWG"
unp = "aXaXaXaXaa"
(1...colors.length).each do
(1..4).each {|y| unp<<"X"<<"Xa"*(5-y)<<"a"<<"Xa"*y}
unp << "a"
end
row = colors.unpack(unp)
35.times do
puts row[0..69].join
row.shift
end


# Harry
 
H

Harry Kakueki

So the challenge is to make a pattern generator to generate the patterns as seen
in the ASCI and picture. It should, or rather NEEDS to, contain the Mexican flag

# My HTML version prints a blanket in color.
# It is quick and dirty HTML that could certainly
# be improved but it is viewable.
# This makes a 200x100 blanket.
# It looks like this http://www.kakueki.com/ruby/q127.html

# Code Start
outs = File.new("./q127.html","w")
colors = "GWRBYRGRRGRYBRWG"
ahash = {}
ahash.store("G","<font color=\"#00ff00\">"+"o" + "</font>")
ahash.store("W","<font color=\"#ffffff\">"+"o" + "</font>")
ahash.store("R","<font color=\"#ff0000\">"+"o" + "</font>")
ahash.store("B","<font color=\"#0000ff\">"+"o" + "</font>")
ahash.store("Y","<font color=\"#ffff00\">"+"o" + "</font>")

unp = "aXaXaXaXaa"
(1...colors.length).each do
(1..4).each {|y| unp<<"X"<<"Xa"*(5-y)<<"a"<<"Xa"*y}
unp << "a"
end
row = colors.unpack(unp)
row.map! {|x| ahash[x] }
outs.puts "<html><body bgcolor=\"#dddddd\">"

200.times do
outs.print row[0..99].join
outs.print "<br>\n"
row.shift
end

outs.puts "</body></html>"
outs.close


# Harry
 
A

Andreas Launila

Ruby said:
So the challenge is to make a pattern generator to generate the patterns as seen
in the ASCI and picture.

Idea: Each line constains a repeating pattern, and the lines themselves
are also repeating patterns. Therefore compute the supersequence of the
lines, then extract subsequences from that to retrieve the complete pattern.



INTERVAL_LENGTH = 5 # The interval at which the color-pattern changes.
LINE_LENGTH = 100
ROW_COUNT = 200

# Mexican flag.
colors = %w{G W R}

# Cycle the colors if we need more. The relationship between
# supersequence length l, interval_length w, and number of colors c is
# l = (1 + (c-1) * w) * w <=> c = ceil((l - w) / w^2) + 1
length_needed = ROW_COUNT + LINE_LENGTH - 1
colors_needed = ((length_needed - INTERVAL_LENGTH).to_f /
INTERVAL_LENGTH**2).ceil + 1
colors *= (colors_needed.to_f / colors.size).ceil

# Create a supersequence for the lines. Reverse the colors and slice
# from the end of the pattern to get the correct order.
color_pattern = colors.reverse.map{ |c| c * INTERVAL_LENGTH }.join
line_superseq = ''
INTERVAL_LENGTH.upto(color_pattern.size) do |i|
line_superseq << color_pattern.slice(-i, INTERVAL_LENGTH)
end

# Sample the line-sequence a few times to produce the complete pattern.
ROW_COUNT.times do |i|
puts line_superseq[i, LINE_LENGTH]
end


I didn't really understand what kind of symmetry was requested, but
replacing the colors with the following can be used to create the
pattern posted by Harry, the need for repetition of colors probably
means I misunderstod something though.


# Recreates the pattern posted by Harry.
colors = %w{G W R B Y R G R}
colors += colors.reverse
 
A

Andreas Launila

Andreas said:
# Cycle the colors if we need more. The relationship between
# supersequence length l, interval_length w, and number of colors c is
# l = (1 + (c-1) * w) * w <=> c = ceil((l - w) / w^2) + 1

And yes, that's wrong. There shouldn't be an equivalence there.
 
J

Jesse Merriman

--Boundary-00=_yDEbGBYN+9Py7Ho
Content-Type: Multipart/Mixed;
boundary="Boundary-00=_yDEbGBYN+9Py7Ho"

--Boundary-00=_yDEbGBYN+9Py7Ho
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Very cool! I'm always tickled when I see somebody using RMagick for
something besides just making thumbnails.

You're right, drawing each pixel would be slow. You could speed it up by
creating each row as an array of Pixels, then using import_pixels or
store_pixels to "draw" an entire row. Not only is doing things a row at
a time faster, these methods are much, much faster than Draw#draw, which
has to interpret the drawing primitives. Check the get_pixels.rb example
in the RMagick distribution.

Again, very cool!

Tim

Right you are Tim. Attached is my new blanket_image.rb improved in the way
you suggested (blanket_draw.rb can be discarded now). Quite a difference:

$ time ./mexican_blanket.orig.rb 800 800 --format png
Wrote blanket to blanket_800x800.png

real 0m28.706s
user 0m25.757s
sys 0m0.454s

$ time ./mexican_blanket.rb 800 800 --format png
Wrote blanket to blanket_800x800.png

real 0m7.687s
user 0m7.452s
sys 0m0.070s

(BTW, your message appears to have been sent to just me, not the list. Not
sure if this was intentional. If so, hope you don't mind me moving to the
list.)


--
Jesse Merriman
(e-mail address removed)
http://www.jessemerriman.com/

--Boundary-00=_yDEbGBYN+9Py7Ho
Content-Type: application/x-ruby;
name="blanket_image.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="blanket_image.rb"

# Ruby Quiz 127: Mexican Blanket
# blanket_image.rb

require 'blanket'
require 'RMagick'
include Magick

class BlanketImage < Magick::Image
# Colors from http://library.thinkquest.org/05aug/01280/Images/flag.jpg
# Not sure how accurate that is though..
StringToColor = { 'R' => '#fe0000', 'B' => '#0333a1', 'Y' => '#ffff49',
'O' => '#ea6520', 'G' => '#039e36', 'W' => '#ffffff' }

def initialize blanket
super blanket.width, blanket.height
draw_blanket blanket
self
end

def draw_blanket blanket
# Fill in the colors row-by-row (thanks Tim Hunter).
blanket.each_row_with_index do |row, y|
pixels = []
row.split(//).each do |color_char|
pixels << Pixel.from_color(StringToColor[color_char])
end
store_pixels 0, y, pixels.size, 1, pixels
end
end
end

--Boundary-00=_yDEbGBYN+9Py7Ho--
--Boundary-00=_yDEbGBYN+9Py7Ho--
 
C

CHubas

The three rules of Ruby Quiz:

Here is my solution. It's rather long, but provides enough flexibility
to
reuse the code, add more colors, etc.
Displays in Unix terminals and PPM Images

http://pastie.caboo.se/69309
It should, or rather NEEDS to, contain the Mexican flag
as it is respectful to the culture where this challenge comes from.

As a mexican, I shall say the don't need the Mexican Flag colors, as
their origin comes from prehispanic times, way before those colors
appeared as a national symbol. Nevertheless, they are often included
nowadays.

Thanks for the quizes.

Ruben Medellin.
 
S

Stephen Ball

I'm very much a newb, but I figure that the best way to learn Ruby
isn't sitting on the sidelines. So here's my solution (hacked, but it
works):

==== mexican_blanket.rb ====
class MexicanBlanket
def initialize(colors, length, max_width)
colors = colors
@length = length
max_width = max_width

@current_row = 0

# generate 'complete' line
@complete_pattern = generate_complete_pattern(colors,max_width)
end

def first_row
@complete_pattern[0...@length].to_s
end

def next_row
length = @length + @current_row
row = @complete_pattern[@current_row ... length]
@current_row += 1
row.to_s
end

def generate_complete_pattern(colors, max_width)
first_two = mix_two_colors(colors[0..1],max_width)
last_two = mix_two_colors(colors[1..2],max_width)
last_two.shift;
complete_pattern = first_two
complete_pattern << last_two
return complete_pattern.to_s.split(//)
end

def mix_two_colors(colors,max_width)
first_color = colors[0]
second_color = colors[1]
first_width = max_width
second_width = 1
two_colors = []
until (second_width > max_width)
two_colors << first_color * first_width << second_color * second_width
first_width -= 1
second_width += 1
end
return two_colors
end

attr_reader :complete_pattern # for testing
end
==== end mexican_blanket.rb ====

==== print_mexican_flag_blanket.rb ====
#!/usr/bin/env ruby -wKU

require "../lib/mexican_blanket"

colors = ["G","W","R"]
line_length = 28
color_max_width = 5
rows = 28

mexican_flag_blanket = MexicanBlanket.new(colors,line_length,color_max_width)

rows.times { |n| puts mexican_flag_blanket.next_row }
==== end print_mexican_flag_blanket.rb ====
 
I

Ivo Dancet

My solution..., I've spent an extra 10 minutes to put the code into a
class.

http://pastie.caboo.se/69806

#! /usr/bin/ruby
#
# usage: $> ruby quiz#127.rb <width> <rows> <color_width>
# without args it prints carpet of 100*200 with color_width 5.

class MexicanCarpet
COLORS = %w(W Y G W B)

def initialize(width, rows, color_width)
@width, @rows, @color_width = width, rows, color_width
total_width = @width * @rows

@color_stack = ""

# make one long line of colors
(COLORS.length-1).times do |i|
color1 = COLORS
color2 = COLORS[i+1]

color_width.times do |i|
@color_stack << color1 * (@color_width-i)
@color_stack << color2 * (i + 1) if i < @color_width - 1
end
end

while total_width > @color_stack.length do
@color_stack_ = @color_stack_ ? @color_stack_.reverse :
@color_stack[5..-1].reverse
@color_stack += (@color_stack[-2..-2] * @color_width) +
@color_stack_
end

@color_stack << COLORS.last * @color_width
print_carpet
end

def print_carpet
# print slices of the color_stack
@rows.times do |row|
puts @color_stack[row..row+@width]
end
end

end

width = ARGV[0] ? ARGV[0].to_i : 100
rows = ARGV[1] ? ARGV[1].to_i : 200
color_width = ARGV[2] ? ARGV[2].to_i : 5

MexicanCarpet.new( width, rows, color_width )
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,792
Messages
2,569,639
Members
45,351
Latest member
RoxiePulli

Latest Threads

Top