[QUIZ] LCD Numbers (#14)

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.grayproductions.net/ruby_quiz/

3. Enjoy!

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

This week's quiz is to write a program that displays LCD style numbers at
adjustable sizes.

The digits to be displayed will be passed as an argument to the program. Size
should be controlled with the command-line option -s follow up by a positive
integer. The default value for -s is 2.

For example, if your program is called with:
lcd.rb 012345

The correct display is:

-- -- -- --
| | | | | | | |
| | | | | | | |
-- -- -- --
| | | | | | |
| | | | | | |
-- -- -- --

And for:
lcd.rb -s 1 6789

Your program should print:

- - - -
| | | | | |
- - -
| | | | | |
- - -

Note the single column of space between digits in both examples. For other
values of -s, simply lengthen the - and | bars.
 
J

James Edward Gray II

In Internet Explorer 6 but fine in Firefox 1.0

I'm unhappy with the current Ruby Quiz Web site and intend to replace
it as soon as I can find the time. Because of that, I'm not spending
too much time fiddling with the CSS myself, but I'll accept a working
patch if you're up to bug hunting.

I hope I don't sound uncaring. I'm not. I do want Ruby Quiz to have a
great site, but the current version has some built-in weaknesses I want
to get past, so I would rather spend my time replacing it.

I do thank you for the information.

James Edward Gray II
 
D

Douglas Livingstone

but I'll accept a working
patch if you're up to bug hunting.

Replace

<p class="example">

with

<pre class="example">

and update the corresponding </p>s to </pre>

The examples are prefromatted text, so mark them up that way and you
make life easier for yourself :) You'll probably want to remove the
"white-space: pre" bits too.

Douglas
 
J

James Edward Gray II

Replace

<p class="example">

with

<pre class="example">

and update the corresponding </p>s to </pre>

The examples are prefromatted text, so mark them up that way and you
make life easier for yourself :) You'll probably want to remove the
"white-space: pre" bits too.

This is a hold-over of the original site design when I didn't use
pre-formatted whitespace for the examples. (Yes, that was dumb.)

The change you purpose requires me to correct every quiz page. <br />s
will need to be translated to \ns as well.

Also, this change is incompatible with the Ruby code blocks, which are
probably suffering from the same problems. (I assume.)

I should have said "a working CSS patch", because if it's not that
simple it's a waste of time on a doomed site.

These, and other reasons, are why I'm planning a replacement.

James Edward Gray II
 
D

Douglas Livingstone

I should have said "a working CSS patch", because if it's not that
simple it's a waste of time on a doomed site.

True, you did say that.

As you have a doctype in there already, you could get off with putting this:

_white-space: pre;

After the following line:

white-space: pre-wrap; /* avoid overflow */

(The underscore at the start will make it apply only in IE, leaving
other browsers to display as they do already.)

Douglas
 
J

James Edward Gray II

True, you did say that.

As you have a doctype in there already, you could get off with putting
this:

_white-space: pre;

After the following line:

white-space: pre-wrap; /* avoid overflow */

(The underscore at the start will make it apply only in IE, leaving
other browsers to display as they do already.)

I dropped this in and saw no change in any of my browsers, just as you
said. I've updated the site with the change. Does this fix the
examples in IE 6?

Thanks for the tips.

James Edward Gray II
 
Z

Zach Dennis

This quiz got my attention. I can't wait until I get home from work and
can do this one...this one just looks so fun

=)

Zach
 
R

Robert McGovern

