Házi megbeszélése
1. feladat
> | l:=[]:x:=1:
while x<10^6 do l:=[op(l),x]; x:=x*2; end do: l; |
Egy kicsit egyszerűbb megoldás, nem halmazzal, hanem csak kiíratással:
> | x:=1:
while x<10^6 do print(x); x:=x*2; end do: |
Illetve:
> | 2^19 > 10^6; |
> | 2^20 > 10^6; |
Ezért:
> | {seq(2^i,i=1..19)}; |
2. feladat
> | [seq(3^n mod 39,n=1..4)]; |
Körbeért, ezért a maradékok
> | {op(%)}; |
Tökéletees, ha valaki 0-tól indította:
> | {seq(3^n mod 39,n=0..3)}; |
3. feladat
Persze jobban örülnék a listás megoldásnak, de még ez is jó.
> | for i from 1 to 1000 do
if i mod 7 = 4 and i mod 3 =2 then print( i ); end if; end do; |
Illetve tanuljunk újat: a select parancs első paramétere egy igazzal (true-val) vagy hamissal (false-szal) visszatérő függvény, második paramétere egy lista. Csak azon elemeket hagyja meg a listában, amelyekre a megadott függvény igazzal tér vissza.
> | select(x -> if x mod 7 = 4 and x mod 3 = 2 then true; else false; end if, [seq(i,i=1..1000)]); |
4. feladat
Az előző megoldások bármelyike jó, sőt még egyszerűbben is lehet. Nem íratom ki, sok van, csak 1000-ig:
> | select(x -> isprime(x) and isprime(x+2), [seq(i,i=1..1000)]); |
5. feladat
> | n:=1:
while n! < 11^n do n:=n+1; od: n; |
Pár plusz trükk
A select-eket lehet egymásba ágyazni.
> | select(i -> isprime(i) and isprime(i+2), select(k -> k mod 2 = 1, [seq(2
* k + 1, k=1..10^3 / 2 - 1)])); |
Ami csak a páratlanokat nézi és nem néz meg kétszer minden prímet, hogy az-e (ami ugye drága művelet):
> | p0:=false:
n:=3: l:=[]: while n < 10^3 do p:=isprime(n): if (p and p0) then l:=[op(l), n-2]: fi: p0 := p: n := n+2: od: l ; |
Műveletek mátrixokkal
Mátrix-okról még nem tanultatok túl sokat, így ez egy plusz rész. A későbbiekben még jól jöhet.
Betöltjük a lineáris algebrával foglalkozó csomagot.
> | with(LinearAlgebra); |
Létrehozunk egy mátrix-ot.
> | A:=<<1,2,3>|<3,4,5>|<1,3,10>>; |
> | MatrixInverse(A); |
> | B:=Matrix([[1,2],[3,a]]); |
> | matrix(3,3,[2,3,6,3,3,6,6,6,6]); |
A B mátrix-ot négyzetre emeljük.
> | MatrixPower(B,2); |
A B mátrix k-adik hatványa:
> | MatrixPower(B,k); |
> | eval(%,{a=4,k=5}); |
Transzponált:
> | Transpose(B); |
> | Determinant(B); |
> | MatrixInverse(B); |
> | A:=<<1,2>|<4,5>>; |
> | A[1,2]; |
Mátrix-ok szorzata:
> | evalm(A&*B); |
A mátrix elemeit így érjük el. Módosíthatjuk is őket.
> | A[1,2]:=5; |
> | A; |
> | evalm(A&*B); |
> | evalm(A&*B+3*A); |
> | a:=Vector([10,20]); |
> | evalm(A&*a); |
> | Eigenvalues(A); |
> | Eigenvectors(A); |
Plot
A plots csomag betöltése után sokkal több függvényt használhatunk rajzolásra.
> | with(plots); |
Minden paraméter nélkül a plot megpróbálja intelligensen kirajzolni a függvényt. Ez nem mindig a legjobb.
> | plot(tan(x),x=-2*Pi..2*Pi); |
A view paraméterrel adjuk meg a megjelenítendő téglalap sarkait, a discont=true hatására nem köti össze a szomszédos pontokat (így nem lesz egy függőleges egyenes a szakadási pontokban).
> | plot(tan(x),x=-2*Pi..2*Pi,view=[-2*Pi..2*Pi,-3..3],discont=true); |
A contourplot a megadott függvény szintvonalait ábrázolja.
> | contourplot(sin(x*y),x=-3..3,y=-3..3); |
Ugyanez 3d-ben:
> | contourplot3d(exp(-(2*x^2+y^2)/2),x=-2..2,y=-2..2); |
A plot3d két paraméterrel dolgozik. A megadott függvény mondja meg, hogy az adott (x,y) pontban milyen magas legyen a pont. Minden rajzolás paraméterezhető, pl. ebben az esetben így értük el, hogy a szín is függjön a paraméterektől, és legye az ábrának neve.
> | plot3d(0.3*x^3-x+y^2, x=-2..2, y=-2..2, axes=box, color=0.3*x^3-x+y^2, title=Köbös); |
A lehetséges opciók listája: a plot3d leírásában alul kattintsunk a plot3d[options] -ra,
> | ?plot3d; |
vagy egyből menjünk a plot3d[options]-ra
> | ?plot3d[options]; |
Programozás
Legnagyobb közös osztó
Az alábbi függvény euklideszi algoritmussal számol legnagyobb közös osztót. A bemenő a és b paraméter után ::integer áll, amely hatására a bemenő paraméternek csak egész számot fogad el. Enélkül a programunk lefutna sajatgcd(Pi,"abc") bemenetre is, és valószínűleg csak a mod-nál futna le.
Egy függvény visszatérési értéke az utolsó számolt képlet eredménye, vagy a return parancs után megadott rész. A return használata esetén azonnal megszakad a program futása, és a megadott értékkel tér vissza.
> | sajatgcd:=proc(a::integer, b::integer)
if b=0 then a; else sajatgcd(b,a mod b); end if; end proc; |
> | sajatgcd(20,5); |
> | sajatgcd(100,60); |
Fibonacci
Fibonacci sorozat n. tagját kiszámoló eljárás. Rekurzívan oldjuk meg. Ha n >= 3, akkor meghívjuk a fib függvényt az n-1 és n-2 helyen, és ennek összegével térünk vissza. Az option remember segítségével megjegyzi a már kiszámolt értékeket, így lényegesen gyorsabb lesz a program. Így lineáris lesz a futási idő, enélkül pedig exponenciális.
> | fib:=proc(n::integer)
option remember; if n < 3 then return 1; fi; fib(n-1)+fib(n-2); end proc; |
> | fib(10); |
Más megoldás rekurzív hívás nélkül:
> | fibi := proc(n::integer)
local n0, a, b, r: a := 1: b := 1: r := 1: n0 := 2: while n0 < n do r := a + b: b := a: a := r: n0 := n0 + 1: od: r; end; |
> | fibi(10); |
Áttérés kettes számrendszerre
A bemenő paramétert szeretnék kettes számrendszerre váltani. Például 6-ra [1,1,0]-t szeretnénk kapni, mert 4*1+2*1+1*0 = 6. A legnagyobb kettőhatvány, amely még nem nagyobb 6-nál, az a 4. 4-et úgy tudjuk kifejezni 6-tal, hogy 4=2^floor(log(6)/log(2)), ahol a floor az alsó egészet jelenti. Ezután minden lépésben levonjuk a megmaradó számból az épp vizsgált 2-hatványt ha tudjuk, ekkor egy 1-est teszünk az r lista végére, egyébként 0-t. Majd felezzük a 2-hatványunkat. Az elején van egy nn változó, amit utána át is másolunk n-re. Így nem az nn-et írjuk felül a munkánk során.
A local után fel kell sorolni minden használt, nem paraméterként kapott változót.
> | kettes:=proc(nn::integer)
local r,x,n; r:=[]; n:=nn; x:=2^floor(log(n)/log(2)); while(x>=1) do if n >= x then r := [op(r),1]; n := n-x; else r := [op(r),0]; end if; x := x/2; end do: r; end proc; |
> | kettes(2); |
> | kettes(1); |
> | kettes(6); |
> | kettes(7); |
> | kettes(65536); |
Leghosszabb tiszta fejsorozat
Vegyünk 100 hosszú egy listát, amelyben 0-ák és 1-esek vannak. Hogy ne nekünk kelljen ilyet írni, csinálhatunk ilyet véletlenszerűen:
> | l:=[seq(rand() mod 2,i=1..100)]; |
Számoljuk meg első körben, hogy hány 1-es van benne.
> | s:=0:
for i from 1 to nops(l) do if l[i]=1 then s := s+1; end if; end do; s; |
Ha az 1-est fejnek, a 0-t pedig írásnak vesszük, akkor megszámolhatjuk a leghosszabb tiszta (egymás után jövő) fejsorozat hosszát. A k változóban tároljuk az éppen addig talált leghosszabb sorozat hosszát, és az m-ben tároljuk a maximumát a k értékeknek.
> | m:=0:
k:=0: for i from 1 to nops(l) do if l[i]=1 then k:=k+1; else k:=0; end if; m:=max(m,k); end do: m; |
Ugyanezt írjuk meg függvényben. Az előny az, hogy ezután könnyen meg tudjuk hívni többször.
> | tiszta:=proc(n::integer)
local l,i,k,m; l:=[seq(rand() mod 2,i=1..n)]; m:=0: k:=0: for i from 1 to n do if l[i]=1 then k:=k+1; else k:=0; end if; m:=max(m,k); end do; m; end proc; |
> | tiszta(100); |
> | tiszta(100); |
> | with(plots): |
Warning, the name changecoords has been redefined
Az ábrát elnézve: az esetek többségében 5-6-7-8 tiszta fejsorozat a leggyakoribb.
> | listplot(sort( [seq(tiszta(100),i=1..1000)] )); |
> |