[SOLUTION] Ruby Quiz #14 LCD Numbers

Discussion in 'Ruby' started by email55555 email55555, Jan 9, 2005.

  1. 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 ~~~
    email55555 email55555, Jan 9, 2005
    #1
    1. Advertising

  2. 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__
    James Edward Gray II, Jan 9, 2005
    #2
    1. Advertising

  3. email55555 email55555

    Jim Menard Guest

    Jim Menard, Jan 9, 2005
    #3
  4. email55555 email55555

    Sean Ross Guest

    # 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
    Sean Ross, Jan 9, 2005
    #4
  5. email55555 email55555

    Sean Ross Guest

    "Sean Ross" <> wrote in message
    news:8JiEd.3477$...
    [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}|"
    Sean Ross, Jan 9, 2005
    #5
  6. email55555 email55555

    Dave Burt Guest

    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
    Dave Burt, Jan 9, 2005
    #6
  7. 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.
    Florian Gross, Jan 10, 2005
    #7
  8. 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] )
    end
    print line + "\n"

    when "VERTICAL"
    1.upto(@size) do |j|
    line = ""
    digits.each_byte do |b|
    line += vertical_segment(
    @@lcdDisplayData[b.chr] )
    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 )
    Dale Martenson, Jan 10, 2005
    #8
  9. email55555 email55555

    Dave Burt Guest

    "Florian Gross" <> 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
    Dave Burt, Jan 10, 2005
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ruby Quiz

    [QUIZ] LCD Numbers (#14)

    Ruby Quiz, Jan 7, 2005, in forum: Ruby
    Replies:
    26
    Views:
    236
    Zach Dennis
    Jan 14, 2005
  2. email55555 email55555

    [SOLUTION] Ruby Quiz #14 LCD Numbers ( solution #2 )

    email55555 email55555, Jan 9, 2005, in forum: Ruby
    Replies:
    16
    Views:
    268
    David Tran
    Jan 10, 2005
  3. Nathaniel Talbott

    [SOLUTION] Ruby Quiz #14 LCD Numbers

    Nathaniel Talbott, Jan 9, 2005, in forum: Ruby
    Replies:
    0
    Views:
    81
    Nathaniel Talbott
    Jan 9, 2005
  4. Vance A Heron

    [SOLUTION] LCD Numbers (#14)

    Vance A Heron, Jan 10, 2005, in forum: Ruby
    Replies:
    0
    Views:
    96
    Vance A Heron
    Jan 10, 2005
  5. David Tran
    Replies:
    9
    Views:
    173
    David Tran
    Jan 21, 2005
Loading...

Share This Page