(The underscore at the start will make it apply only in IE, leaving
I dropped this in and saw no change in any of my browsers, just as you
said. I've updated the site with the change. Does this fix the
examples in IE 6?

It does indeed fix the problem for IE6, thanks Douglas for finding a
fix and James for putting it in place.

Rob
 
L

Luc Heinrich

Ruby Quiz said:
This week's quiz is to write a program that displays LCD style numbers at
adjustable sizes.

Here's my solution:

**************************** [begin code ] ****************************

#!/usr/local/bin/ruby -w

require 'getoptlong'

# ---------------------------------------------------------------------

class Digit

@@chars = [ " ", "-", "|" ]
@@segments =
[
[ [0,1,0], [2,0,2], [0,0,0], [2,0,2], [0,1,0] ], # 0
[ [0,0,0], [0,0,2], [0,0,0], [0,0,2], [0,0,0] ], # 1
[ [0,1,0], [0,0,2], [0,1,0], [2,0,0], [0,1,0] ], # 2
[ [0,1,0], [0,0,2], [0,1,0], [0,0,2], [0,1,0] ], # 3
[ [0,0,0], [2,0,2], [0,1,0], [0,0,2], [0,0,0] ], # 4
[ [0,1,0], [2,0,0], [0,1,0], [0,0,2], [0,1,0] ], # 5
[ [0,1,0], [2,0,0], [0,1,0], [2,0,2], [0,1,0] ], # 6
[ [0,1,0], [0,0,2], [0,0,0], [0,0,2], [0,0,0] ], # 7
[ [0,1,0], [2,0,2], [0,1,0], [2,0,2], [0,1,0] ], # 8
[ [0,1,0], [2,0,2], [0,1,0], [0,0,2], [0,1,0] ] # 9
]

attr_reader :height

def initialize( num, size )
@matrix = @@segments[ num ]
@height = @matrix.size
self.scale_to_size( size ) if size > 1
end

def scale_to_size( size )
t = size - 1
@matrix.each { |l| t.times { l.insert(-2, 0) } }
@matrix.each { |l| l.fill(1, l.index(1),size) if l.include?(1) }
t.times { @matrix.insert( 1, @matrix[1]) }
t.times { @matrix.insert(-2, @matrix[-2]) }
@height = @matrix.size
end

def display_line( line )
@matrix[ line ].each { |c| print @@chars[c] }
print " "
end

end

# ---------------------------------------------------------------------

class LCD

def initialize( num, size=1 )
@digits = Array.new
num.each_byte { |b| @digits << Digit.new( b.to_i - 48, size ) }
end

def display
for line in (e-mail address removed)
@digits.each { |d| d.display_line( line ) }
puts
end
end

end

# ---------------------------------------------------------------------

def print_usage( message=nil )
puts "Usage: lcd [-s size] digits"
end

# ---------------------------------------------------------------------

print_usage & exit if ARGV.empty?

size = 2
opts = GetoptLong.new( ["--size", "-s", GetoptLong::REQUIRED_ARGUMENT] )
opts.each { |opt, val| size = val.to_i if opt == "--size" }

print_usage & exit if ARGV.empty?

digits = ARGV[0].gsub( /[^0-9]/, "" )
lcd = LCD.new( digits, size )
lcd.display

# ---------------------------------------------------------------------

**************************** [end code ] ******************************
 
S

Sea&Gull

Hi!

Thanks for the quiz, it was really fun to code :)
Here is my variant:

#####################################################
#!/usr/bin/env ruby

def usage
print "\n\nUsage: lcd.rb [-s <size>] <digits>\n\n",
" -s digit size (positive integer), default is 2\n",
" digits digits to display as lcd\n\n\n"
exit 1
end

def draw_part_of_digit(d, s, state)
case state
when "top"
print " #{(d == 1 or d == 4) ? ' ' * s : '-' * s} "

when "up_half"
print "#{(d.between?(1, 3) or d == 7) ? ' ' : '|'}",
' ' * s,
"#{d.between?(5, 6) ? ' ' : '|'}"

when "middle"
print " #{(d.between?(0, 1) or d == 7) ? ' ' * s : '-' * s} "

when "down_half"
print "#{(d == 0 or d == 2 or d == 6 or d == 8) ? '|' : ' '}",
' ' * s,
"#{d == 2 ? ' ' : '|'}"

when "bottom"
print " #{(d == 1 or d == 4 or d == 7) ? ' ' * s : '-' * s} "

end # case
end

digits = []
size = 2

if ARGV.join(" ") =~ /^(-s ([1-9]\d*) ){0,1}(\d+)$/
size = $2.to_i if $2
$3.each_byte {|i| digits << i - 48}
else
usage
end

state = "top"

(3 + size * 2).times { |i|
case i
when 1 : state = "up_half"
when 1 + size : state = "middle"
when 2 + size : state = "down_half"
when 2 + size * 2 : state = "bottom"
end

digits.length.times { |j|
draw_part_of_digit(digits[j], size, state);
print ' '
}
print "\n"
}


#####################################################
 
S

Sea&Gull

Hi!

Maybe this is irrelevant, but
what if your script would be called such way:

lcd.rb -b accc 123

lcd.rb -s accc gfgdf 123

lcd.rb -s accc 123 gfgdf

lcd.rb - 2 123


?

:eek:)

--
s&g


Luc said:
This week's quiz is to write a program that displays LCD style numbers at
adjustable sizes.


Here's my solution:

**************************** [begin code ] ****************************

#!/usr/local/bin/ruby -w

require 'getoptlong'

# ---------------------------------------------------------------------

class Digit

