SZIMP2 Ruby
(→8. előadás (2007-04-06)) |
|||
4. sor: | 4. sor: | ||
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. | 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. | ||
+ | |||
+ | Ha a Ruby osztályhierarchiája hasonló a biológiai törzsfához. Például a gerincesek(osztály) törzsén belül a madarak(osztály) osztályának egy alosztálya a pacsirta(osztály) nevű faj, melynek egy példánya a csipcsip nevű kismadarunk (objektum), aki mellesleg egy pacsirta. Őt jellemezhetjük különböző tulajdonságai alapján. Ezek az attribútumok. Például: él-e még? , mennyire éhes, hogy hívják a párját, stb. Tehát bizonyos tulajdonságait megadjuk, amik csak rá jellemzőek. | ||
+ | Matmul Rubyban: | ||
+ | |||
+ | a=[[1,2], #megadjuk az 'a' mátrixot | ||
+ | [3,4], | ||
+ | [5,6]] | ||
+ | b=[[7], #megadjuk a 'b' mátrixot | ||
+ | [8]] | ||
+ | |||
+ | ab=[] #létrehozzuk az üres szorzatmátrixot | ||
+ | i=0; while i<a.size; #'''while''' | ||
+ | ujsor=[] | ||
+ | j=0; while j<b[0].size; | ||
+ | x=0 | ||
+ | k=0; while k<b.size | ||
+ | x+=a[i][k]*b[k][j] | ||
+ | ujsor[j]=x | ||
+ | end | ||
+ | ab[i]=ujsor | ||
+ | end | ||
Néhány új fogalom: | Néhány új fogalom: |
A lap 2007. május 18., 15:52-kori változata
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.
Ha a Ruby osztályhierarchiája hasonló a biológiai törzsfához. Például a gerincesek(osztály) törzsén belül a madarak(osztály) osztályának egy alosztálya a pacsirta(osztály) nevű faj, melynek egy példánya a csipcsip nevű kismadarunk (objektum), aki mellesleg egy pacsirta. Őt jellemezhetjük különböző tulajdonságai alapján. Ezek az attribútumok. Például: él-e még? , mennyire éhes, hogy hívják a párját, stb. Tehát bizonyos tulajdonságait megadjuk, amik csak rá jellemzőek. Matmul Rubyban:
a=[[1,2], #megadjuk az 'a' mátrixot [3,4], [5,6]] b=[[7], #megadjuk a 'b' mátrixot [8]]
ab=[] #létrehozzuk az üres szorzatmátrixot i=0; while i<a.size; #while ujsor=[] j=0; while j<b[0].size; x=0 k=0; while k<b.size x+=a[i][k]*b[k][j] ujsor[j]=x end ab[i]=ujsor end
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 elmaradt. Énekszó és tánc köszöntse. A pénteki gyakorlat anyaga következik.
A tanult C beépített függvények:
- printf()
- scanf()
- putchar()
- getchar()
- abort()
A tanult Ruby beépített osztályok:
- Object
- Float
- Fixnum
- Bignum
- Integer
- String
- Array
- Module
- Class
- TrueClass
- FalseClass
- NilClass
- Hash
- Regexp
Próbálkozások:
$ irb 1.2.class 42.class 42.class.class 42.class.class.class 2**42.class # hiba (2**42).class (2**61).class (2**62).class "".class .class [].class {}.class 42.class.superclass 42.class.superclass.superclass 42.class.superclass.superclass.superclass 42.kind_of?(Fixnum) #: true 42.kind_of?(Integer) #: true 42.kind_of?(String) #: false true.class false.lass nil.class Float.superclass String.methods
Az összes beépített osztály listázása (pl. String):
Object.constants.sort.select { |c| Object.const_get(c).kind_of?(Class) }
Az összes beépített modul listázása (pl. Math):
Object.constants.sort.select { |c| Object.const_get(c).kind_of?(Module) && !Object.const_get(c).kind_of?(Class) }
Osztályhiearachia-részlet:
Object String Array Hash Regexp Numeric Float Integer Fixnum Bignum
A program (listastszamol.rb), amely megszámolja, hogy az aktuális felhasználó levelesládájában a mat06 levelezési listára ki hány levelet küldött, és a küldések számának növekvő sorrendjében nyomtatja ki a feladó e-mail címeket:
r=/^List-Id: *mat06[.]lists[.]math[.]bme[.]hu$/ # p r.class #: Regexp f=File.open(ENV["MAIL"]) listas=false; fejlecben=false froml=nil h={} f.each_line { |l| if fejlecben && l =~ r; then listas=true end if fejlecben && l =~ /^From: *(.*)/ froml=$1 if froml=~/<(.*?)>/; froml=$1 end if froml !~/[@]/; froml=nil end end if fejlecben && l =~ /^$/; if listas and froml; if h.has_key?(froml); h[froml]+=1 else h[froml]=1 end #p froml end froml=nil; listas=false; fejlecben=false end if l =~ /^From /; fejlecben=true end } h.sort { |a,b| a[1]<=>b[1] }.each { |k,v| print "#{v} #{k}\n" }
12. előadás (2007-05-04)
Kivételkezelésről volt szó.
begin f=File.open("bableves.txt") p f.readline p f.readline rescue Errno::ENOENT print "A fájl nem létezik!\n" rescue SystemCallError => e print "Rendszerhiba\n" p e ensure f.close if f && !f.closed? end
Osztályhiererchia-részlet:
Object Exception StandardError SystemCallError Errno::ENOENT
Saját kivétel definiálása:
class NemPozitivHiba <Exception; end def feldolgoz(sor) f=sor.to_f raise NemPozitivHiba, "valami üzenet" if f<=0.0 print "#{Math::sqrt(f)}\n" end STDIN.each_line { |l| begin feldolgoz(l) rescue NemPozitivHiba print "NEM POZITIV\n" end }
13. gyakorlat (2007-05-08, 2007-05-11)
Ezen a pénteken volt a ZH. A gyakorlaton a ZH-feladatokhoz hasonló feladatokat oldottunk meg.
13. előadás (2007-05-11)
A gyors prímtényezőkre bontás algoritmusa volt. Pontosabban: egy olyan algoritmus hangzott el, ami egy j jegyű pozitív egész számnak polinomidőben (O(j^k) db alapművelettel) meghatározza egy valódi osztóját, vagy visszaadja, hogy a szám prím. Sajnos az algoritmus a részletszámítások során az eredeti számnál jóval többjegyű számokkal végez műveleteket, és mivel nagy számokkal lassú számolni, ezért hiába végez kevés műveletet, összességében lassú lesz, legalábbis a mai számítógépeken polinomidőnél lassabb lesz.
14. gyakorlat (2007-05-15, 2007-05-18)
A terv az volt, hogy nyomkövetésről és hibakeresésről lesz szó mind C, mind Ruby nyelven. printf, kdevelop, valgrind, strace.
Ezek közül megvalósítottuk a hibakeresést C nyelven printf és valgrind segítségével, továbbá volt szó a veremkialakításról C-ben, a puffertúlcsordulásos hibákról és kihasználásukról.
Mi a hiba az alábbi C programban? ~/szimp2/fibjavit0.c:
#include <stdio.h> int fib(int n) { printf("FIB %d\n", n); if (n==0) return 0; return fib(n-1, t)+fib(n-2); }
int main(void) { printf("%d\n", fib(10)); return 0; }
Mi a hiba az alábbi C programban? ~/szimp2/fibjavit1.c:
#include <stdio.h> int fib(int n, int *t) { int f; if (n<2) f=n; else f=fib(n-1, t)+fib(n-2, t); t[n]=f; return f; }
int main(void) { int t[2]; printf("%d\n", fib(10, &t[0])); return 0; }
Mi a hiba az alábbi C programban? ~/szimp2/fibjavit2.c:
#include <stdio.h> #include <stdlib.h> int fib(int n, int *t) { int i; t[0]=0; if (n<=0) return t[0]; t[1]=1; if (n<=1) return t[1]; for (i=2;i<=n;i++) { t[i]=t[i-1]+t[i-2]; } return t[n]; } int main(void) { int *t=malloc(100001); printf("%d\n", fib(100000, &t[0])); free(t); return 0; }
Tekintsük az alábbi C programot (~/szimp2/fibt2.c):
#include <stdio.h> int fib(int n, int *t) { int f; if (n<2) f=n; else f=fib(n-1, t)+fib(n-2, t); t[n]=f; return f; } int main(void) { int t[2]; printf("Hello, World! %d\n", fib(22, t)); return 0; }
Kipróbálás:
$ gcc -s -O2 -W -Wall -o fibt2 fibt2.c $ ./fibt2 17711 Szegmens hiba
Kiírja a helyes eredményt (17711), majd szegmens hiba lesz. Azért, mert a t tömb csak 2 elemű, és 22 elemet rak bele a fib. Az extra elemek felülírják a main() visszatérési címét.
Indulás után egy kicsivel így néz ki a verem:
fib(2) visszatérési címe n: 2 --------------------------- fib(3) visszatérési címe n: 3 --------------------------- ... --------------------------- fib(22) visszatérési címe n: 22 --------------------------- t[0]==0 t[1]==1 main() visszatérési címe ---------------------------
Mikor a fib-ek visszatérnek, így néz ki a verem:
t[0]==0 t[1]==1 t[2]==1 (a main() visszatérési címe felülírva) t[3]==2 ... t[22]==17711
Ezután a main() már nem tud visszatérni, mert a visszatérési címét felülírták.
Próbáljuk valgrinddel:
$ gcc -g -W -Wall -o fibt2g fibt2.c $ ./valgrind ./fibt2g ... Hello, World! 17711 ==29070== Jump to the invalid address stated on the next line ==29070== at 0xD00000008: ??? ==29070== Address 0xD00000008 is not stack'd, malloc'd or (recently) free'd ==29070== ==29070== Process terminating with default action of signal 11 (SIGSEGV) ==29070== Bad permissions for mapped region at address 0xD00000008 ==29070== at 0xD00000008: ??? ...
A valgrind se mondja meg, hol a hiba (stack trace), mert a visszatérési cím alapján jelezne.
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
Időpontok:
- elmaradt keddi gyakorlatok pótlása: 2006. május 8. kedd, 12:00--14:15.
- konzultáció: 2007. május 10. csütörtök, 14:14--19:19. H.27. A konzultáció korábban is véget érhet a meghirdetettnél: ha 15 percen belül nem hangzik el kérdés.
- ZH papíron: 2007. május 11. péntek, 12:00--14:00. K.mf.65. Felügyel: Sisak Áron. Javítja: Sisak Áron.
- ZH programozás (opcionális): 2007. május 11. péntek, 14:00--16:00, H.57. Felügyel: Sisak Áron.
- A pótZH 7 nappal a ZH után lesz, a napon belül azonos időbeosztás szerint. Terem: J.208.
- A gyakIV 14 nappal a ZH után lesz, lásd a saját fejezetében.
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.
Mely beépített metódusokat kell ismerni
A tanult Ruby beépített osztályok és metódusok:
- Object
- class
- methods
- Float
- abs + - * < <= == != >= > <=> **
- Fixnum
- abs + - * < <= == != >= > <=> << >> **
- Bignum
- (semmit)
- Integer
- (semmit)
- String
- + =~ !~ split split! chomp chomp! reverse $1 $2 <=> upcase upcase! downcase downcase! reverse reverse!
- Array
- [] []= + - | & join each size << push max min find_all sort sort! sort_by sort_by! include?
- Module
- (semmit)
- Class
- superclass
- TrueClass
- && || ! == !=
- FalseClass
- && || ! == !=
- NilClass
- == !=
- Hash
- [] []= has_key? keys values size delete each_pair
- Regexp
- (semmit)
- Math
- sqrt PI
Van még: STDIN.each_line, p, print, puts.
Hogy a fentiek mit csinálnak, annak itt lehet utánanézni: http://www.ruby-doc.org/core/
Mintafeladatok
Az alábbiakhoz hasonló és másféle feladatok is várhatók a második ZH-n.
Elméleti feladatok:
- Az
x.foo()
hívás esetén mely osztályokban és milyen sorrendben keresi a Ruby a meghívandó metódust? - Hozzon létre egy olyan x objektumot, melyre
x.kind_of?(Alma) && x.class!=Alma
- Mikor áll a C-beli
int i=1; while (i!=0) i*=2;
ciklus? Mikor áll le a Ruby-belii=1; while i!=0; i*=2; end
ciklus? - Írjon egy olyan osztályt Ruby nyelven, amely paraméteres konstruktorral rendelkezik, és hozzon létre két példányt. Hányszor hívódik meg a konstruktor?
- Mutasson példát arra, hogy az
x.leszed()
hívás nem a Gyumolcs osztályon belül definiált leszed metódust hívja, nohax.kind_of?(Gyumolcs)
- Mit ad vissza a
self
egy metóduson belül? - Mi a különbség egy metóduson belül a
foo=5
,@foo=5
és aself.foo=5
értékadások között? - Írjon egy olyan metódust, melyben a
p foo
hívás kétszer szerepel, de csak az egyik esetben írja ki a foo nevű lokális változó értékét, a másik esetben mást ír ki. - Írja át az alábbi kódot úgy, hogy
@a<=@b
mindig teljesüljön. Ha a hívó olyan helyzetet akarna előidézni, amely megsérti a fenti feltételt, akkor dobjon kivételtfail
-lel. (Segítség: 3 db metódusba kellfail
-t tenni.) mintamegoldás
class Intervallum attr_accessor :a, :b def initialize(a, b) @a=a; @b=b end end
- Az alábbi kód végrehajtása után a a Ruby lefuttatja a szemétgyűjtést. Rajzolja fel az
# itt
sor végrehajtásakor az objektumokat, és azt, hogy az a és b változók mely objektumra mutatnak. Mely objektumok maradnak meg, és melyeket szabadítja fel a szemétgyűjtés?
class Gyerek attr_accessor :nev, :kov def initialize(nev) @nev=nev; @kov=nil; end end def egyik() pal=Gyerek.new("Pal") kata=Gyerek.new("Kata") peter=Gyerek.new("Peter") pal.kov=kata; kata.kov=peter; peter.kov=pal end def masik() sandor=Gyerek.new("Sandor") jozsef=Gyerek.new("Jozsef") benedek=Gyerek.new("Benedek") sandor.kov=jozsef; jozsef.kov=benedek end a=egyik b=masik # itt a=nil
Programozási feladatok:
- Írjon Ruby-programot sorhosszcsokkeno.rb néven, amely beolvassa a bemenet sorait, majd a sorhossz szerinti csökkenő sorrendben kiírja a sorokat. Az egyenlő hosszúságú sorok sorrendje tetszőleges.
- Írjon Ruby-programot abszoluterteknovekvo.rb néven, amely beolvassa a bemenet sorait (a sorok egész számokat tartalmaznak), és kiírja a sorokat az abszolút értékek növekvő sorrendjében. Az egyenlő abszolútértékű számok sorrendje tetszőleges.
- Írjon Ruby-programot palindrom.rb néven, amely beolvassa a bemenet sorait, és kiírja a palindrom sorokat. Egy string palindrom, ha a megfordítása önmaga. Segítség: beolvasás után, de még összehasonlítás előtt az
s.chomp!
hívással törölje a soremelést a string végéről. - Írjon Ruby-programot palindromlehet.rb néven, amely beolvassa a bemenet sorait, és kiírja azokat a sorokat, melyekben a betűk átvarálásával palindrom string készíthető. Egy string palindrom, ha a megfordítása önmaga. 1. segítség: beolvasás után, de még összehasonlítás előtt az
s.chomp!
hívással törölje a soremelést a string végéről. 2. segítség: rendezze a string karaktereit azs=s.split().sort.join
hívással. - Írjon Ruby-programot rendszamtobbszor.rb néven, amely beolvassa a bemenet sorait, és kiírja azokat a rendszámokat, melyek 2-szer vagy többször szerepelnek. A rendszám három betűből, egy kötőjelből és három számjegyből áll. Segítség: egy sort szavakra lehet bontani a
s.split
hívással, ami stringekből álló tömböt ad vissza. - Írjon Ruby-programot egyszer.rb néven, amely beolvassa a bemenet sorait, és csak azokat a sorokat írja ki (tetszőleges sorrendben), melyek pontosan egyszer szerepelnek.
- Melyik az a legkisebb kettőhatvány, ami már nem Fixnum? Írjon programot (marnemfixnum.rb néven), ami megadja a választ.
- Adott két objektum: a és b. Írjon Ruby-függvényt, amely visszaadja azt a legmélyebb osztályt, amely mindkét objektumnak szülőosztálya. Deklaráció:
def kozosos(a,b)
- Készítsen egy Teglalap nevű osztályt Ruby nyelven a teglalap.rb fájlba, amely egy tengélypárhuzamos téglalapot tartalmaz. Létrehozására példa:
t=Tegalalap.new(3,4,1,2)
, ahol a bal alsó sarok a (3,4), a szélessége 1, a magassága 2, tehát a jobb felső sarok a (4,6).- Tegye lehetővé a szélső koordináták lekérdezését, például
p t.llx, t.lly
a bal alsó sarkotp t.urx, t.ury
jobb felső sarkot írja ki. - Tegye lehetővé a téglalap méretének lekérdezését, például
p t.width, t.height
a szélességet, majd a magasságot írja ki. - Tegye lehetővé a téglalap méretének megváltoztatását, például
p.width=42
a téglalap szélességét, ap.height=137
pedig a téglalap magasságát változtatja meg. A változtatás a bal alsó sarkot helybenhagyja, a többi csúcsot pedig értelemszerűen mozgatja. - Tegye lehetővé az egyes csúcspontok lekérdezését:
t.ul
a bal felső,t.ur
a jobb felső,t.lr
a jobb alsó,t.ll
a bal alsó sarkot adja vissza. Egy csúcspont egy kételemű tömb:[x,y]
. - Tegye lehetővé a téglalap eltolását: a
t.eltol!(dx,dy)
hívás dx-et hozzáad minden pont x koordintájához, és dy-ot adjon hozzá minden pont y koordinátájához, at.eltol(dx,dy)
hívás pedig egy új téglalapot adjon vissza, amely t-hez képest (dx,dy)-nal van eltolva. - Tegye lehetővé a súlypont lekérdezését: a
t.sulypont
hívás adja vissza a súlypontot[cx,cy]
tömbként, at.cx
hívás adja vissza a súlypont x koordinátáját, at.cy
hívás pedig adja vissza a súlypont y koordinátáját. - Tegye lehetővé a téglalap eltolását a súlypont mozgatásával. A
t.cx=42
hívás x irányban, at.cy=137
hívás pedig irányban mozgassa a téglalapot úgy, hogy a súlypont a megadott koordinátára kerüljön. - Tegye lehetővé a téglalap nagyítását: a
t.nagyit!(m)
hívás a tömegközéppontból m-szeresére nagyítsa a téglalapot, at.nagyit(m)
hívás pedig egy új téglalapot adjon vissza, amely az eredetihez képest a fenti módon van kinagyítva. - A téglalap méretét megváltoztató
t.width=()
ést.height=()
metódusokat módosítsa úgy, hogy negatív méretet ne lehessen megadni. Definiáljon egy kivételosztályt NegativMeretHiba néven, és dobja ezt a kivételt, ha a hívó negatív méretet akar beállítani. - A téglalap létrehozásakor meghívott függvényt módosítsa úgy, hogy negatív méretű téglalapot ne lehessen megadni. Dobjon NegativMeretHiba kivételt, ha a hívó negatív méretű téglalapot akar létrehozni.
- Tegye lehetővé a téglalap szélső koordinátáinak megváltoztatását. A megvalósítandó hívások:
t.llx=1; t.lly=2; t.urx=3; t.ury=4
. Ha a hívó olyan értéket akar beállítani, hogy a téglalap mérete negatív lenne, dobjon NegativMeretHiba kivételt. - Írjon függvényt sulypontok néven, amely soronként beolvassa a bemenetet, minden sorban 4 számot várjon (elemekre bontás:
s.split
hívással), ezek a számok a bal alsó sarok x majd y koordinátája, a szélesség és a magasság. A kimenetre a téglalap súlypontját írja (soremeléssel lezárva), a sulypont metódus hívásával. A NegativMeretHiba kivételt kapja el, ekkor a kimenetre egy N betű és egy soremelés kerüljön.
- Tegye lehetővé a szélső koordináták lekérdezését, például
- Készítsen Szamegyenes néven osztályt Rubyban. A számegyenes olyan, mint egy tömb, de nem csak pozitív, hanem negatív irányban is tetszőlegesen bővíthető. Az adatok tárolásához használjon 2 tömböt: @p és @n. Például a számegyenes 5-ödik elemét @p[5]-ben, a -5-ödik elemét pedig @n[4]-ben tárolja. Kezdetben mindkét tömb legyen üres.
- Írja meg a
def [](i); ... end
metódus törzsét, mely visszaadja a számegyenes i-edik elemét. - Írja meg a
def []=(i,uj); ... end
metódus törzsét, mely a számegyenes i-edik elemét megváltoztatja uj-ra, és visszaadja uj-t. - Írja meg a
def size(); ... end
metódus törzsét, amely visszaadja a számegyenes elemeinek összszámát, vagyis a @p és @n tömbök összméretét. - Írja meg a
def tukroz!(); ... end
metódus törzsét, amely a számegyest tükrözi az origóra, vagyis minden i-re az i-edik elem helyet cserél a -i-edik elemmel.
- Írja meg a
- Készítsen KorlatosTomb néven osztályt Rubyban. A KorlatosTomb egy olyan tömb, amelynek kezdeti mérete később nem változtatható meg. Megvalósításához a @t Ruby tömböt (Array) használja.
- Írja meg a konstruktort, amely paraméterben várja azt az m méretet, melyre korlátozva van a tömb.
- Írja meg a paraméter nélküli size metódust, amely visszaadja a konstruktornak átadott m méretet.
- Írja meg a
def [](i); ... end
metódus törzsét, mely visszaadja a korlátos tömb i-edik elemét. Ha az i kívül esik az intervallumon, kivételt dob (fail
). - Írja meg a
def []=(i,uj); ... end
metódus törzsét, mely a korlátos tömb i-edik elemét megváltoztatja uj-ra, és visszaadja uj-t. Ha az i kívül esik az intervallumon, kivételt dob (fail
).
Mintafeladatok megoldásai
- Intervallum
class Intervallum attr_reader :a, :b def initialize(a, b) fail unless a <= b @a=a; @b=b end def a=(a) fail unless a <= @b @a=a end def b=(b) fail unless @a <= b @b=b end end
- Háromszög és szemétgyűjtés
- A 2. ZH 1. feladatának kicsit módosított változata:
- nincs attr_accessor, mert felesleges,
- #itt és #ott és #amott ki is írjuk, mi van az objektumokban.
- A 2. ZH 1. feladatának kicsit módosított változata:
class Haromszog def initialize(a, b, c) fail unless a+b>c and a+c>b and b+c>a @a=a; @b=b; @c=c end end class SzabalyosHaromszog < Haromszog def initialize(a) super(a, a, a) end end
begin h = Haromszog.new(3,4,5); # haromszog1 sz = SzabalyosHaromszog.new(6); # szabalyosharomszog1 h2 = SzabalyosHaromszog.new(5); # szabalyosharomszog2 # itt p '# itt h: ' + h.to_s + ' sz: ' + sz.to_s h = Haromszog.new(1,2,3); # haromszog2 rescue h2 = nil # ott p '# ott h: ' + h.to_s + ', sz: ' + sz.to_s sz = h ensure h = sz # amott p '# amott h: ' + h.to_s + ', sz: ' + sz.to_s end
- Készítünk 3 objektumot, #itt nem szabadítható fel semmi, h haromszog1 és sz szabalyosharomszog1.
- A haromszog2 létre sem jön (háromszög-egyenlőtlenség miatt)
- így h marad a korábbi, hiszen az értékadás csak a konstruktorhívás után kerül(ne) sorra,
- és átkerülünk a rescue blokkba.
- A rescue blokkban először h2 változik, emiatt #ott h marad haromszog1 és sz marad szabalyosharomszog1, ellenben szabalyosharomszog2 felszabadítható,
- később sz-be is haromszog1 kerül.
- Az ensure blokk mindig lefut,
- h-ba sz, azaz haromszog1 kerül (nem mintha eddig nem az lett volna),
- végül #amott felszabadítható szabalyosharomszog1 is.
GyakIV
A gyakIV 2007. május 25-én, pénteken 12:00-tól 16:00-ig kerül megrendezésre a K.A.62-ben. A gyakIV a teljes féléves anyagból az, ami a wikiben meg van említve.