#!/usr/bin/env ruby -w require 'tk' class Wave include Enumerable @@num_instances = 0 attr_accessor :data def Wave.numinstances @@num_instances end def initialize(formula,points = 300) @@num_instances += 1 @data = [] points.times {|i| @data << 0.0} @points = points if(formula) (0..points-1).each do |p| x = p*Math::PI*2.0/points @data[p] = eval(formula) end end end def to_s @data.each {|d| print d} end def +(other) target = Wave.new(nil,@points) target.data.each_index {|i| target.data[i] = @data[i] + other.data[i]} target end def *(other) target = Wave.new(nil,@points) if (other.class == 5.class || other.class == 5.0.class) target.data.each_index {|i| target.data[i] = @data[i] * other} else target.data.each_index {|i| target.data[i] = @data[i] * other.data[i]} end target end def each raise LocalJumpError,caller unless block_given? @data.each {|pt| yield pt} end def -(other) target = Wave.new(nil,@points) target.data.each_index {|i| target.data[i] = @data[i] - other.data[i]} target end def integral ans = 0.0 @data.each {|pt| ans += pt} ans*2.0*Math::PI/@points end def plot(_title="??",pixHeight=200,maxY=1.5,others=[]) pixHeight = @points*(2.0/3.0) if pixHeight pixWidth = @points maxY = [(@data.max),-(@data.min)].max if !maxY offset = pixHeight/2.0 scale = offset/maxY win = TkRoot.new {title _title} canvas = TkCanvas.new("width"=>pixWidth,"height"=>pixHeight) #create zero line TkcLine.new(canvas,0,offset,pixWidth,offset) canvas.pack() self.plotOne(canvas,pixWidth,scale,offset) others.each {|i| i.plotOne(canvas,pixWidth,scale,offset)} Tk.mainloop end def plotOne(canvas,pixWidth,scale,offset) (0..pixWidth-1).each do |x| y1 = offset - @data[x] * scale if x != (pixWidth-1) y = offset - @data[x+1] * scale else y = y1 end TkcLine.new(canvas,x,y1,(x+1),y) if (x && x!=pixWidth-1) end end end if __FILE__ == $0 a = Wave.new("Math.sin(4*x)",400) b = Wave.new("(Math.sin(3*x))/3.0",400) c = Wave.new("(Math.sin(5*x))/5.0",400) d = Wave.new("(Math.sin(7*x))/7.0",400) e = Wave.new("(Math.sin(9*x))/9.0",400) f = Wave.new("(Math.sin(11*x))/11.0",400) g = Wave.new("(Math.sin(13*x))/13.0",400) h = Wave.new("(Math.sin(15*x))/15.0",400) i = Wave.new("(Math.sin(17*x))/17.0",400) j = Wave.new("(Math.sin(19*x))/19.0",400) k = Wave.new("(Math.sin(21*x))/21.0",400) l = Wave.new("(Math.sin(23*x))/23.0",400) m = Wave.new("(Math.sin(25*x))/25.0",400) res= a-c+e*f-g*h-i+j*k*l-m res.plot("sin(4x)") res.each {|x| puts x} puts "The number of instances is #{Wave.numinstances}" end