Info2/2008tavasz/kuka
(egy szerkesztő 36 közbeeső változata nincs mutatva) | |||
1. sor: | 1. sor: | ||
− | + | A tárgy főoldala: [[info2/2008tavasz]] | |
+ | A tárgy oktatásához felhasznált, http://wiki.math.bme.hu/ -n belüli wikioldalak [http://en.wikipedia.org/wiki/GNU_Free_Documentation_License GNU FDL] licenc vagy (választás szerint) [http://hu.wikipedia.org/wiki/Creative_commons CC-BY-SA-2.0] licenc szerint szabadon használhatók és terjeszthetők. | ||
− | + | == 8. előadás (2007-04-04) == | |
− | + | === Objektum-orientált programozás === | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | 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) | ||
− | + | Osztály ''class'' (síkidom), osztálypéldány ''class instance'' = objektum ''object'' (kör, téglalap), konstruktor ''constructor'' (új objektum létrehozása), objektum azonosító (object identifier - object ID), példány változó ''instance variable'' (mely az objektum állapotát/tulajdonságait tartalmazza, pl. középpont), példány metódus ''instance method'' (), | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | === | + | === Ruby nyelv === |
− | + | A Ruby '''interpretált''', '''szkriptnyelv''' (interpretált, és minden rendszer szintű szolgáltatáshoz hozzá lehet férni). | |
− | + | 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 nem 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. | |
+ | |||
+ | Változók Konstansok és | ||
+ | Lokális Globális Példány Osztály osztály nevek | ||
− | + | valtozo $valami @nev @@osztvalt PI | |
− | + | joEjt_2 $_ @XY @@N String | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | |||
− | + | === Feltételes utasítások === | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | === | + | ==== if ==== |
− | + | Először then-nel, majd újsorral elválasztva: | |
− | + | if x==2 then x += 1 end | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
+ | if x==2 | ||
+ | x += 1 | ||
+ | end | ||
− | === | + | if x==2; x += 1 end |
− | + | ==== else ==== | |
− | + | if x==2 then x += 1 else x += 2 end | |
− | + | ||
− | + | ||
− | + | ||
− | + | if x==2 | |
+ | x += 1 | ||
+ | else | ||
+ | x += 2 | ||
+ | end | ||
− | + | ==== elsif ==== | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | if x == 1 | |
+ | "hetfo" | ||
+ | elsif x == 2 | ||
+ | "kedd" | ||
+ | elsif x == 3 then "szerda" | ||
+ | else "hetvege" | ||
+ | end | ||
− | + | ==== if kifejezésben ==== | |
− | + | x = if y == 1 | |
− | + | 3 | |
− | + | else | |
− | + | 4 | |
+ | end | ||
− | + | x = 4 | |
+ | x = 3 if y == 1 | ||
− | + | ==== unless ==== | |
− | + | unless x <= 4 | |
+ | "nagyobb, mint 4" | ||
+ | end | ||
− | + | unless x <= 4 | |
− | + | "nagyobb, mint 4" | |
− | + | else | |
− | + | "nem nagyobb" | |
− | + | end | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
+ | x = unless x <= 4 then 5 end | ||
− | + | x = 5 unless x <= 4 | |
− | /* | + | ==== case ==== |
− | + | ||
− | + | A fenti if-es példával ekvivalens a következővel (a sorvége helyett itt is lehet then vagy pontosvessző): | |
− | + | ||
+ | case x | ||
+ | when 1 | ||
+ | "hetfo" | ||
+ | when 2 | ||
+ | "kedd" | ||
+ | when 3; "szerda" | ||
+ | else "hetvege" | ||
+ | end | ||
+ | |||
+ | Ekkor valójában a következő hajtódik végre (figyeljük meg a case-egyenlőség használatát): | ||
+ | |||
+ | case | ||
+ | when 1 === x then "hetfo" | ||
+ | when 2 === x then "kedd" | ||
+ | when 3 === x then "szerda" | ||
+ | else "hetvege" | ||
+ | end | ||
+ | |||
+ | Az === néha megegyezik ==-vel, pl. a Fixnum osztályban, más osztályokban külön definiálva van a case számára: | ||
+ | |||
+ | ''tartomány használata:'' itt 'a === b' azt jelenti, hogy 'b' benne van-e az 'a' tartományban: | ||
+ | |||
+ | case x | ||
+ | when 1..5 | ||
+ | "hetkoznap" | ||
+ | when 6..7 | ||
+ | "hetvege" | ||
+ | else "rossz adat" | ||
+ | end | ||
+ | |||
+ | ''reguláris kifejezés használata:'' itt 'a === b' azt jelenti, hogy 'b' illeszkedik-e az 'a' mintára: | ||
+ | |||
+ | x = "ab" | ||
+ | case x | ||
+ | when /[a-z]+/ | ||
+ | "szoveg" | ||
+ | when /[0-9]+/ | ||
+ | "szam" | ||
+ | end | ||
+ | => "szoveg" | ||
+ | |||
+ | egy összetettebb példa (beolvassa és kiírja a sorokat addig, míg egy 'ennyi' tartalmút nem kap, a megjegyzés sorokat kihagyja): | ||
+ | |||
+ | while line=gets.chomp do | ||
+ | case line | ||
+ | when /^\s*#/ | ||
+ | next | ||
+ | when /^ennyi$/i # i = case insensitive | ||
+ | break | ||
+ | else | ||
+ | puts line | ||
+ | end | ||
+ | end | ||
+ | |||
+ | ''osztályhoz tartozás:'' a Class osztályban 'a === b' azt jelenti, hogy a 'b' az 'a' osttály példánya-e: | ||
+ | |||
+ | case x | ||
+ | when Numeric then "szam" | ||
+ | when String then "sztring" | ||
+ | else "valami mas" | ||
+ | end | ||
+ | |||
+ | A Ruby case utasításában nincs ráfutás, így nem is kell minden ágat lezárni, mint C-beli switch utasításban break-kel vagy return-nel!!! | ||
+ | |||
+ | ==== ?: ==== | ||
+ | |||
+ | Ha x == 3, y legyen 4, egyébként 5: | ||
+ | |||
+ | x = y == 3 ? 4 : 5 | ||
+ | |||
+ | === Ciklus utasítások === | ||
+ | |||
+ | ==== while, until ==== | ||
+ | |||
+ | >> x=0 | ||
+ | => 0 | ||
+ | >> while x<4 do | ||
+ | ?> x += 1 | ||
+ | >> puts x | ||
+ | >> end | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | => nil | ||
+ | |||
+ | >> x=0 | ||
+ | => 0 | ||
+ | >> until x>=4 do | ||
+ | ?> x += 1 | ||
+ | >> puts x | ||
+ | >> end | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | => nil | ||
+ | |||
+ | ==== while, until kifejezésekben ==== | ||
+ | |||
+ | >> x = 0; x += 1 while x<4; x | ||
+ | => 4 | ||
+ | |||
+ | >> x=0; x += 1 until x==4; x | ||
+ | => 4 | ||
+ | |||
+ | ==== for-in ciklus ==== | ||
+ | |||
+ | Egy tömbre és egy hash-táblára: | ||
+ | |||
+ | >> a = [1,2,3] | ||
+ | => [1, 2, 3] | ||
+ | >> for i in a | ||
+ | >> p i | ||
+ | >> end | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | => [1, 2, 3] | ||
+ | |||
+ | >> h = {"hetfo"=>1, "kedd"=>2, "vasarnap"=>7} | ||
+ | => {"hetfo"=>1, "vasarnap"=>7, "kedd"=>2} | ||
+ | >> for kulcs, ertek in h | ||
+ | >> puts "#{kulcs} a(z) #{ertek}. nap" | ||
+ | >> end | ||
+ | hetfo a(z) 1. nap | ||
+ | vasarnap a(z) 7. nap | ||
+ | kedd a(z) 2. nap | ||
+ | => {"hetfo"=>1, "vasarnap"=>7, "kedd"=>2} | ||
+ | |||
+ | |||
+ | ==== Iterátorok ==== | ||
+ | |||
+ | A times iterátor: | ||
+ | |||
+ | >> print "Mondja! Maga "; 3.times {print "mindent ketszer mond? "}; print "\n" | ||
+ | Mondja! Maga mindent ketszer mond? mindent ketszer mond? mindent ketszer mond? | ||
+ | => nil | ||
+ | |||
+ | >> a = "Mondja! Maga " | ||
+ | => "Mondja! Maga " | ||
+ | >> 3.times {a << "mindent ketszer mond? "} | ||
+ | => 3 | ||
+ | >> a | ||
+ | => "Mondja! Maga mindent ketszer mond? mindent ketszer mond? mindent ketszer mond? " | ||
+ | |||
+ | Ciklusváltozó használatával: | ||
+ | |||
+ | >> 5.times {|i| print i}; print "\n" | ||
+ | 01234 | ||
+ | => nil | ||
+ | |||
+ | Az upto, downto iterátor: | ||
+ | |||
+ | >> 0.upto(4) {|i| print i}; print "\n" | ||
+ | 01234 | ||
+ | => nil | ||
+ | >> 5.upto(8) {|i| print i}; print "\n" | ||
+ | 5678 | ||
+ | => nil | ||
+ | >> 8.downto(5) {|i| print i}; print "\n" | ||
+ | 8765 | ||
+ | => nil | ||
+ | |||
+ | ==== break, next ==== | ||
+ | |||
+ | while i<6 | ||
+ | if i == 4 then break end | ||
+ | print i | ||
+ | i += 1 | ||
+ | end | ||
+ | |||
+ | 0.upto(5) do |i| | ||
+ | if i == 4 then break 17 end # visszatérési érték is megadható, egyébként nil | ||
+ | print i | ||
+ | i += 1 | ||
+ | end | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Megszámlálható objektumok ==== | ||
+ | |||
+ | Megszámlálható objektumok (''enumerable objects''). Amely osztályok objektumaira definiálva van az each metódus. Pl. Array, Hash, Range. | ||
+ | |||
+ | Az each, map és inject iterátorok használata: | ||
+ | |||
+ | >> [1,2,3].each {|i| p i} | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | => [1, 2, 3] | ||
+ | >> [1,2,3].map {|i| i**2} | ||
+ | => [1, 4, 9] | ||
+ | >> [1,2,3].inject {|sum, i| sum + i} | ||
+ | => 6 | ||
+ | |||
+ | >> (1..4).each {|i| print i} | ||
+ | 1234=> 1..4 | ||
+ | |||
+ | >> (1..4).map {|i| i**2} | ||
+ | => [1, 4, 9, 16] | ||
+ | |||
+ | >> (1..4).inject {|s,i| s+i} | ||
+ | => 10 | ||
+ | |||
+ | Dobjuk fel 4-szer a kockát, és nézzük meg, melyik a legnagyobb dobás: | ||
+ | |||
+ | >> a = Array.new(4) {rand(6) + 1} | ||
+ | => [3, 6, 6, 4] | ||
+ | >> a.inject {|m,i| m > i ? m : i} | ||
+ | => 6 | ||
+ | |||
+ | sőt! | ||
+ | |||
+ | (Array.new(4) {rand(6) + 1}).inject {|m,i| m > i ? m : i} | ||
+ | |||
+ | A következő program egy fájlt kiír az std outputra: | ||
+ | |||
+ | File.open(filenev) do |f| | ||
+ | f.each {|sor| print sor } | ||
+ | end | ||
+ | |||
+ | Az each_with_index használata (az előző példa sorszámozott sorokkal): | ||
+ | |||
+ | >> filenev = "rrrr" | ||
+ | => "rrrr" | ||
+ | >> File.open(filenev) do |f| | ||
+ | ?> f.each_with_index do |sor,i| | ||
+ | ?> print "#{i+1}: #{sor}" | ||
+ | >> end | ||
+ | >> end | ||
+ | 1: Ez egy tesztfile | ||
+ | 2: Ez a 2. sora | ||
+ | 3: Ez meg az utso | ||
+ | => #<File:rrrr (closed)> | ||
+ | |||
+ | === Blokkok === | ||
+ | |||
+ | Blokkok csak metódushívásokat követhetnek. Vagy kapcsos zárójelek közt vagy do és end közt adhatók meg. | ||
+ | |||
+ | >> h = {:piros => 0xff0000, :zold => 0x00ff00, :kek => 0x0000ff} | ||
+ | => {:piros=>16711680, :zold=>65280, :kek=>255} | ||
+ | >> h.each {|kulcs, ertek| print "%s kodja " % kulcs, "%06x\n" % ertek} | ||
+ | piros kodja ff0000 | ||
+ | zold kodja 00ff00 | ||
+ | kek kodja 0000ff | ||
+ | => {:piros=>16711680, :zold=>65280, :kek=>255} | ||
+ | |||
+ | ==== redo/retry ==== | ||
+ | |||
+ | |||
+ | A redo csak azt a ciklust ismétli | ||
+ | puts "Mi jut eszedbe?" | ||
+ | szavak = %w(alma piros tehen) | ||
+ | valasz = szavak.collect do |szo| | ||
+ | print szo + "> " | ||
+ | valasz = gets.chop | ||
+ | if valasz.size == 0 | ||
+ | szo.upcase! | ||
+ | redo | ||
+ | end | ||
+ | valasz | ||
+ | end | ||
+ | |||
+ | A retry az egész ciklust ismétli | ||
+ | n = 5 | ||
+ | n.times do |x| | ||
+ | print x | ||
+ | if x == n-1 | ||
+ | n -= 1 | ||
+ | retry | ||
+ | end | ||
+ | end | ||
+ | |||
+ | ==== catch/throw ==== | ||
+ | |||
+ | a=[[1,nil,3],[2,3,4],[0,2,5]] | ||
+ | catch :kiugrunk do | ||
+ | 0.upto 2 do |i| | ||
+ | 0.upto 2 do |j| | ||
+ | throw :kiugrunk unless a[i][j] | ||
+ | print a[i][j] | ||
+ | end | ||
+ | print "\n" | ||
+ | end | ||
+ | end | ||
+ | print "vege\n" | ||
+ | |||
+ | === Példányváltozó -- setter === | ||
+ | |||
+ | A példányváltozó beállítása az =-végű metódussal. | ||
+ | (Az előadáson mutatott példában figyelmetlenségből nagy betűvel lett írva a class parancs!) Helyesen: | ||
+ | |||
+ | class Nev | ||
+ | attr_reader :vezetek, :kereszt | ||
+ | |||
+ | def vezetek=(vezetek) | ||
+ | if vezetek == nil or vezetek.size == 0 | ||
+ | raise ArgumentError.new('Mindenkinek van vezetekneve') | ||
+ | end | ||
+ | vezetek = vezetek.dup | ||
+ | vezetek[0] = vezetek[0].chr.capitalize | ||
+ | @vezetek = vezetek | ||
+ | end | ||
+ | |||
+ | def kereszt=(kereszt) | ||
+ | if kereszt == nil or kereszt.size == 0 | ||
+ | raise ArgumentError.new('Mindenkinek van keresztneve') | ||
+ | end | ||
+ | kereszt = kereszt.dup | ||
+ | kereszt[0] = kereszt[0].chr.capitalize | ||
+ | @kereszt = kereszt | ||
+ | end | ||
+ | |||
+ | def teljes_nev | ||
+ | "#{@vezetek} #{@kereszt}" | ||
+ | end | ||
− | + | def initialize(vezetek, kereszt) | |
− | + | self.vezetek=vezetek | |
− | + | self.kereszt=kereszt | |
− | + | end | |
+ | end | ||
− | + | === Néhány példaprogram === | |
− | + | Matmul Ruby nyelven: | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | 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'' ciklust nem véletlenül használunk, mivel Rubyban nincs ''for'' ciklus | ||
+ | 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 | ||
− | + | Objektum-orientáltan kezdtünk programozni Ruby nyelven, a Sikidom, BBox és Kor osztályok kerültek fel a táblára. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | 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 | ||
− | + | Egy sudoku megoldás (Fischer Richárd megoldása alapján): | |
− | + | ||
− | + | # puts "Add meg a filenevet! " | |
− | + | # filenev=gets.chomp! | |
− | return | + | filenev = "sudoku1" |
+ | a=Array.new(9) {[]} | ||
+ | File.open(filenev) do |f| | ||
+ | f.each_with_index do |sor,i| | ||
+ | 0.upto(8) {|j| a[i][j]= if sor[j]>48 then sor[j].chr.to_i else 0 end} | ||
+ | end | ||
+ | end | ||
+ | |||
+ | vanuj=true | ||
+ | while vanuj do | ||
+ | vanuj=false | ||
+ | 0.upto(8) do |i| | ||
+ | 0.upto(8) do |j| | ||
+ | if a[i][j] == 0 | ||
+ | d=(1..9).to_a | ||
+ | 0.upto(8) do |k| | ||
+ | d.delete(a[i][k]) | ||
+ | d.delete(a[k][j]) | ||
+ | end | ||
+ | 0.upto(2) do |e| | ||
+ | 0.upto(2) do |f| | ||
+ | d.delete(a[i/3*3+e][j/3*3+f]) | ||
+ | end | ||
+ | end | ||
+ | if d.size==1 | ||
+ | a[i][j]=d[0] | ||
+ | vanuj=true | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | 0.upto(8) do |i| | ||
+ | 0.upto(8) do |j| | ||
+ | print a[i][j] | ||
+ | end | ||
+ | print "\n" | ||
+ | end | ||
+ | |||
+ | Egy gráfokat kezelő osztály: | ||
+ | |||
+ | class Adjacencia < Array | ||
+ | attr_reader :adj | ||
+ | def initialize | ||
+ | @adj = [] | ||
+ | end | ||
+ | |||
+ | def [](x,y) | ||
+ | x,y = y,x if x > y | ||
+ | raise IndexError if x==y | ||
+ | @adj[ (y*y-y)/2 + x ] | ||
+ | end | ||
+ | |||
+ | def []=(x,y,e) | ||
+ | x,y = y,x if x > y | ||
+ | raise IndexError if x==y | ||
+ | @adj[ (y*y-y)/2 + x ] = e | ||
+ | end | ||
+ | end | ||
+ | |||
+ | class Graf | ||
+ | attr_reader :adj | ||
+ | def initialize( *elek ) | ||
+ | @adj = Adjacencia.new | ||
+ | @csucsok = 0 | ||
+ | for e in elek | ||
+ | @adj[e[0],e[1]] = 1 | ||
+ | @csucsok = [@csucsok,e[0],e[1]].max | ||
+ | end | ||
+ | end | ||
+ | |||
+ | def [](x,y) | ||
+ | @adj[x,y] | ||
+ | end | ||
+ | |||
+ | def add x,y | ||
+ | @adj[x,y]=1 | ||
+ | @csucsok = [@csucsok,x,y].max | ||
+ | end | ||
+ | |||
+ | def fok(x) | ||
+ | (0..@csucsok).inject(0) {|s,i| x!=i && @adj[x,i] ? s+1 : s } | ||
+ | end | ||
+ | |||
+ | def each_csucs | ||
+ | (0..@csucsok).each {|v| yield v} | ||
+ | end | ||
+ | |||
+ | def each_el | ||
+ | for i in 0...@csucsok | ||
+ | for j in i+1..@csucsok | ||
+ | yield i,j if self[i,j] | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | def osszefuggo? | ||
+ | c = @csucsok | ||
+ | volt = [] | ||
+ | lesz = [c] | ||
+ | for i in 0...@csucsok | ||
+ | lesz << i if self[i,c] | ||
+ | volt << i if self[i,c] | ||
+ | end | ||
+ | while !volt.empty? | ||
+ | v = volt.shift | ||
+ | self.each_el do |x,y| | ||
+ | if x==v || y==v | ||
+ | z = x==v ? y : x | ||
+ | if !lesz.include? z | ||
+ | lesz << z | ||
+ | volt << z | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | lesz.size <= @csucsok ? false : true | ||
+ | end | ||
+ | def euler_kor? | ||
+ | return false if !osszefuggo? | ||
+ | paratlan = 0 | ||
+ | each_csucs do |i| | ||
+ | if fok(i) % 2 == 1 | ||
+ | paratlan += 1 | ||
+ | end | ||
+ | end | ||
+ | paratlan == 0 | ||
+ | end | ||
+ | |||
+ | def euler_ut? | ||
+ | return false if !osszefuggo? | ||
+ | paratlan = 0 | ||
+ | each_csucs do |i| | ||
+ | if fok(i) % 2 == 1 | ||
+ | paratlan += 1 | ||
+ | end | ||
+ | end | ||
+ | paratlan == 2 | ||
+ | end | ||
+ | |||
+ | def euler? | ||
+ | return false if !osszefuggo? | ||
+ | paratlan = 0 | ||
+ | each_csucs do |i| | ||
+ | if fok(i) % 2 == 1 | ||
+ | paratlan += 1 | ||
+ | end | ||
+ | end | ||
+ | paratlan <= 2 | ||
+ | end | ||
+ | |||
+ | def show | ||
+ | (0...@csucsok).each do |i| | ||
+ | (0..@csucsok).each do |j| | ||
+ | print i>=j ? " " : (@adj[i,j] ? @adj[i,j] : 0) | ||
+ | end | ||
+ | print "\n" | ||
+ | end | ||
+ | end | ||
+ | end |
A lap jelenlegi, 2008. május 9., 18:53-kori változata
A tárgy főoldala: info2/2008tavasz A tárgy oktatásához felhasznált, http://wiki.math.bme.hu/ -n belüli wikioldalak GNU FDL licenc vagy (választás szerint) CC-BY-SA-2.0 licenc szerint szabadon használhatók és terjeszthetők.
Tartalomjegyzék |
8. előadás (2007-04-04)
Objektum-orientált programozás
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)
Osztály class (síkidom), osztálypéldány class instance = objektum object (kör, téglalap), konstruktor constructor (új objektum létrehozása), objektum azonosító (object identifier - object ID), példány változó instance variable (mely az objektum állapotát/tulajdonságait tartalmazza, pl. középpont), példány metódus instance method (),
Ruby nyelv
A Ruby interpretált, szkriptnyelv (interpretált, és minden rendszer szintű szolgáltatáshoz hozzá lehet férni).
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 nem 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.
Változók Konstansok és Lokális Globális Példány Osztály osztály nevek valtozo $valami @nev @@osztvalt PI joEjt_2 $_ @XY @@N String
Feltételes utasítások
if
Először then-nel, majd újsorral elválasztva:
if x==2 then x += 1 end
if x==2 x += 1 end
if x==2; x += 1 end
else
if x==2 then x += 1 else x += 2 end
if x==2 x += 1 else x += 2 end
elsif
if x == 1 "hetfo" elsif x == 2 "kedd" elsif x == 3 then "szerda" else "hetvege" end
if kifejezésben
x = if y == 1 3 else 4 end
x = 4 x = 3 if y == 1
unless
unless x <= 4 "nagyobb, mint 4" end
unless x <= 4 "nagyobb, mint 4" else "nem nagyobb" end
x = unless x <= 4 then 5 end
x = 5 unless x <= 4
case
A fenti if-es példával ekvivalens a következővel (a sorvége helyett itt is lehet then vagy pontosvessző):
case x when 1 "hetfo" when 2 "kedd" when 3; "szerda" else "hetvege" end
Ekkor valójában a következő hajtódik végre (figyeljük meg a case-egyenlőség használatát):
case when 1 === x then "hetfo" when 2 === x then "kedd" when 3 === x then "szerda" else "hetvege" end
Az === néha megegyezik ==-vel, pl. a Fixnum osztályban, más osztályokban külön definiálva van a case számára:
tartomány használata: itt 'a === b' azt jelenti, hogy 'b' benne van-e az 'a' tartományban:
case x when 1..5 "hetkoznap" when 6..7 "hetvege" else "rossz adat" end
reguláris kifejezés használata: itt 'a === b' azt jelenti, hogy 'b' illeszkedik-e az 'a' mintára:
x = "ab" case x when /[a-z]+/ "szoveg" when /[0-9]+/ "szam" end => "szoveg"
egy összetettebb példa (beolvassa és kiírja a sorokat addig, míg egy 'ennyi' tartalmút nem kap, a megjegyzés sorokat kihagyja):
while line=gets.chomp do case line when /^\s*#/ next when /^ennyi$/i # i = case insensitive break else puts line end end
osztályhoz tartozás: a Class osztályban 'a === b' azt jelenti, hogy a 'b' az 'a' osttály példánya-e:
case x when Numeric then "szam" when String then "sztring" else "valami mas" end
A Ruby case utasításában nincs ráfutás, így nem is kell minden ágat lezárni, mint C-beli switch utasításban break-kel vagy return-nel!!!
?:
Ha x == 3, y legyen 4, egyébként 5:
x = y == 3 ? 4 : 5
Ciklus utasítások
while, until
>> x=0 => 0 >> while x<4 do ?> x += 1 >> puts x >> end 1 2 3 4 => nil
>> x=0 => 0 >> until x>=4 do ?> x += 1 >> puts x >> end 1 2 3 4 => nil
while, until kifejezésekben
>> x = 0; x += 1 while x<4; x => 4
>> x=0; x += 1 until x==4; x => 4
for-in ciklus
Egy tömbre és egy hash-táblára:
>> a = [1,2,3] => [1, 2, 3] >> for i in a >> p i >> end 1 2 3 => [1, 2, 3]
>> h = {"hetfo"=>1, "kedd"=>2, "vasarnap"=>7} => {"hetfo"=>1, "vasarnap"=>7, "kedd"=>2} >> for kulcs, ertek in h >> puts "#{kulcs} a(z) #{ertek}. nap" >> end hetfo a(z) 1. nap vasarnap a(z) 7. nap kedd a(z) 2. nap => {"hetfo"=>1, "vasarnap"=>7, "kedd"=>2}
Iterátorok
A times iterátor:
>> print "Mondja! Maga "; 3.times {print "mindent ketszer mond? "}; print "\n" Mondja! Maga mindent ketszer mond? mindent ketszer mond? mindent ketszer mond? => nil
>> a = "Mondja! Maga " => "Mondja! Maga " >> 3.times {a << "mindent ketszer mond? "} => 3 >> a => "Mondja! Maga mindent ketszer mond? mindent ketszer mond? mindent ketszer mond? "
Ciklusváltozó használatával:
>> 5.times {|i| print i}; print "\n" 01234 => nil
Az upto, downto iterátor:
>> 0.upto(4) {|i| print i}; print "\n" 01234 => nil >> 5.upto(8) {|i| print i}; print "\n" 5678 => nil >> 8.downto(5) {|i| print i}; print "\n" 8765 => nil
break, next
while i<6 if i == 4 then break end print i i += 1 end
0.upto(5) do |i| if i == 4 then break 17 end # visszatérési érték is megadható, egyébként nil print i i += 1 end
Megszámlálható objektumok
Megszámlálható objektumok (enumerable objects). Amely osztályok objektumaira definiálva van az each metódus. Pl. Array, Hash, Range.
Az each, map és inject iterátorok használata:
>> [1,2,3].each {|i| p i} 1 2 3 => [1, 2, 3] >> [1,2,3].map {|i| i**2} => [1, 4, 9] >> [1,2,3].inject {|sum, i| sum + i} => 6
>> (1..4).each {|i| print i} 1234=> 1..4
>> (1..4).map {|i| i**2} => [1, 4, 9, 16]
>> (1..4).inject {|s,i| s+i} => 10
Dobjuk fel 4-szer a kockát, és nézzük meg, melyik a legnagyobb dobás:
>> a = Array.new(4) {rand(6) + 1} => [3, 6, 6, 4] >> a.inject {|m,i| m > i ? m : i} => 6
sőt!
(Array.new(4) {rand(6) + 1}).inject {|m,i| m > i ? m : i}
A következő program egy fájlt kiír az std outputra:
File.open(filenev) do |f| f.each {|sor| print sor } end
Az each_with_index használata (az előző példa sorszámozott sorokkal):
>> filenev = "rrrr" => "rrrr" >> File.open(filenev) do |f| ?> f.each_with_index do |sor,i| ?> print "#{i+1}: #{sor}" >> end >> end 1: Ez egy tesztfile 2: Ez a 2. sora 3: Ez meg az utso => #<File:rrrr (closed)>
Blokkok
Blokkok csak metódushívásokat követhetnek. Vagy kapcsos zárójelek közt vagy do és end közt adhatók meg.
>> h = {:piros => 0xff0000, :zold => 0x00ff00, :kek => 0x0000ff} => {:piros=>16711680, :zold=>65280, :kek=>255} >> h.each {|kulcs, ertek| print "%s kodja " % kulcs, "%06x\n" % ertek} piros kodja ff0000 zold kodja 00ff00 kek kodja 0000ff => {:piros=>16711680, :zold=>65280, :kek=>255}
redo/retry
A redo csak azt a ciklust ismétli
puts "Mi jut eszedbe?" szavak = %w(alma piros tehen) valasz = szavak.collect do |szo| print szo + "> " valasz = gets.chop if valasz.size == 0 szo.upcase! redo end valasz end
A retry az egész ciklust ismétli
n = 5 n.times do |x| print x if x == n-1 n -= 1 retry end end
catch/throw
a=[[1,nil,3],[2,3,4],[0,2,5]] catch :kiugrunk do 0.upto 2 do |i| 0.upto 2 do |j| throw :kiugrunk unless a[i][j] print a[i][j] end print "\n" end end print "vege\n"
Példányváltozó -- setter
A példányváltozó beállítása az =-végű metódussal. (Az előadáson mutatott példában figyelmetlenségből nagy betűvel lett írva a class parancs!) Helyesen:
class Nev attr_reader :vezetek, :kereszt def vezetek=(vezetek) if vezetek == nil or vezetek.size == 0 raise ArgumentError.new('Mindenkinek van vezetekneve') end vezetek = vezetek.dup vezetek[0] = vezetek[0].chr.capitalize @vezetek = vezetek end def kereszt=(kereszt) if kereszt == nil or kereszt.size == 0 raise ArgumentError.new('Mindenkinek van keresztneve') end kereszt = kereszt.dup kereszt[0] = kereszt[0].chr.capitalize @kereszt = kereszt end def teljes_nev "#{@vezetek} #{@kereszt}" end def initialize(vezetek, kereszt) self.vezetek=vezetek self.kereszt=kereszt end end
Néhány példaprogram
Matmul Ruby nyelven:
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 ciklust nem véletlenül használunk, mivel Rubyban nincs for ciklus 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
Objektum-orientáltan kezdtünk programozni Ruby nyelven, a Sikidom, BBox és Kor osztályok kerültek fel a táblára.
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
Egy sudoku megoldás (Fischer Richárd megoldása alapján):
# puts "Add meg a filenevet! " # filenev=gets.chomp! filenev = "sudoku1" a=Array.new(9) {[]} File.open(filenev) do |f| f.each_with_index do |sor,i| 0.upto(8) {|j| a[i][j]= if sor[j]>48 then sor[j].chr.to_i else 0 end} end end vanuj=true while vanuj do vanuj=false 0.upto(8) do |i| 0.upto(8) do |j| if a[i][j] == 0 d=(1..9).to_a 0.upto(8) do |k| d.delete(a[i][k]) d.delete(a[k][j]) end 0.upto(2) do |e| 0.upto(2) do |f| d.delete(a[i/3*3+e][j/3*3+f]) end end if d.size==1 a[i][j]=d[0] vanuj=true end end end end end 0.upto(8) do |i| 0.upto(8) do |j| print a[i][j] end print "\n" end
Egy gráfokat kezelő osztály:
class Adjacencia < Array attr_reader :adj def initialize @adj = [] end def [](x,y) x,y = y,x if x > y raise IndexError if x==y @adj[ (y*y-y)/2 + x ] end def []=(x,y,e) x,y = y,x if x > y raise IndexError if x==y @adj[ (y*y-y)/2 + x ] = e end end class Graf attr_reader :adj def initialize( *elek ) @adj = Adjacencia.new @csucsok = 0 for e in elek @adj[e[0],e[1]] = 1 @csucsok = [@csucsok,e[0],e[1]].max end end def [](x,y) @adj[x,y] end def add x,y @adj[x,y]=1 @csucsok = [@csucsok,x,y].max end def fok(x) (0..@csucsok).inject(0) {|s,i| x!=i && @adj[x,i] ? s+1 : s } end def each_csucs (0..@csucsok).each {|v| yield v} end def each_el for i in 0...@csucsok for j in i+1..@csucsok yield i,j if self[i,j] end end end def osszefuggo? c = @csucsok volt = [] lesz = [c] for i in 0...@csucsok lesz << i if self[i,c] volt << i if self[i,c] end while !volt.empty? v = volt.shift self.each_el do |x,y| if x==v || y==v z = x==v ? y : x if !lesz.include? z lesz << z volt << z end end end end lesz.size <= @csucsok ? false : true end def euler_kor? return false if !osszefuggo? paratlan = 0 each_csucs do |i| if fok(i) % 2 == 1 paratlan += 1 end end paratlan == 0 end def euler_ut? return false if !osszefuggo? paratlan = 0 each_csucs do |i| if fok(i) % 2 == 1 paratlan += 1 end end paratlan == 2 end def euler? return false if !osszefuggo? paratlan = 0 each_csucs do |i| if fok(i) % 2 == 1 paratlan += 1 end end paratlan <= 2 end def show (0...@csucsok).each do |i| (0..@csucsok).each do |j| print i>=j ? " " : (@adj[i,j] ? @adj[i,j] : 0) end print "\n" end end end