@@chars = [ " ", "-", "|" ]
@@segments =
[
[ [0,1,0], [2,0,2], [0,0,0], [2,0,2], [0,1,0] ], # 0
[ [0,0,0], [0,0,2], [0,0,0], [0,0,2], [0,0,0] ], # 1
[ [0,1,0], [0,0,2], [0,1,0], [2,0,0], [0,1,0] ], # 2
[ [0,1,0], [0,0,2], [0,1,0], [0,0,2], [0,1,0] ], # 3
[ [0,0,0], [2,0,2], [0,1,0], [0,0,2], [0,0,0] ], # 4
[ [0,1,0], [2,0,0], [0,1,0], [0,0,2], [0,1,0] ], # 5
[ [0,1,0], [2,0,0], [0,1,0], [2,0,2], [0,1,0] ], # 6
[ [0,1,0], [0,0,2], [0,0,0], [0,0,2], [0,0,0] ], # 7
[ [0,1,0], [2,0,2], [0,1,0], [2,0,2], [0,1,0] ], # 8
[ [0,1,0], [2,0,2], [0,1,0], [0,0,2], [0,1,0] ] # 9
]

attr_reader :height

def initialize( num, size )
@matrix = @@segments[ num ]
@height = @matrix.size
self.scale_to_size( size ) if size > 1
end

def scale_to_size( size )
t = size - 1
@matrix.each { |l| t.times { l.insert(-2, 0) } }
@matrix.each { |l| l.fill(1, l.index(1),size) if l.include?(1) }
t.times { @matrix.insert( 1, @matrix[1]) }
t.times { @matrix.insert(-2, @matrix[-2]) }
@height = @matrix.size
end

def display_line( line )
@matrix[ line ].each { |c| print @@chars[c] }
print " "
end

end

# ---------------------------------------------------------------------

class LCD

def initialize( num, size=1 )
@digits = Array.new
num.each_byte { |b| @digits << Digit.new( b.to_i - 48, size ) }
end

def display
for line in (e-mail address removed)
@digits.each { |d| d.display_line( line ) }
puts
end
end

end

# ---------------------------------------------------------------------

def print_usage( message=nil )
puts "Usage: lcd [-s size] digits"
end

# ---------------------------------------------------------------------

print_usage & exit if ARGV.empty?

size = 2
opts = GetoptLong.new( ["--size", "-s", GetoptLong::REQUIRED_ARGUMENT] )
opts.each { |opt, val| size = val.to_i if opt == "--size" }

print_usage & exit if ARGV.empty?

digits = ARGV[0].gsub( /[^0-9]/, "" )
lcd = LCD.new( digits, size )
lcd.display

# ---------------------------------------------------------------------

**************************** [end code ] ******************************
 
L

Luc Heinrich

Luc Heinrich said:
Here's my solution:

Woops, found a bug: displaying the same digit multiple times wasn't
working, so doing 'lcd.rb 55' for example would render garbage.

Here's my fixed (and slightly updated) solution:

**************************** [begin code ] ****************************

#!/usr/local/bin/ruby -w

require 'getoptlong'

# ----------------------------------------------------------------------

class Array

def deep_clone
Marshal::load(Marshal.dump(self))
end

end

# ----------------------------------------------------------------------

class Digit

S = " "
H = "-"
V = "|"

@@segments =
[
[ [S,H,S], [V,S,V], [S,S,S], [V,S,V], [S,H,S] ], # 0
[ [S,S,S], [S,S,V], [S,S,S], [S,S,V], [S,S,S] ], # 1
[ [S,H,S], [S,S,V], [S,H,S], [V,S,S], [S,H,S] ], # 2
[ [S,H,S], [S,S,V], [S,H,S], [S,S,V], [S,H,S] ], # 3
[ [S,S,S], [V,S,V], [S,H,S], [S,S,V], [S,S,S] ], # 4
[ [S,H,S], [V,S,S], [S,H,S], [S,S,V], [S,H,S] ], # 5
[ [S,H,S], [V,S,S], [S,H,S], [V,S,V], [S,H,S] ], # 6
[ [S,H,S], [S,S,V], [S,S,S], [S,S,V], [S,S,S] ], # 7
[ [S,H,S], [V,S,V], [S,H,S], [V,S,V], [S,H,S] ], # 8
[ [S,H,S], [V,S,V], [S,H,S], [S,S,V], [S,H,S] ] # 9
]

attr_reader :height

def initialize( num, size )
@matrix = @@segments[ num ].deep_clone
@height = @matrix.size
self.scale_to_size( size ) if size > 1
end

