SZIMP2 Ruby
A tárgy főoldala: SZIMP2
8. előadás (2007-04-06)
Az objektum-orientált programozás elméleti bevezetője hangzott el, és a matmul feladat megoldása felkerült a táblára Ruby nyelven.
Néhány új fogalom:
- osztály (a C-beli struktúratípusnak felel meg)
- objektum (a C-beli struktúrának felel meg)
- attribútum (a C-beli struktúramezőnek felel meg)
- metódus (a C-beli függvénynek felel meg)
9. gyakorlat (2007-04-10, 2007-04-13)
lepcso.rb:
n=7 l=[[1], [2,3], [4,5,6], ... ] # l.size==n p l
9. előadás (2007-04-13)
Objektum-orientáltan kezdtünk programozni Ruby nyelven, a Sikidom, BBox és Kor osztályok kerültek fel a táblára. Megismertük a szemétgyűjtést (garbage collection) is. Láttunk példát rá, hogy két változó mutathat ugyanarra az objektumra.
class BBox attr_accessor :llx, :lly, :urx, :ury end class Sikidom def bbox() fail # még nem tudjuk megírni, a Sikidom túl absztrakt end def kerulet() fail # még nem tudjuk megírni, a Sikidom túl absztrakt end def terulet() fail # még nem tudjuk megírni, a Sikidom túl absztrakt end end class Kor <Sikidom attr_accessor :cx, :cy, :r def bbox() b=BBox.new b.llx=@cx-@r; b.lly=@cy-@r b.urx=@cx+@r; b.ury=@cy+@r return b # a return fölösleges end def kerulet() Math::PI*2*@r end def terulet() Math::PI*@r*@r end end
10. gyakorlat (2007-04-17, 2007-04-20)
A Szórt Spektrum a Háztetőn Csillagjós és Rádióamatőr Klub holnap Guinness-rekordkísérletre készül: annyi űrturistával kívánják felvenni a kapcsolatot egy nap alatt, amennyivel csak lehet. Az internetről letöltötték a holnapi űrturista-áthaladási időpontokat. Minden áthaladáshoz három adat tartozik: az űrturista neve (szóközt nem tartalmaz), mikortól (hány órától) kezdve tartózkodik a klub rádiójának vételkörzetében, és mikor hagyja el a vételkörzetet. E két időpont egy balról zárt, jobbról nyílt intervallum végpontjai. Példa áthaladási időpontok (~/szimp2/urturista1.in):
Pirx_pilota 5 7 Leia_hercegno 7 9 Dalek_42 6 10 Kis_herceg 1 6
Írjon programot Ruby nyelven, ami beolvassa az áthaladási időpontokat, és kiválaszt a benne levő űrturisták közül egy olyan maximális részhalmazt, melynek bármely két eleméhez tartozó intervallumok diszjunktak. (A diszjunktságot azért kell kikötni, mert a klubnak csak egy rádiója van, és szerencsétlen esetben előfordulhat, hogy a teljes intervallumban próbálkozniuk kell, hogy végre összejöjjön a kapcsolat.)
Ötlet: Használja ki, hogy ha az intervallumok végpont szerint növekvő sorrendbe vannak rendezve, akkor a mohó algoritmus jó és optimális eredményt ad. A mohó algoritmus veszi sorra az intervallumokat, és egy intervallumot akkor választ ki, ha az ő metszete az utoljára kiválasztott intervallummal üres halmaz.
Mintamegoldás (Ivett és Viktor, ~/szimp2/urturista.rb):
class Intervallum attr_accessor :nev, :a, :b end p=[] STDIN.each_line { |s| t=s.split(/\s+/) h=Intervallum.new h.nev=t[0] h.a=t[1].to_i h.b=t[2].to_i #p[p.size]=h #p.push(h) p << h } p.sort!{|ha,hb| ha.b<=>hb.b} q=[] h0=nil p.each { |h| if (h0==nil || [h.a,h0.a].max >= [h.b,h0.b].min); q.push(h) h0=h end } q.each { |h| STDOUT.puts h.nev }
10. előadás (2007-04-20)
Megtanultuk:
- konstruktor (initialize)
- példányváltozó (@)
- metódus, amely beállít egy példányváltozót (attr_writer)
- metódus, amely visszaad egy példányváltozót (attr_reader)
- fekete doboz
11. gyakorlat (2007-04-24, 2007-04-27)
A keddi gyakorlat sportnap miatt elmaradt.
A gyakorlatot Bácsi László, LacKac (e-mail: lackac@) tartotta stringfeldolgozásról. Ezt a programot (~lackac/ruby/backup.rb) magyarázta:
require 'net/http' require 'iconv' class String def to_latin2 Iconv.iconv('iso-8859-2', 'utf-8', self)[0] end end class Feed def initialize url @url = url @items = [] end def get_content @content = Net::HTTP.get(URI.parse(@url)) end def parse get_content @content.gsub(/<item.*?>.*?<\/item>/m) do |match| item = {} match =~ /<title>(<!\[CDATA\[)?(.*?)(\]\]>)?<\/title>/m item[:title] = $2 match =~ /<link>(.*?)<\/link>/m item[:link] = $1 match =~ /<description>(<!\[CDATA\[)?(.*?)(\]\]>)?<\/description>/m item[:desc] = $2 @items << item end end def parse_by_xml require 'rexml/document' get_content xml = REXML::Document.new(@content) xml.elements.each('//item') do |match| item = {} item[:title] = match.elements['title'].text item[:link] = match.elements['link'].text item[:desc] = match.elements['description'].text @items << item end end def list @items.each do |item| puts item[:title].to_latin2 puts item[:link].to_latin2 l=0 item[:desc].split.each do |w| print " " if l == 0 print w.to_latin2+" " l+=w.length+1 if l > 60 print "\n" l = 0 end end print "\n" end end end feed = Feed.new(ARGV[0]) feed.parse_by_xml feed.list
Így próbáltuk:
$ ruby backup.rb 'http://24ora.index.hu/?rss&keres=&szerzokeres=&rovatkeres=osszes&order=1' $ ruby backup.rb 'http://origo.hu/contentpartner/rss/hircentrum/origo.xml'
11. előadás (2007-04-27)
Az előadást Bácsi László, LacKac (e-mail: lackac@) tartotta stringfeldolgozásról. Az IRB-be ezt írta be:
$ irb irb(main):001:0> irb(main):002:0* irb(main):003:0* n=42 => 42 irb(main):004:0> n.class => Fixnum irb(main):005:0> f=3.14 => 3.14 irb(main):006:0> f.class => Float irb(main):007:0> s="alma" => "alma" irb(main):008:0> s.class => String irb(main):009:0> irb(main):010:0* irb(main):011:0* irb(main):012:0* s.methods => ["methods", "instance_eval", "%", "rindex", "map", "<<", "split", "any?", "dup", "sort ", "strip", "size", "instance_variables", "downcase", "min", "gsub!", "count", "include?" , "succ!", "instance_of?", "extend", "downcase!", "intern", "squeeze!", "eql?", "*", "nex t", "find_all", "each", "rstrip!", "each_line", "+", "id", "sub", "slice!", "hash", "sing leton_methods", "tr", "replace", "inject", "reverse", "taint", "unpack", "sort_by", "lstr ip", "frozen?", "instance_variable_get", "capitalize", "max", "chop!", "method", "kind_of ?", "capitalize!", "scan", "select", "to_a", "display", "each_byte", "type", "casecmp", " gsub", "protected_methods", "empty?", "to_str", "partition", "tr_s", "tr!", "match", "gre p", "rstrip", "to_sym", "instance_variable_set", "next!", "swapcase", "chomp!", "is_a?", "swapcase!", "ljust", "respond_to?", "between?", "reject", "to_s", "upto", "hex", "sum", "class", "object_id", "reverse!", "chop", "<=>", "insert", "<", "tainted?", "private_meth ods", "==", "delete", "dump", "===", "__id__", "member?", "tr_s!", ">", "concat", "nil?", "untaint", "succ", "find", "strip!", "each_with_index", ">=", "to_i", "rjust", "<=", "se nd", "index", "collect", "inspect", "slice", "oct", "all?", "clone", "length", "entries", "chomp", "=~", "public_methods", "upcase", "sub!", "squeeze", "__send__", "upcase!", "cr ypt", "delete!", "equal?", "freeze", "detect", "zip", "[]", "lstrip!", "center", "[]=", " to_f"] irb(main):013:0> s+" korte" => "alma korte" irb(main):014:0> s => "alma" irb(main):015:0> s.methods.class => Array irb(main):016:0> s.methods.find_all {|m| m =~ /case/} => ["downcase", "downcase!", "casecmp", "swapcase", "swapcase!", "upcase", "upcase!"] irb(main):017:0> irb(main):018:0* irb(main):019:0* irb(main):020:0* a=[1,2,3,4,5,6] => [1, 2, 3, 4, 5, 6] irb(main):021:0> a.clas NoMethodError: undefined method `clas' for [1, 2, 3, 4, 5, 6]:Array from (irb):21 from :0 irb(main):022:0> a.class => Array irb(main):023:0> a.methods => ["methods", "instance_eval", "rindex", "map", "<<", "any?", "&", "dup", "sort", "join" , "pack", "reverse_each", "size", "instance_variables", "min", "include?", "collect!", "r assoc", "instance_of?", "extend", "at", "compact!", "eql?", "*", "find_all", "each", "+", "reject!", "flatten", "slice!", "pop", "hash", "id", "singleton_methods", "-", "transpos e", "replace", "inject", "reverse", "indexes", "sort_by", "taint", "map!", "uniq", "max", "frozen?", "instance_variable_get", "fetch", "method", "kind_of?", "values_at", "|", "se lect", "to_a", "display", "type", "shift", "protected_methods", "empty?", "clear", "parti tion", "indices", "grep", "instance_variable_set", "is_a?", "flatten!", "first", "respond _to?", "reject", "to_s", "delete_at", "nitems", "class", "reverse!", "<=>", "unshift", "i nsert", "object_id", "tainted?", "private_methods", "==", "delete", "fill", "===", "__id_ _", "member?", "uniq!", "concat", "find", "nil?", "untaint", "compact", "each_with_index" , "last", "send", "delete_if", "index", "collect", "inspect", "slice", "all?", "clone", " =~", "each_index", "length", "entries", "sort!", "assoc", "public_methods", "__send__", " to_ary", "equal?", "freeze", "detect", "zip", "[]", "[]=", "push"] irb(main):024:0> n.size => 4 irb(main):025:0> a.size => 6 irb(main):026:0> a.nitems => 6 irb(main):027:0> n => 42 irb(main):028:0> irb(main):029:0* irb(main):030:0* a=[1,2,3,4] => [1, 2, 3, 4] irb(main):031:0> b=["egy","ketto",harom"] irb(main):032:1" " irb(main):033:1> b=["egy","ketto","harom"] irb(main):034:1> 10000000.size irb(main):035:1> 10_000_000.size irb(main):036:1> " irb(main):037:1" " irb(main):038:1> irb(main):039:1* irb(main):040:1* irb(main):041:1* n=10_000_000_000 irb(main):042:1> n.class irb(main):043:1> SyntaxError: compile error (irb):31: parse error, unexpected tSTRING_BEG, expecting kDO or '{' or '(' b=["egy","ketto",harom"] ^ from (irb):42 from (null):0 LacKac@LacKacMB:~> irb irb(main):001:0> n=10_000_000_000 => 10000000000 irb(main):002:0> n.size => 8 irb(main):003:0> n=1_000_000_000 => 1000000000 irb(main):004:0> n.size => 4 irb(main):005:0> a=[1,2,3,4] => [1, 2, 3, 4] irb(main):006:0> b=["egy","ketto","harom"] => ["egy", "ketto", "harom"] irb(main):007:0> a+b => [1, 2, 3, 4, "egy", "ketto", "harom"] irb(main):008:0> [1,2,3]+[3,4,5] => [1, 2, 3, 3, 4, 5] irb(main):009:0> [1,2,3]|[3,4,5] => [1, 2, 3, 4, 5] irb(main):010:0> [1,2,3]-[3,4,5] => [1, 2] irb(main):011:0> [1,2,3]^[3,4,5] NoMethodError: undefined method `^' for [1, 2, 3]:Array from (irb):11 from :0 irb(main):012:0> [1,2,3]&[3,4,5] => [3] irb(main):013:0> [1,2,3]*3 => [1, 2, 3, 1, 2, 3, 1, 2, 3] irb(main):014:0> [1,2,3]==[1,2,3] => true irb(main):015:0> [1,2,3]==[2,1,3] => false irb(main):016:0> a=[1,2,3,4,5] => [1, 2, 3, 4, 5] irb(main):017:0> a[0] => 1 irb(main):018:0> a[4] => 5 irb(main):019:0> a[-1] => 5 irb(main):020:0> a[-3] => 3 irb(main):021:0> a[-3]="harom" => "harom" irb(main):022:0> a => [1, 2, "harom", 4, 5] irb(main):023:0> a[23423] => nil irb(main):024:0> a.sort ArgumentError: comparison of Fixnum with String failed from (irb):24:in `sort' from (irb):24 from :0 irb(main):025:0> a.sort_by^C irb(main):025:0> a=[3,6,2,89,42 irb(main):026:1> ] => [3, 6, 2, 89, 42] irb(main):027:0> a=[3,6,2,89,42] => [3, 6, 2, 89, 42] irb(main):028:0> a.sort => [2, 3, 6, 42, 89] irb(main):029:0> b => ["egy", "ketto", "harom"] irb(main):030:0> b.sort => ["egy", "harom", "ketto"] irb(main):031:0> c=a.map! {|i| i.to_s} => ["3", "6", "2", "89", "42"] irb(main):032:0> a.has?(4) NoMethodError: undefined method `has?' for ["3", "6", "2", "89", "42"]:Array from (irb):32 from :0 irb(main):033:0> a.include?(4) => false irb(main):034:0> a.include?(89) => false irb(main):035:0> a => ["3", "6", "2", "89", "42"] irb(main):036:0> a.include?("89") => true irb(main):037:0> a.sort => ["2", "3", "42", "6", "89"] irb(main):038:0> a.sort_by {|i| i.to_i} => ["2", "3", "6", "42", "89"] irb(main):039:0> a => ["3", "6", "2", "89", "42"] irb(main):040:0> b => ["egy", "ketto", "harom"] irb(main):041:0> b=["alma","korte","dio"] => ["alma", "korte", "dio"] irb(main):042:0> b.sort_by {|s| s.length} => ["dio", "alma", "korte"] irb(main):043:0> b.sort_by {|valami| valami.length} => ["dio", "alma", "korte"] irb(main):044:0> s="alma korte dio" => "alma korte dio" irb(main):045:0> s.length => 14 irb(main):046:0> s[6] => 111 irb(main):047:0> s[6].class => Fixnum irb(main):048:0> s[6] == "a" => false irb(main):049:0> s[6] == "k" => false irb(main):050:0> s[6] == ?k => false irb(main):051:0> ?k => 107 irb(main):052:0> ?o => 111 irb(main):053:0> s[6] == ?o => true irb(main):054:0> irb(main):055:0* s => "alma korte dio" irb(main):056:0> s.split => ["alma", "korte", "dio"] irb(main):057:0> mac="16:ef:3d:3a:56:dc" => "16:ef:3d:3a:56:dc" irb(main):058:0> mac.split(":") => ["16", "ef", "3d", "3a", "56", "dc"] irb(main):059:0> mac="16:ef 3d.3a:56.dc" => "16:ef 3d.3a:56.dc" irb(main):060:0> mac.split(":") => ["16", "ef 3d.3a", "56.dc"] irb(main):061:0> mac.split(":. ") => ["16:ef 3d.3a:56.dc"] irb(main):062:0> mac.split(/[:\. ]/) => ["16", "ef", "3d", "3a", "56", "dc"] irb(main):063:0> "alma"+"korte" => "almakorte" irb(main):064:0> "alma"+" "+"korte" => "alma korte" irb(main):065:0> 'alma' => "alma" irb(main):066:0> print "alma\n" alma => nil irb(main):067:0> print "alma" alma=> nil irb(main):068:0> print "alma\n" alma => nil irb(main):069:0> print "alma\tkorte\tdio\n" alma korte dio => nil irb(main):070:0> print 'alma\tkorte\tdio\n' alma\tkorte\tdio\n=> nil irb(main):071:0> irb(main):072:0* n=42 => 42 irb(main):073:0> s="egy" => "egy" irb(main):074:0> s="ertelme" => "ertelme" irb(main):075:0> print "az elet "+s+" "n SyntaxError: compile error (irb):75: parse error, unexpected tIDENTIFIER, expecting $ from (irb):75 from :0 irb(main):076:0> print "az elet "+s+" "+n TypeError: can't convert Fixnum into String from (irb):76:in `+' from (irb):76 from :0 irb(main):077:0> print "az elet "+s+" "+n.to_s az elet ertelme 42=> nil irb(main):078:0> print "az elet "+s+" "+n.to_s+"\n" az elet ertelme 42 => nil irb(main):079:0> print "az elet #{s} #{n}\n" az elet ertelme 42 => nil irb(main):080:0> print "az elet #{s.upcase} #{n}\n" az elet ERTELME 42 => nil irb(main):081:0> irb(main):082:0* irb(main):083:0* irb(main):084:0* s.upcase => "ERTELME" irb(main):085:0> s="LacKac" => "LacKac" irb(main):086:0> s.upcase => "LACKAC" irb(main):087:0> s.downcase => "lackac" irb(main):088:0> s.swapcase => "lACkAC" irb(main):089:0> s => "LacKac" irb(main):090:0> s.upcase! => "LACKAC" irb(main):091:0> s => "LACKAC" irb(main):092:0> s.methods => ["methods", "instance_eval", "%", "rindex", "map", "<<", "split", "any?", "dup", "sort ", "strip", "size", "instance_variables", "downcase", "min", "gsub!", "count", "include?" , "succ!", "instance_of?", "extend", "downcase!", "intern", "squeeze!", "eql?", "*", "nex t", "find_all", "each", "rstrip!", "each_line", "+", "id", "sub", "slice!", "hash", "sing leton_methods", "tr", "replace", "inject", "reverse", "taint", "unpack", "sort_by", "lstr ip", "frozen?", "instance_variable_get", "capitalize", "max", "chop!", "method", "kind_of ?", "capitalize!", "scan", "select", "to_a", "display", "each_byte", "type", "casecmp", " gsub", "protected_methods", "empty?", "to_str", "partition", "tr_s", "tr!", "match", "gre p", "rstrip", "to_sym", "instance_variable_set", "next!", "swapcase", "chomp!", "is_a?", "swapcase!", "ljust", "respond_to?", "between?", "reject", "to_s", "upto", "hex", "sum", "class", "object_id", "reverse!", "chop", "<=>", "insert", "<", "tainted?", "private_meth ods", "==", "delete", "dump", "===", "__id__", "member?", "tr_s!", ">", "concat", "nil?", "untaint", "succ", "find", "strip!", "each_with_index", ">=", "to_i", "rjust", "<=", "se nd", "index", "collect", "inspect", "slice", "oct", "all?", "clone", "length", "entries", "chomp", "=~", "public_methods", "upcase", "sub!", "squeeze", "__send__", "upcase!", "cr ypt", "delete!", "equal?", "freeze", "detect", "zip", "[]", "lstrip!", "center", "[]=", " to_f"] irb(main):093:0> s.reverse => "CAKCAL" irb(main):094:0> a => ["3", "6", "2", "89", "42"] irb(main):095:0> a.reverse => ["42", "89", "2", "6", "3"] irb(main):096:0> "bacsi laszlo".capitalize => "Bacsi laszlo" irb(main):097:0> nev = "bacsi laszlo istvan" => "bacsi laszlo istvan" irb(main):098:0> nev.splite NoMethodError: undefined method `splite' for "bacsi laszlo istvan":String from (irb):98 from :0 irb(main):099:0> nev.split => ["bacsi", "laszlo", "istvan"] irb(main):100:0> nev.split.map {|i| i.capitalize} => ["Bacsi", "Laszlo", "Istvan"] irb(main):101:0> nev.split.map {|i| i.capitalize}.join => "BacsiLaszloIstvan" irb(main):102:0> nev.split.map {|i| i.capitalize}.join(" ") => "Bacsi Laszlo Istvan" irb(main):103:0> a=["alma", "korte", "szilva"] => ["alma", "korte", "szilva"] irb(main):104:0> a.each {|i| puts i} alma korte szilva => ["alma", "korte", "szilva"] irb(main):105:0> a.each_with_index {|v,i| puts "#{i}: #{v}"} 0: alma 1: korte 2: szilva => ["alma", "korte", "szilva"] irb(main):106:0> a.each_with_index {|v,i| print "#{i}: #{v}"} 0: alma1: korte2: szilva=> ["alma", "korte", "szilva"] irb(main):107:0> a.each_with_index {|v,i| print "#{i}: #{v}\n"} 0: alma 1: korte 2: szilva => ["alma", "korte", "szilva"] irb(main):108:0> s="alma\nkorte\nszilva" => "alma\nkorte\nszilva" irb(main):109:0> print s alma korte szilva=> nil irb(main):110:0> s.each_line {|l| puts l} alma korte szilva => "alma\nkorte\nszilva" irb(main):111:0> irb(main):112:0* irb(main):113:0* irb(main):114:0* s => "alma\nkorte\nszilva" irb(main):115:0> s="alma korte szilva" => "alma korte szilva" irb(main):116:0> s.split => ["alma", "korte", "szilva"] irb(main):117:0> a=["alma", "korte", szilva"] irb(main):118:1" ["] SyntaxError: compile error (irb):117: parse error, unexpected tSTRING_BEG, expecting kDO or '{' or '(' a=["alma", "korte", szilva"] ^ (irb):118: parse error, unexpected ']', expecting $ from (irb):118 from :0 irb(main):119:0> a=["alma", "korte", "szilva"] => ["alma", "korte", "szilva"] irb(main):120:0> a= %w{ alma korte szilva } => ["alma", "korte", "szilva"] irb(main):121:0> a= %w{alma korte szilva} => ["alma", "korte", "szilva"]
12. gyakorlat (2007-05-01, 2007-05-04)
A keddi, május elsejei gyakorlat az ünnep miatt elmarad. Énekszó és tánc köszöntse.
12. előadás (2007-05-04)
13. gyakorlat (2007-05-08, 2007-05-11)
13. előadás (2007-05-11)
14. gyakorlat (2007-05-15, 2007-05-18)
Nyomkövetésről és hibakeresésről lesz szó mind C, mind Ruby nyelven. printf, kdevelop, valgrind, strace.
14. előadás (2007-05-18)
Mivel a március 15. előtti szombaton plusz egy előadást tartottunk, ezért a félévben egy előadást ki kell hagyni. Ez lesz az. Pontosabban: az előadás meg lesz tartva, és továbbmegyünk az anyagban, de nem kötelező eljönni. Ennek az előadásnak az anyaga nem lesz számonkérve (nem is lehet, mivel a ZH-t az előző héten már megírtuk). Az előadás előtti gyakorlat természetesen kötelező.
A második ZH
A második ZH időpontja: 2007. május 11. péntek, 12:00. A teremfogalásról időben gondoskodunk. PótZH a vizsgaidőszak első hetében lesz. A ZH témája objektum-orientált programozás Ruby nyelven. A ZH-n 1 db, kézzel, kék tollal írt A4-es lapnyi puskát lehet használni. A ZH-n kb. 50% programozási és 50% elméleti feladat lesz. Aki a programozási feladatokat számítógéppel szeretné írni, az jelentkezzen e-mailben a tárgy előadójánál. A számítógépes megoldás lehetőségét technikai okokból csak abban az esetben tudjuk biztosítani, ha max. 10 jelentkező lesz.