2010年9月15日星期三

ruby quiz - LCD numbers and solutions

 

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

answer

# point.rb
 require 'test/unit'

 class Point

 attr_reader :row, :column
   def initialize(row, column)
     if !row.is_a?(Integer) or !column.is_a?(Integer)
       raise "row #{row} and column #{column} must be integer"
     end
     if row < 0 or column < 0
       raise "row #{row} and column #{column} must be >= 0"
     end
     @row = row
     @column = column
   end

 end

 class TC_PointTest < Test::Unit::TestCase
   @@valid_points = [[1, 2], [0, 0]]
   @@invalid_points = [[nil, 3], [3, nil], [1, -2], [-1, 2], [1.5, 2], [35, 5.66778]]

   def test_valid_point
     @@valid_points.each do |point|
       p = Point.new(point[0], point[1])
       assert(p.row == point[0])
       assert(p.column == point[1])
     end
   end
  
   def test_invalid_point
     @@invalid_points.each do |point|
       assert_raise RuntimeError do
         p = Point.new(point[0], point[1])
       end
     end
   end
  
 end

# stick.rb
 require 'test/unit'
 require 'point'

 class Stick
   attr_reader :starting_point, :size

 def initialize(starting_point, size)
     @starting_point = starting_point
     if size.is_a?(Integer) and size > 0
       @size = size
     else
       raise "size #{size} must be integer and > 0"
     end
   end

 def paint_in_picture(picture)
     raise "this method need to be overloaded"
   end

 end


 class HorizontalStick < Stick
   HORIZONTAL = "-"

 def paint_in_picture(picture)
     (1..@size).each do |i|
       picture[@starting_point.row][@starting_point.column+i] = HORIZONTAL
     end
   end

 end


 class VerticalStick < Stick
   VERTICAL = "|"

 def paint_in_picture(picture)
     (1..@size).each do |i|
       picture[@starting_point.row+i][@starting_point.column] = VERTICAL
     end
   end

 end

 class StickTest < Test::Unit::TestCase
   def test_stick_init
     s = Stick.new(Point.new(0,0), 3)
     assert(s.size==3)
     assert(s.starting_point.row == 0)
     assert(s.starting_point.column == 0)

     picture = [[0,0,0],[1,1,1],[2,2,2]]
     assert_raise RuntimeError do
       s.paint_in_picture(picture)
     end
   end
 end

 class HorizontalStickTest < Test::Unit::TestCase
   def test_paint_in_picture
     hs = HorizontalStick.new(Point.new(0,0), 2)
     picture = [[0,0,0],[1,1,1],[2,2,2]]
     hs.paint_in_picture(picture)
     assert(picture[0][1]=="-")
     assert(picture[0][0]==0)
     assert(picture[0][2]=="-")
   end
 end

 class VerticalStickTest < Test::Unit::TestCase
   def test_paint_in_picture
     vs = VerticalStick.new(Point.new(0,0), 2)
     picture = [[0,0,0],[1,1,1],[2,2,2]]
     vs.paint_in_picture(picture)
     assert(picture[0][0]==0)
     assert(picture[1][0]=="|")
     assert(picture[2][0]=="|")
   end
 end

# numberpicture.rb
 require 'pp'
 require 'point'
 require 'stick'

 class NumberPicture
   EMPTY = " "
   attr_reader :width, :heighth, :size
   attr_accessor :picture
  
   def initialize(number, size)
     @number = number
     @size = size
     @width = @size + 2
     @heighth = @size*2 + 3
     init_picture
     init_points
     init_sticks
     end
  
   def init_picture()
     @picture = Array.new()
     (0..@heighth-1).each do |i|
       @picture[i] = Array.new(@width-1, 0)
       (0..@width-1).each do |j|
         @picture[i][j] = EMPTY
       end
     end
   end
  
   def init_points()
     @top_left = Point.new(0, 0)
     @top_right = Point.new(0, @width-1)
     @middle_left = Point.new(@size+1, 0)
     @middle_right = Point.new(@size+1, @width-1)
     @bottom_left = Point.new(@heighth-1, 0)
   end
  
   def init_sticks()
     @top_stick = HorizontalStick.new(@top_left, @size)
     @middle_stick = HorizontalStick.new(@middle_left, @size)
     @bottom_stick = HorizontalStick.new(@bottom_left, @size)
     @upper_left_stick = VerticalStick.new(@top_left, @size)
     @upper_right_stick = VerticalStick.new(@top_right, @size)
     @lower_left_stick = VerticalStick.new(@middle_left, @size)
     @lower_right_stick = VerticalStick.new(@middle_right, @size)
   end
  
   def paint_sticks()
     if [0,2,3,5,6,7,8,9].include? @number
       @top_stick.paint_in_picture(@picture)
     end
     if [2,3,4,5,6,8,9].include? @number
       @middle_stick.paint_in_picture(@picture)
     end
     if [0,2,3,5,6,8,9].include? @number
       @bottom_stick.paint_in_picture(@picture)
     end
     if [0,4,5,6,8,9].include? @number
       @upper_left_stick.paint_in_picture(@picture)
     end
     if [1,2,3,4,7,8,9,0].include? @number
       @upper_right_stick.paint_in_picture(@picture)
     end
     if [2,6,8,0].include? @number
       @lower_left_stick.paint_in_picture(@picture)
     end
     if [1,3,4,5,6,7,8,9,0].include? @number
       @lower_right_stick.paint_in_picture @picture
     end
   end
  
 end


 numbers="123455"
 size=2

 pictures=Array.new()
 for i in (0..numbers.length-1)
   pictures[i] = NumberPicture.new(numbers[i]-48,size)
   pictures[i].paint_sticks()
 end

 (0..pictures[0].heighth-1).each do |row|
   pictures.each do |picture|
     (0..picture.width-1).each do |column|
       print picture.picture[row][column]
       print " "
     end
   end
   puts ""
 end

没有评论: