Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > [SOLUTION] Ruby Quiz #14 LCD Numbers

Reply
Thread Tools

[SOLUTION] Ruby Quiz #14 LCD Numbers

 
 
email55555 email55555
Guest
Posts: n/a
 
      01-09-2005
Here is my solution:

#!/usr/bin/env ruby
# Program : Ruby Quiz #14 LCD Numbers
(http://www.grayproductions.net/ruby_quiz/quiz14.html)
# Author : David Tran
# Date : 2005-01-07

class LCD
DEFAULT_SIZE = 2
LCD_CODES = [ # code for digits's each horizontal line (for size == 1)
[:h1, :v3, :h0, :v3, :h1], #0
[:h0, :v1, :h0, :v1, :h0], #1
[:h1, :v1, :h1, :v2, :h1], #2
[:h1, :v1, :h1, :v1, :h1], #3
[:h0, :v3, :h1, :v1, :h0], #4
[:h1, :v2, :h1, :v1, :h1], #5
[:h1, :v2, :h1, :v3, :h1], #6
[:h1, :v1, :h0, :v1, :h0], #7
[:h1, :v3, :h1, :v3, :h1], #8
[:h1, :v3, :h1, :v1, :h1], #9
]

def initialize(number, size)
@number = number.to_s.split(//).collect { |c| c.to_i }
@size = (size || DEFAULT_SIZE).to_i
@size = DEFAULT_SIZE if @size <= 0
@gap = ' ' # gap between each digit

line_codes = { # For size == 1
:h0 => ' ' + ' ' * @size + ' ', # h0 = " "
:h1 => ' ' + '-' * @size + ' ', # h1 = " - "
:v0 => ' ' + ' ' * @size + ' ', # v0 = " " (same as h0)
:v1 => ' ' + ' ' * @size + '|', # v1 = " |"
:v2 => '|' + ' ' * @size + ' ', # v2 = "| "
:v3 => '|' + ' ' * @size + '|', # v3 = "| |"
}

@lines = []
(0..4).each { |line| @lines << @number.inject('') { |s, d| s +=
line_codes[LCD_CODES[d][line]] + @gap } }
end

def each_line
return unless block_given?
last_line = (@size + 1) * 2
middle_line = last_line / 2
(0..last_line).each do |line|
index = case line
when 0: 0
when 1...middle_line: 1
when middle_line: 2
when last_line: 4
else 3
end
yield @lines[index]
end
end

end

key, size = ARGV.slice!(ARGV.index('-s'), 2) if ARGV.include?('-s')
raise "Usage: #$0 [-s size] number" if ARGV.empty?
LCD.new(ARGV.first, size).each_line { |line| puts line }


=========================
~~~ http://www.doublegifts.com ~~~


 
Reply With Quote
 
 
 
 
James Edward Gray II
Guest
Posts: n/a
 
      01-09-2005
My own solution. It looks a long but it's mostly the digits, arguments
and usage.

James Edward Gray II

#!/usr/bin/env ruby

DIGITS = [
[ " - ",
"| |",
" ",
"| |",
" - " ],
[ " ",
" |",
" ",
" |",
" " ],
[ " - ",
" |",
" - ",
"| ",
" - " ],
[ " - ",
" |",
" - ",
" |",
" - " ],
[ " ",
"| |",
" - ",
" |",
" " ],
[ " - ",
"| ",
" - ",
" |",
" - " ],
[ " - ",
"| ",
" - ",
"| |",
" - " ],
[ " - ",
" |",
" ",
" |",
" " ],
[ " - ",
"| |",
" - ",
"| |",
" - " ],
[ " - ",
"| |",
" - ",
" |",
" - " ]
]

def scale( num, size )
bigger = [ ]
num.each do |l|
row = l.dup
row[1, 1] = row[1, 1] * size
if row =~ /\|/
size.times { bigger << row }
else
bigger << row
end
end
bigger
end

s = 2
if ARGV.size >= 2 and ARGV[0] == '-s' and ARGV[1] =~ /^[1-9]\d*$/
ARGV.shift
s = ARGV.shift.to_i
end

unless ARGV.size == 1 and ARGV[0] =~ /^\d+$/
puts "Usage: #$0 [-s SIZE] DIGITS"
exit
end
n = ARGV.shift

num = [ ]
n.each_byte do |c|
num << [" "] * (s * 2 + 3) if num.size > 0
num << scale(DIGITS[c.chr.to_i], s)
end

num = ([""] * (s * 2 + 3)).zip(*num)
num.each { |l| puts l.join }

__END__



 
Reply With Quote
 
 
 
 
Jim Menard
Guest
Posts: n/a
 
      01-09-2005
Here's my solution: http://www.io.com/~jimm/rubyquiz/quiz14/

Jim
--
Jim Menard, http://www.velocityreviews.com/forums/(E-Mail Removed), http://www.io.com/~jimm/
"If at first you don't succeed, don't go skydiving." -- Unknown



 
Reply With Quote
 
Sean Ross
Guest
Posts: n/a
 
      01-09-2005
# lcd.rb
require 'optparse'

opts = OptionParser.new
size = 2 # default
opts.on("-s","--size VAL", Integer){|val| size=val}
digit_entry = opts.parse(*ARGV).first

raise "size must be greater than zero (given #{size})" if size <= 0
raise "'#{digit_entry}' contains non-digit characters" if digit_entry =~ /\D/

# to hold LCD format information
LCD = Struct.new(:upper_crossbar, :upper_uprights,
:middle_crossbar,:lower_uprights,:lower_crossbar)

# lcd segment formats
nothing = " #{' '*size} "
crossbar = " #{'-'*size} "
leftpost = "|#{' '*size} "
rightpost = " #{' '*size}|"
uprights = "|#{' '*size}|"

# digits in LCD format
LCDs = {'0'=>LCD[crossbar,uprights,nothing,uprights,crossbar],
'1'=>LCD[nothing,rightpost,nothing,rightpost,nothing],
'2'=>LCD[crossbar,rightpost,crossbar,leftpost,crossbar],
'3'=>LCD[crossbar,rightpost,crossbar,rightpost,crossbar],
'4'=>LCD[nothing,uprights,crossbar,rightpost,nothing],
'5'=>LCD[crossbar,leftpost,crossbar,rightpost,crossbar],
'6'=>LCD[crossbar,leftpost,crossbar,uprights,crossbar],
'7'=>LCD[crossbar,rightpost,nothing,rightpost,nothing],
'8'=>LCD[crossbar,uprights,crossbar,uprights,crossbar],
'9'=>LCD[crossbar,uprights,crossbar,rightpost,crossbar]}

# simulate LCD panel display
digits = digit_entry.split(//).collect{|d| LCDs[d]}
LCD.members.each_with_index do |segment_name, index|
panel_segment = digits.collect{|lcd| lcd[segment_name]}.join(' ')
repeat = index%2==0 ? 1 : size # only repeat 'upright' segments
repeat.times{puts panel_segment}
end


 
Reply With Quote
 
Sean Ross
Guest
Posts: n/a
 
      01-09-2005
"Sean Ross" <(E-Mail Removed)> wrote in message
news:8JiEd.3477$(E-Mail Removed).. .
[snip]
> # lcd segment formats
> nothing = " #{' '*size} "
> crossbar = " #{'-'*size} "
> leftpost = "|#{' '*size} "
> rightpost = " #{' '*size}|"
> uprights = "|#{' '*size}|"

[snip]

Needs a little refactoring:

gap = ' '*size
nothing = " #{gap} "
crossbar = " #{'-'*size} "
leftpost = "|#{gap} "
rightpost = " #{gap}|"
uprights = "|#{gap}|"



 
Reply With Quote
 
Dave Burt
Guest
Posts: n/a
 
      01-09-2005
You can see my solution at http://www.dave.burt.id.au/ruby/lcd_digits.rb

I used two functions, one to turn something like '9' into a big ASCII-art
digital-looking 9, and one like UNIX's paste command to stick them next to
each other.

Then like this:

number = ARGV[0].scan(/\d/)
puts paste(number.map {|digit| lcd_digit(digit, size) })

Cheers,
Dave


 
Reply With Quote
 
Florian Gross
Guest
Posts: n/a
 
      01-10-2005
Dave Burt wrote:

> You can see my solution at http://www.dave.burt.id.au/ruby/lcd_digits.rb
>
> I used two functions, one to turn something like '9' into a big ASCII-art
> digital-looking 9, and one like UNIX's paste command to stick them next to
> each other.


Your solution is very similar to mine. We both represented the number
faces via bit masks and decided to first render the individual digits
and then stick them next to each other.

I'm keeping the lines of a digit as an Array and sticking them together
with this code:

ary.transpose.map do |line|
line.join(" ")
end.join("\n")

Maybe that would also be an option for you.
 
Reply With Quote
 
Dale Martenson
Guest
Posts: n/a
 
      01-10-2005
require 'getoptlong'

class LCD
attr_accessor( :size, :spacing )

#
# This hash is used to define the segment display for the
# given digit. Each entry in the array is associated with
# the following states:
#
# HORIZONTAL
# VERTICAL
# HORIZONTAL
# VERTICAL
# HORIZONTAL
# DONE
#
# The HORIZONTAL state produces a single horizontal line. There
# are two types:
#
# 0 - skip, no line necessary, just space fill
# 1 - line required of given size
#
# The VERTICAL state produces a either a single right side line,
# a single left side line or a both lines.
#
# 0 - skip, no line necessary, just space fill
# 1 - single right side line
# 2 - single left side line
# 3 - both lines
#
# The DONE state terminates the state machine. This is not needed
# as part of the data array.
#
@@lcdDisplayData = {
"0" => [ 1, 3, 0, 3, 1 ],
"1" => [ 0, 1, 0, 1, 0 ],
"2" => [ 1, 1, 1, 2, 1 ],
"3" => [ 1, 1, 1, 1, 1 ],
"4" => [ 0, 3, 1, 1, 0 ],
"5" => [ 1, 2, 1, 1, 1 ],
"6" => [ 1, 2, 1, 3, 1 ],
"7" => [ 1, 1, 0, 1, 0 ],
"8" => [ 1, 3, 1, 3, 1 ],
"9" => [ 1, 3, 1, 1, 1 ]
}

@@lcdStates = [
"HORIZONTAL",
"VERTICAL",
"HORIZONTAL",
"VERTICAL",
"HORIZONTAL",
"DONE"
]

def initialize( size=1, spacing=1 )
@size = size
@spacing = spacing
end

def display( digits )
states = @@lcdStates.reverse
0.upto(@@lcdStates.length) do |i|
case states.pop
when "HORIZONTAL"
line = ""
digits.each_byte do |b|
line += horizontal_segment( @@lcdDisplayData[b.chr][i] )
end
print line + "\n"

when "VERTICAL"
1.upto(@size) do |j|
line = ""
digits.each_byte do |b|
line += vertical_segment(
@@lcdDisplayData[b.chr][i] )
end
print line + "\n"
end
when "DONE"
break
end
end
end

def horizontal_segment( type )
case type
when 1
return " " + ("-" * @size) + " " + (" " * @spacing)
else
return " " + (" " * @size) + " " + (" " * @spacing)
end
end

def vertical_segment( type )
case type
when 1
return " " + (" " * @size) + "|" + (" " * @spacing)
when 2
return "|" + (" " * @size) + " " + (" " * @spacing)
when 3
return "|" + (" " * @size) + "|" + (" " * @spacing)
else
return " " + (" " * @size) + " " + (" " * @spacing)
end
end
end

##### Main

opts = GetoptLong.new(
[ "--size", "-s", GetoptLong::REQUIRED_ARGUMENT ],
[ "--spacing", "--sp", "-p", GetoptLong::REQUIRED_ARGUMENT ]
)

lcd = LCD.new

opts.each do |opt, arg|
case opt
when "--size"
lcd.size = arg.to_i

when "--spacing"
lcd.spacing = arg.to_i
end
end

lcd.display( ARGV.shift )



 
Reply With Quote
 
Dave Burt
Guest
Posts: n/a
 
      01-10-2005
"Florian Gross" <(E-Mail Removed)> wrote:
> Dave Burt wrote:
>
>> You can see my solution at http://www.dave.burt.id.au/ruby/lcd_digits.rb
>>
>> I used two functions, one to turn something like '9' into a big ASCII-art
>> digital-looking 9, and one like UNIX's paste command to stick them next
>> to each other.

>
> Your solution is very similar to mine. We both represented the number
> faces via bit masks and decided to first render the individual digits and
> then stick them next to each other.
>
> I'm keeping the lines of a digit as an Array and sticking them together
> with this code:
>
> ary.transpose.map do |line|
> line.join(" ")
> end.join("\n")
>
> Maybe that would also be an option for you.


My newsreader missed your post
I was able to read it on ruby-talk.com via the Ruby Quiz site (which is
pretty cool for all its failings)

Sticking together like this?

def paste(array_of_strings, delim = ' ')
array_of_strings.map {|s| s.split(/\n/)}.transpose.map do |line|
line.join(delim)
end.join("\n")
end

Yes, that's neater than my paste(), and plugs right in. These strings all
have the same number of lines, so it doesn't matter that it fails if they
don't.

It's an interesting one. The process we used seemed to me to be the obvious
one, yet everyone's come up with a different way, stretching, golfing, etc.

I should also borrow your comments for my bitmask hash.

Cheers,
Dave


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[QUIZ] Gathering Ruby Quiz 2 Data (#189) Daniel Moore Ruby 10 01-31-2009 08:36 PM
[SOLUTION] Ruby Quiz #15 Animal Quiz David Tran Ruby 9 01-21-2005 02:11 AM
[QUIZ] LCD Numbers (#14) Ruby Quiz Ruby 26 01-14-2005 01:42 AM
[SOLUTION] Ruby Quiz #14 LCD Numbers ( solution #2 ) email55555 email55555 Ruby 16 01-10-2005 04:56 PM
[SOLUTION] Ruby Quiz #14 LCD Numbers Nathaniel Talbott Ruby 0 01-09-2005 09:03 PM



Advertisments