def scale_to_size( size )
t = size - 1
@matrix.each { |l| t.times { l.insert(-2, S) } }
@matrix.each { |l| l.fill(H, l.index(H), size) if l.include?(H)
}
t.times { @matrix.insert( 1, @matrix[1]) }
t.times { @matrix.insert(-2, @matrix[-2]) }
@height = @matrix.size
end

def display_line( line )
print @matrix[ line ], " "
end

end

# ----------------------------------------------------------------------

class LCD

def initialize( num, size=1 )
@digits = Array.new
num.each_byte { |b| @digits << Digit.new( b.to_i - 48, size ) }
end

def display
for line in (e-mail address removed)
@digits.each { |d| d.display_line( line ) }
puts
end
end

end

# ----------------------------------------------------------------------

def print_usage( message=nil )
puts "Usage: lcd [-s size] digits"
end

# ----------------------------------------------------------------------

print_usage & exit if ARGV.empty?

size = 2
opts = GetoptLong.new( ["--size", "-s", GetoptLong::REQUIRED_ARGUMENT] )
opts.each { |opt, val| size = val.to_i if opt == "--size" }

print_usage & exit if ARGV.empty?

digits = ARGV[0].gsub( /[^0-9]/, "" )
lcd = LCD.new( digits, size )
lcd.display

# ----------------------------------------------------------------------

**************************** [end code ] ****************************
 
L

Luc Heinrich

Sea&Gull said:
Maybe this is irrelevant, but
what if your script would be called such way:
...

Right, your comment is of course valid, but I assumed that the purpose
of the quiz was to find smart and/or elegant ways to achieve the core
problem, not to come up with a 100% foolproof script :p
 
L

Lee Marlow

Here's a Ruby newbie attempt:

************************* lcd_quiz.rb *************************

zero = [[" ", "-", " "],
["|", " ", "|"],
[" ", " ", " "],
["|", " ", "|"],
[" ", "-", " "]]

one = [[" ", " ", " "],
[" ", " ", "|"],
[" ", " ", " "],
[" ", " ", "|"],
[" ", " ", " "]]

two = [[" ", "-", " "],
[" ", " ", "|"],
[" ", "-", " "],
["|", " ", " "],
[" ", "-", " "]]

three = [[" ", "-", " "],
[" ", " ", "|"],
[" ", "-", " "],
[" ", " ", "|"],
[" ", "-", " "]]

four = [[" ", " ", " "],
["|", " ", "|"],
[" ", "-", " "],
[" ", " ", "|"],
[" ", " ", " "]]

five = [[" ", "-", " "],
["|", " ", " "],
[" ", "-", " "],
[" ", " ", "|"],
[" ", "-", " "]]

six = [[" ", "-", " "],
["|", " ", " "],
[" ", "-", " "],
["|", " ", "|"],
[" ", "-", " "]]

seven = [[" ", "-", " "],
[" ", " ", "|"],
[" ", " ", " "],
[" ", " ", "|"],
[" ", " ", " "]]

eight = [[" ", "-", " "],
["|", " ", "|"],
[" ", "-", " "],
["|", " ", "|"],
[" ", "-", " "]]

nine = [[" ", "-", " "],
["|", " ", "|"],
[" ", "-", " "],
[" ", " ", "|"],
[" ", "-", " "]]

$numbers = [zero, one, two, three, four, five, six, seven, eight, nine]

def normalized_xy(x, y, size)
norm_x = case x % (size + 3)
when 0 then 0
when size + 1 then 2
else 1
end
norm_y = case y
when 0 then 0
when size * 2 + 2 then 4
when size + 1 then 2
when 1..(size+1) then 1
else 3
end
[norm_x, norm_y]
end

def stretch(numstring, size = 2)
nums = numstring.scan(/\d/).collect { |n| n.to_i }
single_len = (size + 3) # add a space between numbers
total_len = single_len * nums.length - 1
height = size*2 + 3
arr = Array.new(height) { |y|
Array.new(total_len) { |x|
norm_x, norm_y = normalized_xy(x, y, size)
index = (x/(single_len)).floor
num = nums[index]
((x+1) %(single_len) == 0) ? " " : $numbers[num][norm_y][norm_x]
}
}
arr.collect! { |line| line.join }
arr.join("\n")
end

if __FILE__ == $0
require 'optparse'
size = 2
ARGV.options do |opts|
opts.banner = "Usage: ruby #$0 [options] number_string"
opts.on("-s", "--size SIZE", Integer, "the size to print the LCD numbers.", " defaults to 2") do |s|
size = s.to_i
end
opts.on_tail("-h", "--help", "show this message") do
puts opts
exit
end
opts.parse!
if ARGV[0] !~ /^\d+$/
puts opts
exit
end
end

