Vyriešené zadania z prvého týždňa


A) Collatzová rada

Prvé dva obrázky boli vygenerované za pomoci vlastnej knižnice pre prácu s Svg grafikou. Ostatné 4 obrazky boli vygenerované pomocou gnuplot knižnice.

Algoritmus:

class Collatz
  def initialize(number)
    @number = number
  end

  def sequence
    @_sequence ||= collatz_sequence(@number)
  end

  def number_of_steps
    sequence.count
  end

  def maximum_number
    sequence.max
  end

  def collatz_sequence(number)
    return [number] if number == 1

    next_number = number.even? ? number/2 : number*3 + 1
    [number].concat collatz_sequence(next_number)
  end
end

Outputs:

collatz_max.png
collatz_steps.png
collatz_max_plot.png
collatz_steps_plot.png
collatz_max_25_plot.png
collatz_sequence_27_plot.png

B) Práca s grafikou

Práca s bitmapov:

require 'rubygems'
require 'RMagick'
include Magick

def bitmap_method
  img = Image.new(256, 256) {
    self.background_color = 'white'
  }

  256.times do |x|
    256.times do |y|
      img.pixel_color(x, 0, 255 - y, "rgb(#{x},0,#{255-y})")
    end
  end

  img.display
end

Práca s Svg grafikou:

def svg_method(size)
  size_2  = size/2.0
  size_20 = size/20.0?

  svg_line_args = {:swidth => 2}

  svg = Svg::Svg.new :width => size, :height => size
  (0..10).each do |i|
    svg.add_shape(Svg::Line.new(     i*size_20, size_2, size_2, size_2-i*size_20, svg_line_args))
    svg.add_shape(Svg::Line.new(size-i*size_20, size_2, size_2, size_2-i*size_20, svg_line_args))
    svg.add_shape(Svg::Line.new(     i*size_20, size_2, size_2, size_2+i*size_20, svg_line_args))
    svg.add_shape(Svg::Line.new(size-i*size_20, size_2, size_2, size_2+i*size_20, svg_line_args))
  end

  svg.doc.write File.new('svg_graphics.svg', 'w')
end

if __FILE__ == $0
  svg_method(640)
end

Outputs:

bitmap.png
svg_graphics.png

C) Ulamova špirála

Algoritmus:

require 'rubygems'
require 'RMagick'
include Magick

class UlamSpiral
  DIRECTIONS = [[1, 0], [0, -1], [-1, 0], [0, 1]]

  # @param [Numeric] size number of columns and rows (size x size)
  def initialize(size)
    @size = size.odd? ? size : size-1
    @current_position = [@size/2, @size/2]
    @direction = 0
  end

  def generate_img(img)
    number, step = 1, 1

    while number <= @size**2
      2.times do
        step.times do
          x, y = @current_position
          img.pixel_color(x, y, 'black') if block_given? and yield(number)
          number += 1
          xt, yt = DIRECTIONS[@direction]
          @current_position = [x+xt, y+yt]
        end
       @direction = (@direction+1)%4
      end
      step += 1
    end

    return img
  end
end

if __FILE__ == $0
  size = 640
  img = Image.new(size, size) {
    self.background_color = 'white'
  }

  ulms = UlamSpiral.new(size)
  img = ulms.generate_img(img) { |number| number.prime? }

  img.write 'png:outputs/ulam_prime.png'


  img = Image.new(size, size) {
    self.background_color = 'white'
  }

  ulms = UlamSpiral.new(size)
  img = ulms.generate_img(img) { |number| number % 7 == 0 }

  img.write 'png:outputs/ulam_modulo_7.png
end

Outputs:

ulam_prime.png
ulam_modulo_7.png

D) Vizualizácia najväčšieho spoločného delitela

Algoritmus:

class Gcd
  class << self
    def gcd_subtract(a, b)
      while a != b
        a, b = b, a if a < b
        a = a - b
        yield if block_given?
      end

      return a
    end

    def gcd_modulo(a, b)
      a, b = b, a if a < b

      while a % b != 0
        a, b = b, a % b
        yield if block_given?
      end

      return b
    end

    def gcd_subtract_steps(a, b)
      res = 0
      Gcd.gcd_subtract(a, b) { res += 1 }
      return res
    end

    def gcd_modulo_steps(a, b)
      res = 0
      Gcd.gcd_modulo(a, b) { res += 1 }
      return res
    end
  end
end

require 'rubygems'
require 'RMagick'

include Magick

def visualize_gcd
  size = 256
  img = Image.new(size, size) {
    self.background_color = 'black'
  }

  size.times do |x|
    size.times do |y|
      img.pixel_color(x, size-y, "cmyk(0,0,0,#{yield(x,y)}") if block_given?
    end
  end

  return img
end

if __FILE__ == $0
  # gcd size
  img = visualize_gcd { |x,y| Gcd.gcd_modulo(x+1, y+1) % 256 }
  img.write 'png:outputs/gcd_size.png'

  # gcd subtract steps
  img = visualize_gcd { |x,y| Gcd.gcd_subtract_steps(x+1, y+1) % 256 }
  img.write 'png:outputs/gcd_subtract_steps.png'

  # gcd modulo steps 24
  img = visualize_gcd { |x,y| 24 * Gcd.gcd_modulo_steps(x+1, y+1) % 256 }
  img.write 'png:outputs/gcd_modulo_steps_24.png
end

Outputs:

gcd_size.png
gcd_subtract_steps.png
gcd_modulo_steps_24.png