puts stretch(ARGV[0], size)
end

*********************** end lcd_quiz.rb ***********************

-Lee

-----Original Message-----
From: Ruby Quiz [mailto:[email protected]]
Sent: Friday, January 07, 2005 6:49 AM
To: ruby-talk ML
Subject: [QUIZ] LCD Numbers (#14)

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.grayproductions.net/ruby_quiz/

3. Enjoy!

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

This week's quiz is to write a program that displays LCD style numbers at adjustable sizes.

The digits to be displayed will be passed as an argument to the program. Size should be controlled with the command-line option -s
follow up by a positive integer. The default value for -s is 2.

For example, if your program is called with:
lcd.rb 012345

The correct display is:

-- -- -- --
| | | | | | | |
| | | | | | | |
-- -- -- --
| | | | | | |
| | | | | | |
-- -- -- --

And for:
lcd.rb -s 1 6789

Your program should print:

- - - -
| | | | | |
- - -
| | | | | |
- - -

Note the single column of space between digits in both examples. For other values of -s, simply lengthen the - and | bars.
 
S

Sea&Gull

Luc said:
Right, your comment is of course valid, but I assumed that the purpose
of the quiz was to find smart and/or elegant ways to achieve the core
problem, not to come up with a 100% foolproof script :p

Exactly:)

But personally I enjoy to find "smart and/or elegant" solutions
for even boring/tedious tasks (for instance, parsing of
command line arguments :) ).
"Smart and/or elegant" solution is usually smart and/or elegant
in _all_ its _details_, isn't it? ;-)

At least it should aim at it, IMHO :eek:)
 
J

Jannis Harder

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Here is my solution ( 398 bytes )
And my solution with hex digits ( 405 bytes)

Usage:
14-1.rb number* [-s size] number*
Right:
14-1.rb -s 9 456456
14-1.rb 456456 -s 9
14-1.rb 4 5 64 56 -s 9 45 6456
Wrong:
14-1.rb -s9 456456


### Dec
s=$*.index("-s");s=(s ?$*.slice!(s,2)[1].to_i: 2)
i=$*.join.split("").map{|x|x.to_i}
d,="7krtt1r30v/s".unpack("m")[0].unpack("B*")
f=" "
a,b=f*s,f+"-"*s+f
c,e,o="|",a+f+f,49
y=([0]*5).map{""}
i.each{|z|u=d[z*7,7]
y[0]<<(u[0]<o ?e: b)
y[1]<<(u[1]<o ?f: c)+a+(u[2]<o ?f: c)
y[2]<<(u[3]<o ?e: b)
y[3]<<(u[4]<o ?f: c)+a+(u[5]<o ?f: c)
y[4]<<(u[6]<o ?e: b)
y.map!{|v|v<<32}}
y[1,1]*=s
y[2+s,1]*=s
puts y
###

### Hex
s=$*.index("-s");s=(s ?$*.slice!(s,2)[1].to_i: 2)
i=$*.join.split("").map{|x|x.hex}
d,="7krtt1r30v/v8vyn9uw=".unpack("m")[0].unpack("B*")
f=" "
a,b=f*s,f+"-"*s+f
c,e,o="|",a+f+f,49
y=([0]*5).map{""}
i.each{|z|u=d[z*7,7]
y[0]<<(u[0]<o ?e: b)
y[1]<<(u[1]<o ?f: c)+a+(u[2]<o ?f: c)
y[2]<<(u[3]<o ?e: b)
y[3]<<(u[4]<o ?f: c)+a+(u[5]<o ?f: c)
y[4]<<(u[6]<o ?e: b)
y.map!{|v|v<<32}}
y[1,1]*=s
y[2+s,1]*=s
puts y
###

PS: it took me 7 minutes to write this mail because everytime I pasted
the source I found another way to do it in less bytes


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (Darwin)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFB4WPd5YRWfc27RzQRAmyXAJ9lEcHjbKdIGDLKZAorKDbp/W6u3QCgo2uC
zsgHcCAhm7jkLJpJultYnBI=
=Gk50
-----END PGP SIGNATURE-----
 
L

Luc Heinrich

Sea&Gull said:
But personally I enjoy to find "smart and/or elegant" solutions
for even boring/tedious tasks (for instance, parsing of
command line arguments :) ).
"Smart and/or elegant" solution is usually smart and/or elegant
in _all_ its _details_, isn't it? ;-)

Ok, you win, very good point. :)
 

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

No members online now.

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top