Az elmĂșlt Ă©vekben mĂĄr többször prĂłbĂĄlkoztam az Advent of Code teljesĂtĂ©sĂ©vel. A decemberi idĆszak valĂłban a lecsendesĂŒlĂ©s idĆszaka lehetne, ha nem ekkor lennĂ©nek a ZHk, pĂłtZHk, beadandĂłk, elsĆ vizsgĂĄk. S ez nem csak a diĂĄkok, hanem a tanĂĄrjaik szĂĄmĂĄra is kihĂvĂĄst jelent, hisz illene mindent idĆre ĂĄtolvasni, kijavĂtani. Ennek ellenĂ©re 2018-ban sikerĂŒlt Python-ban, majd 2021-ben Scala-ban teljesĂteni a kihĂvĂĄst, igaz mĂĄsodjĂĄra csak pĂĄr hetes kĂ©sĂ©ssel. 18-ban a Python mellett prĂłbĂĄltam Racket-ben is megoldani a feladatokat, hogy alaposabban megismerjek egy funkcionĂĄlis nyelvet, de valĂłjĂĄban ez csak 21-ben jött össze a Scala-val. Több Ă©vig ott mocorgott bennem, hogy illene egy vektor alapĂș nyelvet is elsajĂĄtĂtani. ElĂ©g sokat töprengtem azon, hogy az APL, a J, a K Ă©s a Q közĂŒl melyikkel lenne Ă©rdemes prĂłbĂĄlkozni; vĂ©gĂŒl az egyszerƱsĂ©ge miatt nĂĄlam a K gyĆzött. Persze ez azt is jelenti, hogy pĂĄr esetben majd körĂŒlmĂ©nyesebben lehet ugyanazt megfogalmazni, mint mĂĄs nyelveken lehetne, de ha mĂĄr eddig is zsĂĄkbafutĂĄsrĂłl volt szĂł, akkor mĂ©g egy megszorĂtĂĄs mĂĄr nem sokat ad hozzĂĄ.
MĂ©g a nyolcvanas Ă©vekben hozzĂĄszoktam a programozĂĄsi nyelvek nyelvjĂĄrĂĄsaihoz, a legjellemzĆbb a ZX Spectrum Ă©s Commodore C64 BASIC-je közti eltĂ©rĂ©s volt, mert szinte minden egyes programsort ĂĄt kellett Ărni, hogy mƱködjön. AztĂĄn a szabvĂĄnyosabbnak tekinthetĆ eszközökkel Ă©s programnyelvekkel ez szinte eltƱnt, a Turbo Pascal, a C, a Java szabvĂĄnyos, egysĂ©ges volt, az egyik helyen megĂrt program minden mĂłdosĂtĂĄs nĂ©lkĂŒl futott a mĂĄsik gĂ©pen is. A visszafele kompatibilitĂĄs elvĂĄrt tulajdonsĂĄg szinte mindenĂŒtt, van is belĆle nagy galiba, ha nem teljesĂŒl - lĂĄsd a Python 2-3 vĂĄltĂĄst -, de az sem tĂșlsĂĄgosan jĂł, ha ez fĂ©kezi az adott nyelvet, mint pĂ©ldĂĄul a Java esetĂ©n.
Arthur Whitney - a K programozĂĄsi nyelv atyja - szĂĄmĂĄra ez sose volt szempont, a K kĂŒlönfĂ©le verziĂłi tekinthetĆek egymĂĄs nyelvjĂĄrĂĄsainak. Ahogy az igĂ©nyek vĂĄltoznak, Ășgy vĂĄltozott a nyelv is, kerĂŒlt bele Ășjabb Ă©s Ășjabb eszköz. A rossznyelvek szerint az Ășjabb verziĂłk megĂrĂĄsĂĄhoz egy sort sem hasznĂĄl fel a rĂ©gi kĂłdokbĂłl, mindig mindent a nullĂĄrĂłl kezd. MĂĄr a kilencedik verziĂłnĂĄl tartunk, de mivel ezer dollĂĄrokban mĂ©rhetĆ Ă¶sszegĂ©rt lehet hozzĂĄfĂ©rni az egyes variĂĄnsokhoz, elĂ©ggĂ© elterjedt a "generikusok" hasznĂĄlata, amikor fĂŒggetlen szemĂ©lyek az egyes verziĂłkra nagyon hasonlĂtĂł variĂĄnsokat kĂ©szĂtenek, jellemzĆen mĂĄr nyĂlt forrĂĄssal. Ezek közĂŒl többet is kiprĂłbĂĄltam, szĂĄmomra a legegyszerƱbb volt a Kona variĂĄnst mƱködĂ©sre bĂrni (Linux, OSX Ă©s Windows alatt is), Ă©s ennĂ©l tudom leginkĂĄbb kihasznĂĄlni a mĂĄr meglĂ©vĆ K2 leĂrĂĄsokat illetve K oktatĂłanyagokat.
MiutĂĄn akadĂĄlyoztatĂĄs miatt nem tudtam idĆben elkezdeni a kihĂvĂĄst, nem az a cĂ©lom, hogy karĂĄcsonyra önĂĄllĂłan vĂ©gezzek az összes feladattal, hanem az, hogy rĂĄĂ©rezzek a vektor-alapĂș programozĂĄs ĂzĂ©re, megismerjem a Kona lehetĆsĂ©geit Ă©s korlĂĄtait, s ha lehet, vĂ©ges idĆn belĂŒl egyedĂŒl oldjam meg a feladatot; s nem titkolt cĂ©lom az sem, hogy mĂĄs figyelmĂ©t is felhĂvjam erre a nyelvre, s magyar nyelvƱ oktatĂłanyagot biztosĂtsak szĂĄmĂĄra. MiutĂĄn elsĆdleges cĂ©l a tanulĂĄs/tanĂtĂĄs, emiatt ha minden kötĂ©l szakad, akkor rĂĄfanyalodok mĂĄsok - mint pĂ©ldĂĄul ngn/k vagy qbists - megoldĂĄsaira, amelyek persze vĂ©letlenĂŒl sem Kona-ban ĂrĂłdtak, de utat mutathatnak a sajĂĄt megoldĂĄshoz, s megmutathatnak pĂĄr trĂŒkköt, melyekre nem biztos, hogy egyedĂŒl rĂĄjönnĂ©k.
SzeretnĂ©m, ha mindaz megragadna bennem, amit egyszer sikerĂŒlt összehoznom, ezĂ©rt magamnak is leĂrom, hogy milyen eszközöket hasznĂĄlok, azokat milyen nĂ©ven talĂĄlom meg a manual-ban, s hogyan jutok elĆre lĂ©pĂ©srĆl lĂ©pĂ©sre. Ha ez mĂĄsnak is segĂt, az meg kĂ©sz nyeresĂ©g.
Az input formĂĄtuma a következĆ:
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
A feladat nem mĂĄs, mint az ĂŒres sorokkal elvĂĄlasztott rĂ©szeket összegezni, majd kivĂĄlasztani a maximĂĄlist.
Az input beolvasåsa igen egyszerƱen megy (load text file) 0:
test01.txt`, majd mivel minden Ă©rtĂ©k egy szĂĄm, sorokat konvertĂĄljuk egybĆl egĂ©szekkĂ© is (Format) 0$. Ezzel csak az a baj, hogy ez az ĂŒres sorokkal nem tud mit kezdeni, s ezeknĂ©l hibĂĄt jelez (0N). Ez az ami pont jĂł lesz nekĂŒnk, ugyanis ezeket tekintjĂŒk majd elvĂĄlasztĂĄsnak. Annak Ă©rdekĂ©ben, hogy az elsĆ sorunk is megmaradjon, az egĂ©sz input elĂ© berakunk mĂ©g egy ilyen jelzĂ©st 0N, s a könnyebb hivatkozĂĄs Ă©rdekĂ©ben ezt tĂĄroljuk egy vĂĄltozĂłban.
b:0N,0$0:`test01.txt
Azt, hogy hol is talĂĄlhatjuk meg az elvĂĄlasztĂłkat, az egyenlĆsĂ©ggel (equal) hatĂĄrozzuk meg: 0N=b, s mivel itt egy Ă©rtĂ©ket hasonlĂtunk össze egy listĂĄval, ennek eredmĂ©nye egy bitlista lesz, ott kapunk egyest, ahol az egyenlĆsĂ©g teljesĂŒl, s mindenĂŒtt mĂĄsutt nullĂĄt. Ez kivĂĄlĂł inputja lesz a where (&) operĂĄtornak, amely ilyen esetben összegyƱjti az egyesek indexeit. A Drop/Cut operĂĄtornak listĂĄt adva bal argumentumkĂ©nt a Cut mƱveletet hajtja vĂ©gre, azaz az inputbĂłl szĂĄrmazĂł listĂĄnkat allistĂĄk listĂĄjĂĄvĂĄ alakĂtja. Ez mĂĄr majdnem jĂł is lenne, de az elvĂĄlasztĂłink ott talĂĄlhatĂłak minden egyes sor elejĂ©n, amitĆl azĂ©rt jĂł lenne megszabadulni. Ha a Drop/Cut bal argumentuma egy egĂ©sz (esetĂŒnkben 1), akkor a Drop mƱveletrĆl lesz szĂł, Ă©s Ăgy minden egyes allistĂĄnak elsĆ elemĂ©tĆl megszabadulhatunk (Drop Each), de ha mĂĄr itt vagyunk, az egyes rĂ©szlistĂĄkat összegezzĂŒk is (Add Over Each):
s:+/'1_'(&0N=b) _ b
Az elsĆ kĂ©rdĂ©st megvĂĄlaszolĂĄsĂĄhoz nincs mĂĄs dolgunk, mint kivĂĄlasztani a kapott szĂĄmok közĂŒl a maximĂĄlist (Max Over) :
|/s
A feladat mĂĄsodik rĂ©szĂ©ben az allistĂĄk összegei közĂŒl a hĂĄrom legnagyobbat kell összegezni. Ehhez csökkenĆ sorrenbe rendezzĂŒk az lista elemeit (Grade-down azutĂĄn pedig Index), majd vesszĂŒk az elsĆ hĂĄrom elemet (Take 3) Ă©s szummĂĄzzuk azokat (Plus Over)
+/3#s[>s]
Ahogy a feladat elnevezĂ©se is mutatja, a kĆ-papĂr-ollĂł jĂĄtĂ©kon alapul a feladat. Az inputban szereplĆ betƱpĂĄr alapjĂĄn kell pontokat szĂĄmolni, majd ezeket összegezni. A hĂĄrom-hĂĄrom lehetĆsĂ©g miatt kilenc kĂŒlönfĂ©le sor jelenhet meg az inputban, akĂĄr ezeket is lehetne hasznĂĄlni, ĂĄm prĂłbĂĄljunk egy kicsit takarĂ©koskodni a memĂłriĂĄval, Ă©s a string adattĂpus helyett a symbol-t hasznĂĄlni, amely valĂłjĂĄban egy dinamikus felsorolĂĄsos tĂpus. Az input formĂĄtuma a következĆ:
A Y
B X
C Z
Nincs mĂĄs dolgunk, mint a sor elsĆ Ă©s harmadik karakterĂ©bĆl egy sztringet alkotni, majd ezt konvertĂĄlni szimbĂłlummĂĄ. Erre Ă©n egy egyargumentumĂș fĂŒggvĂ©nyt vezetek be, melynek alapĂ©rtelmezett vĂĄltozĂłja az x, Ă©s az Index-Item mƱveletet hasznĂĄlja az egyes betƱk kinyerĂ©sĂ©re, majd a Format segĂtsĂ©gĂ©vel konvertĂĄlja a kĂvĂĄnt alakra:
f:{`$x@0 2}
Ezek utĂĄn kĂ©szĂtĂŒnk egy asszociatĂv tömböt (dict), mely a korai K verziĂłknĂĄl mĂ©g a Make/Unmake segĂtsĂ©gĂ©vel törtĂ©nik, s az egymĂĄsba ĂĄgyazott feltĂ©teles utasĂtĂĄsok helyett ebben a tömbben tĂĄroljuk a feladatspecifikus informĂĄciĂłkat, az inputhoz tartozĂł pontszĂĄmot. EzutĂĄn nincs mĂĄs dolgunk, mint az input minden egyes sora helyett a neki megfelelĆ Ă©rtĂ©ket venni, Ă©s ezeket összegezni.
d1: .((`AX;4);(`AY;8);(`AZ;3);(`BX;1);(`BY;5);(`BZ;9);(`CX;7);(`CY;2);(`CZ;6))
+/d1@f'0:`input02.txt
A feladat mĂĄsodik rĂ©szĂ©ben megvĂĄltozik az input jelentĂ©se. Ezt az asszociatĂv tömb lecserĂ©lĂ©sĂ©vel kezelhetjĂŒk le, minden mĂĄs marad ugyanaz.
d2: .((`AX;3);(`AY;4);(`AZ;8);(`BX;1);(`BY;5);(`BZ;9);(`CX;2);(`CY;6);(`CZ;7))
+/d2@f'0:`input02.txt
Ebben a feladatban az input a következĆkĂ©ppen nĂ©z ki:
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
Az elsĆ esetben minden sort meg kell felezni, Ă©s megkeresni azt a karaktert, amely mindkĂ©t fĂ©lben szerepel, majd ezekhez a karakterekhez tartozĂł kĂłdokat kell összegezni.
A megoldĂĄshoz kĂ©szĂtĂŒnk egy fĂŒggvĂ©nyt, mely a sorhoz megadja a közös karakter kĂłdjĂĄt. K-ban megszokott, hogy a kifejezĂ©seket jobbrĂłl-balra olvassuk, ĂĄm ha a fĂŒggvĂ©ny törzsĂ©ben több mƱvelet is szerepel, akkor az egyes mƱveletek balrĂłl-jobbra hajtĂłdnak vĂ©gre. Most ezek a mƱveletek lokĂĄlis vĂĄltozĂłk Ă©rtĂ©kadĂĄsai lesznek. x jelöli a fĂŒggvĂ©ny egyetlen paramĂ©terĂ©t, ami majd az input egyik sora lesz. Az l jelöli a sor hosszĂĄnak a felĂ©t (Count, Divide), az a a sor elsĆ felĂ©t (Take), a b a sor mĂĄsodik felĂ©t (Drop), mĂg a o a feladat kiĂrĂĄsa szerinti egyetlen közös karakter ASCII kĂłdjĂĄt.
A két sztring metszetét a _lin
beĂ©pĂtett fĂŒggvĂ©nnyel lehet kiszĂĄmolni. Adott a kĂ©t sztring mint kĂ©t karakterlista, Ă©s teszteljĂŒk, hogy az elsĆ karakterei közĂŒl melyik fordul elĆ a mĂĄsodikban. Ennek megfelelĆen az eredmĂ©ny egy bitvektor lesz, melybĆl ki kell nyerni a közös karaktereket, azaz az elsĆ sztring azon betƱit, amelyekhez a bitvektorban igaz (1) Ă©rtĂ©k tartozik. Itt a megfelelĆ indexet a Where szolgĂĄltatja. Mivel a kapott eredmĂ©ny egy egyelemƱ lista lesz, ennek az elsĆ elemĂ©t kell venni (First), majd pedig az ASCII kĂłdjĂĄt (_ic). A nagybetƱk kĂłdjai 65 Ă©s 90, mĂg a kisbetƱkĂ© 97 Ă©s 122 közĂ© esnek, a feladat szerint pedig 27-52 illetve 1-26 közĂ© kell konvertĂĄlni, Ăgy egy if-then-else szerkezetet hasznĂĄlunk, ahol a szögletes zĂĄrĂłjelben elĆl a feltĂ©tel szerepel, majd az igaz ĂĄghoz tartozĂł kifejezĂ©s, amit a hamis ĂĄghoz tartozĂł követ.
Nem maradt mĂĄs dolgunk, mint alkalmazni a fĂŒggvĂ©nyt az input minden sorĂĄra (Apply-monadic Each), majd összegezni a kĂłdokat (Plus Over)
f:{l:(#x)%2;a:l # x;b:l _ x;o:_ic *a[&a _lin b];:[96<o;o-96;o-38] }
+/f @' 0:`input03.txt
A mĂĄsodik esetben nem kettĂ© kell szelni a sort, hanem hĂĄrmassĂĄval csoportosĂtani. MielĆtt ezt megcsinĂĄlnĂĄnk, kezdjĂŒnk azzal a fĂŒggvĂ©nnyel, amely a hĂĄrom sorbĂłl ĂĄllĂł listĂĄhoz hozzĂĄrendeli a neki rendelt kĂłdot. Az a, b Ă©s a c rendre az egyes sorokat jelölik (First, Index/At), a d az elsĆ kĂ©t sor "metszetĂ©t", mĂg az o a hĂĄrom sor metszete elsĆ karakterĂ©nek ASCII kĂłdjĂĄt.
f:{a:*x;b:x@1;d:a[&a _lin b];c:x@2;o: _ic *d[&d _lin c];:[96<o;o-96;o-38]}
 ```
Ahhoz, hogy hĂĄrmassĂĄval szĂ©t tudjuk szabdalni az inputot, nem ĂĄrtana tudni, hogy hĂĄny sorbĂłl ĂĄll, ezĂ©rt az egĂ©sz inputot beolvassuk az _i_ vĂĄltozĂłba, majd ebbĆl kiszĂĄmoljuk, hogy hĂĄny csoportunk is lesz (Count Ă©s Divide), majd a szĂ©tszabdalĂĄshoz egy aritmetikai sorozatot hozunk lĂ©tre (Enumerate Ă©s Times), Ă©s vĂ©gĂŒl a Cut segĂtsĂ©gĂ©vel az input listĂĄjĂĄt allistĂĄk listĂĄjĂĄvĂĄ alakĂtjuk. Erre mĂĄr alkalmazhatĂł a fĂŒggvĂ©nyĂŒnk (Apply Each) Ă©s szummĂĄzhatunk (Plus Over)
```kona
+/f@'(3*!(#i)%3) _ i:0:`input03.txt
A soron következĆ feladatban az egyes sorok 2-2 intervallumot tartalmaznak. A feladatunk az egymĂĄst ĂĄtfedĆ intervallumpĂĄrok szĂĄmĂĄt meghatĂĄrozni. LĂĄtjuk, hogy az intervallumot a mĂnusz jel jelöli, Ă©s vesszĆvel vĂĄlasztjuk el a kĂ©t intervallumot. ElĆször is a nĂ©gy szĂĄmot kellene kinyerni. MĂĄs esetben a regulĂĄris kifejezĂ©s egy kĂ©zenfekvĆ megoldĂĄs, de most ezzel nem Ă©lhetĂŒnk. Viszont a Scan nem dokomentĂĄlt tulajdonsĂĄga, hogy elĆtte egy karaktert, mögötte egy sztringet szerepeltetve az adott karakter elĆfordulĂĄsainĂĄl feldarabolja a sztringet. Most csak azt tart vissza bennĂŒnket, hogy mĂĄsodik Ă©s harmadik szĂĄmot vesszĆ vĂĄlasztja el, nem pedig mĂnusz jel.
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
Ezen könnyƱ segĂteni, csak az _ssr
beĂ©pĂtett fĂŒggvĂ©nyt kell hasznĂĄlni, ahol az elsĆ argumentum az eredeti szöveg, a mĂĄsodik hogy mit szeretnĂ©nk lecserĂ©lni, mĂg a harmadik, hogy mire. A csere utĂĄn mĂĄr jöhet a Scan, majd a Format a sztring darabjainak szĂĄmmĂĄ alakĂtĂĄsĂĄra. Mindezt az f
fĂŒggvĂ©ny tartalmazza. Ha x0, x1, x2, x3 jelöli a nĂ©gy szĂĄmot, akkor az elsĆ intervallum akkor tartalmazza a mĂĄsodikat, ha x0<x2 Ă©s x3<x1, mĂg fordĂtva x2<x0 Ă©s x1<x3. Ezt egy az egyben le is lehetne fordĂtani kĂ©pletre, de gyorsabban vĂ©gzĂŒnk, ha (x0-x2)(x1-x3) szorzatot tekintjĂŒk. Ha az negatĂv (pontosabban nem pozitĂv), akkor az elĆbbi kĂ©t feltĂ©tel valamelyike teljesĂŒl. HasznĂĄlhatĂł lenne a  x[i]
jelölés is, de ennél rövidebb a x@i
, sĆt a First mĂ©g rövidebb. Mivel kisebb-egyenlĆ nem lĂ©tezik a rendszerben, ezĂ©rt a nagyobbat kell tagadni (Negate). A g
fĂŒggvĂ©ny tartalmazza ezt a vizsgĂĄlatot, s nincs mĂĄs hĂĄtra, mint a beolvasott inputot ĂĄtengedni elĆbb az f
, majd a g
fĂŒggvĂ©nyen, s mivel darabszĂĄmra vagyunk kĂvĂĄncsiak, mĂĄr csak összegezni kell a megkapott logikai Ă©rtĂ©keket.
f:{0$"-"\ _ssr[x;",";"-"]}
g: {~0<((*x)-(x@2))*((x@1)-(x@3))}
+/g'f@'0:`test04.txt
A feladat mĂĄsodik felĂ©ben az ĂĄtfedĂ©sek szĂĄmĂĄt kell megadni. Ez hasonlĂł az elĆbbihez, csak az (x0-x2)(x1-x3) szorzat nem pozitĂvsĂĄgĂĄt kell vizsgĂĄlni, amit itt a h
fĂŒggvĂ©ny tartalmaz.
h: {~0<((*x)-(x@3))*((x@1)-(x@2))}
+/h'f@'0:`test04.txt
Ebben a feladatban egy darut kell szimululålnunk. Az input megadja az egyes oszlopok tartalmåt, illetve a végrehajtandó feladatsort.
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
ElsĆ dolgunk az ĂĄllapot beolvasĂĄsa. Ehhez a következĆ vĂĄltozĂłkat hasznĂĄljuk: a a teljes input, b az elsĆ ĂŒres sorig terjedĆ sorok szĂĄma, c az elsĆ b sor oszlopaibĂłl kivĂĄlogatva a nekĂŒnk szĂŒksĂ©gesek, d pedig ugyanez szĂłközök nĂ©lkĂŒl, illetve hogy a nullĂĄval kezdĆdĆ indexelĂ©s ne kavarjon be, amikor a feladat egyessel kezdĆdĆen hivatkozik az oszlopokra, mĂ©g beszĂșrunk egy virtuĂĄlis oszlopot a többi elĂ©. A c meghatĂĄrozĂĄsakor minden negyedik karakter-oszlopra szĂŒksĂ©g lesz, ĂĄm az elsĆ jĂł oszlop az egyes indexƱ. Nincs mĂĄs hĂĄtra, mint megszabadulni a sorkezdĆ szĂłközöktĆl, erre egy kĂŒlön fĂŒggvĂ©nyt csinĂĄlunk, mely minden karakterre teszteli, hogy az szĂłköz-e, s ezeket a Where-t hasznĂĄlva kihagyja. SzerencsĂ©re a sorban hĂĄtrĂĄbb (oszlopban lentebb) mĂĄr nincs szĂłköz, kĂŒlönben kellene a a Scan Ă©s az Or is, hogy azokat semlegesĂtsĂŒk.
a:0:"test05.txt"
b:a?""
c:(+b#a)@1+4*!1+(#*a)%4
d:"0",{a:~x=" ";b:|\a;x@&b}'c
A feladat megoldĂĄsĂĄhoz szĂŒksĂ©gĂŒnk van a parancssorozatra is. Sajnos ez tele van szemetelve mindenfĂ©le szavakkal, pedig nekĂŒnk csak a szĂĄmok kellenĂ©nek. A pĂ©ldĂĄban csak egyjegyƱ szĂĄmok szerepelnek, a valĂłs feladatban hosszabbak is, ezĂ©rt Ăłvatosabban jĂĄrunk el. KĂ©szĂtĂŒnk egy fĂŒggvĂ©nyt, mely elsĆkĂ©nt meghatĂĄrozza a szĂłközök helyĂ©t, hasonlĂłan a d kezdĆ lĂ©pĂ©sĂ©hez. Majd a szĂłközöknĂ©l - pontosabban elĆttĂŒk - szĂ©tvagdaljuk a sztringet (Cut). Emiatt a move szĂł ki is esik, Ăgy a pĂĄratlan sorszĂĄmĂș (pĂĄros indexƱ) elemeit kell megtartani a listĂĄnak. MiutĂĄn ezek egy-egy szĂĄmot, meg egy azt megelĆzĆ szĂłközt tartalmaznak, alkalmazhatĂł mindegyikre a Format (parse), mikor is egĂ©sz szĂĄmot nyerĂŒnk ki belĆle. Ezt fĂŒggvĂ©nyt a fĂĄjl elsĆ b+1 sora utĂĄni rĂ©szĂ©re kell alkalmazni, tehĂĄt a Drop lesz a barĂĄtunk.
Ezek utĂĄn lĂ©nyegĂ©ben szĂł szerint követni kell az elĆĂrt utasĂtĂĄsokat. A Take segĂtsĂ©gĂ©vel lemĂĄsolunk annyi elemet a megadott indexƱ oszloprĂłl, amennyit ĂĄt kell mozgatnunk (ez kerĂŒl a q vĂĄltozĂłba), majd következĆleg valĂłban töröljĂŒk is ezeket az elemeket (Drop), s vĂ©gĂŒl - a feladatnak megfelelĆen fordĂtott sorrendben (Reverse) a cĂ©loszlopot kiegĂ©szĂtjĂŒk. Annak Ă©rdekĂ©ben, hogy a mƱveleteink vĂ©grehajtĂłdjanak az egyes oszlopokat tartalmazĂł sztringeket felĂŒlĂrjuk az Ășj Ă©rtĂ©kkel.
A fĂŒggvĂ©ny amely ezt megvalĂłsĂtja kĂ©t argumentumot hasznĂĄl. Az x lesz az oszlopok listĂĄja, mĂg az y a mƱveletet jelzĆ szĂĄmhĂĄrmas. Ărdemes megfigyelni, hogy a fĂŒggvĂ©ny utolsĂł kifejezĂ©snĂ©l visszaadja x aktuĂĄlis Ă©rtĂ©kĂ©t. Erre pedig mĂĄr lehet is alkalmazni a soron következĆ mƱvelet hĂĄrmasĂĄt. Azt, hogy minden mƱveletetet sorra vĂ©grehajtsunk, az Over dyad Ă©s Scan dyad rĂ©vĂ©n Ă©rhetjĂŒk el. Ha tesztelni kĂvĂĄnjuk a programunkat Ă©s lĂĄtni akarjuk a köztes eredmĂ©nyeket is, akkor az utĂłbbit hasznĂĄlhatjuk fel: d f\s
, mĂg ha csak le akarjuk futtatni, akkor az elĆbbit:
s:{0$'((&x = " ") _ x) @ 0 2 4}'(b+1) _ a
f:{q:(*y)#x[y@1];x[y@1]:(*y) _ x[y@1];x[y@2]:(|q),x[y@2];x}
d f/s
A mĂĄsodik feladatban az a trĂŒkk, hogy nem kell a levĂĄlasztott rĂ©szt megfordĂtani, amikor ĂĄthelyezzĂŒk, emiatt a kapott fĂŒggvĂ©ny kicsit rövidebb lesz.
g:{q:(*y)#x[y@1];x[y@1]:(*y) _ x[y@1];x[y@2]:q,x[y@2];x}
d g/s
A soron következĆ feladatnĂĄl azt a legelsĆ pozĂciĂłt kell meghatĂĄrozni, amelyet követĆ 4 karakter mind kĂŒlönbözĆ. Az input csupĂĄn egy sor, a mintĂĄban Ăgy nĂ©z ki.
mjqjpqmgbljsphdztnvjfqwrcgsmlb
Az inputnak csak az elsĆ sorĂĄval kell dolgozni, ezĂ©rt is hasznĂĄljuk a First-öt. Majd el kellene dönteni, hogy marker-rel van-e dolgunk. A fĂŒggvĂ©nyĂŒnknek egy paramĂ©tere van, hogy melyik karaktertĆl szĂĄmoljuk a dolgokat. ElsĆ lĂ©pĂ©sben ennyit eldobunk (Drop), majd vesszĂŒk a nĂ©gy soron következĆt (Take), Ă©s a Range - mĂĄs nĂ©ven uniq - segĂtsĂ©gĂ©vel kivĂĄlogatjuk az egyedi karaktereket. Ha pont nĂ©gyen vannak, akkor nincs ismĂ©tlĆdĂ©s. VegyĂŒk az input hosszĂĄt, egy eddig növekvĆ szĂĄmsorozatot, Ă©s ezek mindegyikĂ©re alkalmazzuk az elĆbbi fĂŒggvĂ©nyt. (Ha tĂșl sokat vĂĄgunk le, akkor nem lesz elĂ©g hosszĂș a maradĂ©k, emiatt a fĂŒggvĂ©ny hamis Ă©rtĂ©kkel tĂ©r vissza, ami nem baj). MegkeressĂŒk, hogy melyik indexnĂ©l van az elsĆ igaz Ă©rtĂ©k, s hozzĂĄadunk mĂ©g nĂ©gyet, mert az azt követĆ karakter a kĂ©rdĂ©ses.
a:*0:"input06.txt"
f:{4=#?4#x _ a}
4+(f'!#a)?1
A feladat mĂĄsodik felĂ©ben csak a korĂĄbbi konstanst kellett ĂĄtĂrni mĂĄsra.
g:{14=#?14#x _ a}
14+(g'!#a)?1
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k
A feladat inputja kellĆen szemĂ©t. ElĂ©g sok olyan sor van benne, mely csak zavart okoz, ezektĆl jĂł lenne megszabadulni. MĂĄsrĂ©szt szellemesen a könyvtĂĄrrendszer közepĂ©n fejezi be a sĂ©tĂĄt, ami a megoldĂĄst nem zavarja, de erre figyelemmel kell lenni a program megĂrĂĄsakor.
KezdjĂŒk azzal, beolvassuk az inputot az a vĂĄltozĂłban, de egybĆl el is hagyjuk az input elsĆ sorĂĄt (Drop), mert arra nem lesz szĂŒksĂ©gĂŒnk. Az fw fĂŒggvĂ©ny neve a first word rövidĂtĂ©se, Ă©s az korĂĄbbiak szerint igen egyĂ©rtelmƱ a definĂciĂłja. Mely sorokat hagyjuk el? Amely sor a dir szĂłval kezdĆdik, az most nem hordoz a feladat megoldĂĄsĂĄhoz semmi informĂĄciĂłt, mert utĂĄna Ășgyis lesz egy rĂĄ vonatkozĂł cd. Hogyan akadunk rĂĄ ezekre a sorokra? Alkalmazzuk az fw fĂŒggvĂ©nyt az input összes sorĂĄra (Each) - amivel megkapjuk a sorok elsĆ szavait, Ă©s ezt mĂĄr csak össze kell hasonlĂtani a dir szĂłcskĂĄval (Match Each-left). Ezzel minden sorra kapunk egy igaz-hamis Ă©rtĂ©ket - megvĂĄlaszolva azt kĂ©rdĂ©st, hogy ezzel a szĂłval kezdĆdik-e a sor.
Vannak tovåbbi felesleges soraink, melyekkel körbenéznénk: $ ls
. Mivel az input sztringek listĂĄja, ez pedig itt egy string a String match (_sm
) szintĂ©n logikai Ă©rtĂ©kek sorozatĂĄval tĂ©r vissza. A kĂ©t bitsorozatnak venni kell a diszjunkciĂłjĂĄt (Or), majd tagadni (Not), hogy pont ott kapjunk egyest, amely sort meg akarjuk Ćrizni. Ezek utĂĄn egy korĂĄbban mĂĄr lĂĄtott trĂŒkkel (Where + At) mĂĄr csak a valĂłban szĂŒksĂ©ges soraink maradtak meg.
a:1_0:"test07.txt"
fw:{(x?" ")#x}
b:a@&~(a _sm "$ ls")|(fw'a)~\:"dir"
Annak Ă©rdekĂ©ben, hogy a gyökĂ©rkönyvtĂĄrban kössĂŒnk ki, össze kellene szĂĄmolni, hogy hĂĄnyszor lĂ©pĂŒnk befele, Ă©s hĂĄnyszor kifele. Az utĂłbbi egyszerƱ: cd ..
, viszont az elĆbbi kicsit komplikĂĄltabb, ezĂ©rt az összes cd
parancs szĂĄmĂĄt hatĂĄrozzuk meg, ami nem nehĂ©z, mert csak ilyen parancsaink maradtak, azaz ha az elsĆ szĂł egy karakterbĆl ĂĄllĂł sztring - emiatt kell a vesszĆt hasznĂĄlni (Enlist) - ami pont a dollĂĄr prompt, akkor kĂ©sz is vagyunk. A szerkezet hasonlĂł a dir-nĂ©l lĂĄtotthoz, csak miutĂĄn itt darabszĂĄmra vagyunk kĂvĂĄncsiak, összegezni kell a logikai Ă©rtĂ©keket (Add Over). A visszalĂ©pĂ©s is ugyanaz mint az elĆbb, s itt is összegezni kell. Ezzel a kĂ©t darabszĂĄm a c Ă©s d vĂĄltozĂłba kerĂŒl. MĂĄr csak a sorok listĂĄjĂĄt kell megfelelĆ szĂĄmĂș visszalĂ©pĂ©st tartalmazĂł sorral:
c:+/(fw'b)~\:,"$"
d:+/b _sm "$ cd .."
b:b,(c-2*d)#,"$ cd .."
A megoldĂĄsunkban Ășjra a xf/y
szerkezetet kĂvĂĄnjuk hasznĂĄlni, ahol x tartalmazza az aktuĂĄlis ĂĄllapotot, az y pedig az input mĂ©g fel nem dolgozott rĂ©szĂ©t. Mire is van szĂŒksĂ©gĂŒnk? Mivel kijjebb Ă©s beljebb mozgunk a fĂĄjlszerkezetben, Ă©szben kell tartani, hogy a kĂŒlsĆ könyvtĂĄraban mĂĄr mekkora mĂ©retet szĂĄmoltunk mĂĄr össze, mĂĄsrĂ©szt szĂĄmolni kell, hogy a feladatban szereplĆ mĂ©ret hol tart.
A szĂłban forgĂł fĂŒggvĂ©ny a Scheme cond feltĂ©teles szerkezetĂ©t követi. Az egyes feltĂ©teleket azok igaz ĂĄga követi, esetlegesen egy else ĂĄggal - arra az esetre ha egyik feltĂ©tel sem teljesĂŒl. LĂĄssuk milyen esetekkel kell foglalkoznunk!
-
A sor egy visszalĂ©pĂ©st tartalmaz. Ha a feladatban megadott mĂ©retet nem Ă©ri el a listĂĄnk elsĆ eleme, akkor hozzĂĄ kell adnunk a pĂĄr mĂĄsodik tagjĂĄhoz, egyĂ©bkĂ©nt nem. Viszont ennek az alkönyvtĂĄrnak a mĂ©rete hozzĂĄadĂłdik a tartalmazĂł könyvtĂĄr mĂ©retĂ©hez, azaz az elsĆ szĂĄmmal meg kell növelni a mĂĄsodikat. A listĂĄnk - ami a pĂĄros elsĆ tagja - elsĆ elemĂ©re hivatkozhatunk a First-First-tel, a mĂĄsodik elemĂ©re a
x@0@1
helyett az At-Over segĂtsĂ©gĂ©vel hivatkozunk. Ăjabb feltĂ©teles szerkezet hasznĂĄlata helyett aritmetikai kifejezĂ©st hasznĂĄlunk. -
A mĂĄsodik feltĂ©tel arrĂłl szĂłl, hogy beljebb kerĂŒlĂŒnk a fĂĄjlrendszerben. Ekkor egy nullĂĄt szĂșrunk a listĂĄnk elejĂ©re.
-
Ha nem cd parancs szerepel a sorban, akkor egy fĂĄjlrĂłl van szĂł, melynek a mĂ©retĂ©vel meg kell növelni a lista elsĆ elemĂ©t
A listĂĄnk egy nulla szĂĄmbĂłl ĂĄll, mĂg a szĂĄmlĂĄlĂł megint nulla Ă©rtĂ©kkel indul.
f: {:[y~"$ cd ..";(((**x)+(x@/0 1)),2_*x;(x[1] + (**x)*(100001>**x)));(fw@y)~,"$";(0,*x;x[1]);(((0$y)+**x),1 _ *x;x[1])]}
(,0;0) f/ b
A mĂĄsodik feladatnĂĄl azt a könyvtĂĄrat kell megtalĂĄlni, mellyel Ă©pp megfelelĆ mĂ©retƱ helyet tudunk felszabadĂtani. Most nem kell növelni a szĂĄmlĂĄlĂłt, hanem feljegyezni minden egyes könyvtĂĄr mĂ©retĂ©t. Ezzel csak az elsĆ eset kĂłdja mĂłdosult, illetve az, hogy az indulĂł paramĂ©terĂŒnk mĂĄsodik tagja egy ĂŒres lista. EredmĂ©nyĂŒl egy teljes elfoglalt terĂŒlet Ă©s a könyvtĂĄrak mĂ©reteinek listĂĄjĂĄt kapjuk meg. Ezt a pĂĄros az e vĂĄltozĂłban mentjĂŒk el. Az l a felszabadĂtantĂł terĂŒlet mĂ©retĂ©t tartalmazza. EzĂ©rt tekintjĂŒk mindazokat a mĂ©reteket, melyek az l-nĂ©l nagyobbat, majd tekintjĂŒk ezek minimumĂĄt, s ezzel kĂ©sz is vagyunk.
g: {:[y~"$ cd ..";(((**x)+(x@/0 1)),2_*x;(**x),x[1]);(fw@y)~,"$";(0,*x;x[1]);(((0$y)+**x),1 _ *x;x[1])]}
e: (,0;()) g/ b
l: 30000000-(70000000-**e)
&/(e[1][&e[1] >' l])
Ez a feladat kifejezetten kedvez a vektor-nyelveknek, szinte egyĂ©rtelmƱ a megoldĂĄsa. A feladat arrĂłl szĂłl - hasonlĂłan a skyscraper rejtvĂ©nyhez - hogy hĂĄny fa lĂĄthatĂł a nĂ©gy Ă©gtĂĄj valamelyikĂ©bĆl. Ehhez az kell, hogy magasabb legyen, mint az elĆtte ĂĄllĂł hĂĄzak. Az input az egyes fĂĄk magassĂĄgĂĄt adja meg egy-egy karakterrel.
30373
25512
65332
33549
35390
Az karakter-egĂ©sz ĂĄtalakĂtĂĄst a _ic
fĂŒggvĂ©ny oldja meg, s jĂłl nevelt vektor-nyelvre jellemzĆen egybĆl ĂĄtadhatjuk a teljes inputot, az összes sor minden karaktere konvertĂĄlĂłdik egy egĂ©sszĂ©. Lusta mĂłdon az Ăgy kapott ASCII kĂłdokkal is dolgozhatnĂĄnk tovĂĄbb, de jobb kisebb szĂĄmokra alakĂtani ezeket. Udvarias lenne 48-at levonni, hogy egyezen a feladatben lĂĄtott szĂĄmjegy, meg a belĆle szĂĄrmazĂł szĂĄm, de van egy szerencsĂ©s mellĂ©khatĂĄsa, ha ezt egy kisebb szĂĄmmal helyettesĂtjĂŒk, mert Ăgy minden kerethez tartozĂł Ă©rtĂ©k lĂĄthatĂłnak minĆsĂŒl. Azon lehetne vitatkozni, hogy a 0 magassĂĄgĂș fa lĂĄthatĂł-e vagy sem, de a feladat kitƱzĆje szerint igen, akkor fogadjuk el. A mĂĄtrixunk az m nevet kapta, Ă©s s jelöli a mĂ©retĂ©t. SzerencsĂ©re nĂ©gyzetes a feladat, Ăgy egy mĂ©ret elĂ©g mindkĂ©t irĂĄnyba.
A megoldĂĄs egy trĂŒkkön mĂșlik, az f fĂŒggvĂ©nyen. Ez kĂ©t paramĂ©tert hasznĂĄl, az x
egészet, és az y
mĂĄtrixot. LevĂĄlasztjuk a mĂĄtrix elsĆ x sorĂĄt (Take), majd oszloponkĂ©nt maximumot szĂĄmolunk (Max Over), az eredmĂ©nyt összehasonlĂtjuk a soron következĆ x+1-dik sorral, s ahol az nagyobb, ott van egy lĂĄthatĂł fa. A mĂĄtrixot rögitjĂŒk (parciĂĄlis fĂŒggvĂ©nyt definiĂĄlunk), Ă©s a levĂĄlaszthatĂł sorok összes lehetĆsĂ©gĂ©re vĂ©grehajtjuk ezt a parciĂĄlis fĂŒggvĂ©nyt. Ahogy kĂ©t vektor összehasonlĂtĂĄsa egy bitvektort ad, ezek egymĂĄsutĂĄnja egy bitmĂĄtrixot, ahol ott ĂĄll egyes, ahol lĂĄthatĂł fa van. Az, hogy a legkisebb fa nĂĄlunk legalĂĄbb 1, az elsĆ sorra konstans igazat ad.
Ezek utĂĄn nincs mĂĄs dolgunk, mint a mĂĄtrixunkat megfelelĆ mĂłdon tĂŒkrözni, s megkapjuk mind a nĂ©gy irĂĄnyt: ha nincs transzformĂĄciĂł, akkor az az Ă©szaki irĂĄny (a); ha vizszintesen tĂŒkrözzĂŒk (Reverse), az a dĂ©li irĂĄny (b), ha transzponĂĄljuk mĂĄtrixot (Flip) az a nyugati irĂĄny (c), ha pedig elĆbb trĂŒkközzĂŒk, majd transzponĂĄljuk, a keleti irĂĄnyt adja (d). Itt vigyĂĄzni kell az eredmĂ©ny visszaalakĂtĂĄsĂĄval, hogy jĂł sorrendben törtĂ©njen!
Ezek utån nincs mås dolgunk, mint venni a bitmåtrixok diszjunkciójåt (Or), majd összegezni az egészet (duplån Add Over).
m: (_ic 0:"test08.txt")-47
s:#m
f:{(|/x#y)<y[x]}
a:f[;m]'!s
b:|f[;|m]'!s
c:+f[;+m]'!s
d:+|f[;|+m]'!s
+/(+/a|b|c|d)
A feladat mĂĄsodik rĂ©szĂ©ben az a lĂ©nyegi kĂ©rdĂ©s, hogy egy-egy irĂĄnyba meddig lĂĄthatunk el. Az adott fĂĄnĂĄl alacsonyabb fĂĄkat mindenkĂ©ppen lĂĄtjuk, viszont az azonos magassĂĄgĂș vagy mĂ©g magasabb fĂĄk mögĂ© mĂĄr nem lĂĄtunk.
Ha adott az aktuĂĄlis fa magassĂĄga (a), valamint adott irĂĄnyban ĂĄllĂł fĂĄk magassĂĄgai (b), akkor az b<a
egy bitsorozatot ad vissza, s ebben az elsĆ hamis Ă©rtĂ©k (0) jelöli azt a fĂĄt amit mĂ©g lĂĄtunk, de mögĂ© mĂĄr nem.
A Find megadja ennek az indexĂ©t, de mivel az indexelĂ©s nullĂĄval kezdĆdik, ezt mĂ©g eggyel növelnĂŒnk kell.
Ha ez a nullĂĄs nem lĂ©tezik, akkor rossz Ă©rtĂ©ket kapnĂĄnk, ezĂ©rt bevetĂŒnk egy minimumot (Min), melynek a mĂĄsik argumentuma a b hossza (Count).
Az a Ă©s b meghatĂĄrozĂĄsĂĄhoz ki kell indulnunk egy a mĂĄtrix egy sorĂĄbĂłl, ez lesz a fĂŒggvĂ©ny y argumentuma, Ă©s a sor egy elemĂ©nek indexĂ©bĆl (x). Az At Ă©s Drop hasznĂĄlatĂĄval elĂ©rjĂŒk, hogy az index ĂĄltal jelölt elem, valamint a mögötte ĂĄllĂł szĂĄmokat veszik fel a lokĂĄlis vĂĄltozĂłink.
A g fĂŒggvĂ©nynek egy indexet Ă©s egy sort kell ĂĄtadni, de az indexnĂ©l felsoroljuk az összes lehetĆsĂ©get (Enumerate Each), majd mindezt egy kĂŒlsĆ fĂŒggvĂ©nynek tekintve ĂĄtadjuk a mĂĄtrix összes sorĂĄt (Each). Ezzel a vĂ©geredmĂ©ny (e1) egy mĂĄtrix melynek elemeit a keleti irĂĄnyba lĂĄthatĂł fĂĄk szĂĄmai alkotjĂĄk. Annak Ă©rdekĂ©ben, hogy ugyanezt megkapjuk a nyugati irĂĄnyra (e2), a mĂĄtrix sorait kell egyenkĂ©nt megfordĂtani (Reverse monadic Each). A Reverse-t direkt alkalmazva mĂĄtrixra vĂzszintesen tĂŒkrözzĂŒk a mĂĄtrixot, nem pedig fĂŒggĆlegesen. A transzponĂĄlĂĄs Ășjra hasznĂĄlhatĂł, ekkor a dĂ©li irĂĄnyt kapjuk meg (e3). Az Ă©szaki irĂĄnyhoz a transzponĂĄlĂĄst Ă©s a tĂŒkrözĂ©st kell kombinĂĄlni (e4).
VĂ©gĂŒl a feladat nem kĂ©r mĂĄst, mint az egyes irĂĄnyokhoz tartozĂł szĂĄmok szorzatĂĄnak a maximumĂĄt. Ehhez nincs mĂĄsra szĂŒksĂ©gĂŒnk, mint a nĂ©gy mĂĄtrix elemenkĂ©nti szorzatĂĄra (ami vĂ©letlenĂŒl sem mĂĄtrixszorzat), s kĂ©t Max-Over segĂtsĂ©gĂ©vel mindkĂ©t irĂĄnyban helyettesĂtjĂŒk a sort/oszlopot a maximĂĄlis elemĂ©vel.
g:{a:y@x;b:(x+1) _ y; (#b)&1+(a>b)?0}
e1:{g[;x]' (!s)}' m
e2:|:'{g[;x]' (!s)}' |:'m
e3:+{g[;x]' (!s)}' +m
e4:+|:'{g[;x]' (!s)}' |:'+m
|/|/e1*e2*e3*e4
A feladatban egy kötĂ©lke mozgĂĄsĂĄt kell követni. Az input a kötĂ©l elejĂ©nek a mozgĂĄsĂĄt Ărja le. A kötĂ©l vĂ©ge kis kĂ©slekedĂ©ssel követi az elejĂ©t, Ă©s az kĂ©rdĂ©s, hogy hĂĄny pozĂciĂłt lĂĄtogatott meg a kötĂ©l vĂ©ge.
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2
A feladat megoldĂĄsa sorĂĄn jellemzĆen a mĂĄr hasznĂĄlt mƱveleteket alkazzuk. Az i Ă©s az n a teszt Ă©s valĂłdi inputot tartalmazza. Ahogy fentebb is lĂĄthatĂł: elĆl szerepel egy irĂĄnyt jelzĆ betƱ, amit egy szĂĄm követ. JĂł ĂłrĂĄs debuggolĂĄst igĂ©nyelt, az a tĂ©ny, hogy ez a szĂĄm nem csak egy szĂĄmjegybĆl ĂĄllhat, bĂĄr a teszt ilyet nem tartalmaz. A beolvasĂĄshoz kĂ©szĂtĂŒnk egy segĂ©dfĂŒggvĂ©nyt, amit nem lĂĄtunk el nĂ©vvel, csak egyszerƱen felhasznĂĄljuk. Ennek az input egy sora lesz az argumentuma, ebbĆl kell a kezdĆ karaktert kinyerni (First) majd egy szimbĂłlummĂĄ kovertĂĄlni (Dollar Backtick), az elsĆ kĂ©t karaktert eldobni (Drop), hogy megkapjuk a szĂĄmot tartalmazĂł sztringet, ezt szĂĄmmĂĄ konvertĂĄlni (Dollar Int), Ă©s alkalmazni a szimbĂłlumra Take mƱveletet, hogy elegendĆ szĂĄmban megismĂ©teljĂŒk. MiutĂĄn minden betƱt kellĆ szĂĄmban megismĂ©teltĂŒnk, jöhet a Join Over, hogy egy listĂĄba szervezzĂŒk a sok aprĂł listĂĄt.
Az s az elĆjel fĂŒggvĂ©nyt jelöli, az itt lĂĄthatĂł fĂŒggvĂ©ny mĂĄs nyelveken is közkedvelt megvalĂłsĂtĂĄs.
A kötĂ©l vĂ©ge akkor mozog, ha nem szomszĂ©dos az elejĂ©vel. Egy-egy pozĂciĂłt kĂ©t szĂĄmmal jelölĂŒnk, Ăgy a c fĂŒggvĂ©nynek nĂ©gy argumentuma lesz. Ha az eltĂ©rĂ©s bĂĄrmely irĂĄnyban tĂșllĂ©pi az egyet - a fĂŒggvĂ©ny igaz Ă©rtĂ©ket ad vissza - , akkor mĂĄr nem Ă©rnek össze, s ekkor kell mozdĂtani a kötĂ©l vĂ©gĂ©t. A d fĂŒggvĂ©ny megadja az kötĂ©l vĂ©gĂ©nek valamely irĂĄnyĂș koordinĂĄtĂĄjĂĄt, az argumentumai pedig a kötĂ©l elejĂ©nek Ă©s vĂ©gĂ©nek ugyanezen irĂĄnyĂș koordinĂĄtĂĄi. Az f Ă©s g kĂ©t fĂŒggĂ©ny, mely a kötĂ©l eleje Ă©s vĂ©ge pozĂciĂłjĂĄhoz megadja a vĂ©gĂ©nek frissĂtett pozĂciĂłit, akĂĄr mozog, akĂĄr nem. Az a Ă©s b kĂ©t dictionary, s miattuk kell szimbĂłlumokat hasznĂĄlni, mert le vagyunk korlĂĄtozva ilyen kulcsok hasznĂĄlatĂĄra.
A h fĂŒggvĂ©ny a kötĂ©l egy ĂĄllapotĂĄt vĂĄrja (a nĂ©gy szĂĄmmal leĂrt kĂ©t pozĂciĂłt), illetve egy irĂĄnyt jelzĆ szimbĂłlumot. Majd ebbĆl elĆĂĄllĂt egy Ășjabb ĂĄllapotot. MĂĄr korĂĄbban is alkalmaztuk a trĂŒkköt, mikor a fĂŒggvĂ©ny-Over segĂtsĂ©gĂ©vel folyamatosan frissĂtjĂŒk az ĂĄllapotot, s közben feldolgozzuk a lista minden elemĂ©t. Itt nem az kĂ©rdĂ©s, hogy vĂ©gĂŒl hova kerĂŒl vĂ©gĂŒl a kötĂ©l, ezĂ©rt a fĂŒggvĂ©ny-Scan variĂĄnst alkalmazzuk, mint valamilyen trace parancs a nyolcvanas Ă©vekbĆl. Viszont nincs szĂŒksĂ©gĂŒnk minden Ăgy megkapott adatra, csak a kötĂ©l vĂ©gĂ©nek pozĂciĂłjĂĄra. A j fĂŒggvĂ©nyt ezt vĂĄlogatja ki, sĆt a Z80 processzornĂĄl lĂĄtott binary-coded-decimal trĂŒkköt alkalmazzuk, a szĂĄmpĂĄrbĂłl egy szĂĄmot kĂ©szĂtĂŒnk. Mi haszna van ennek? Sajnos a nyelvben nincs halmaz adattĂpus. Viszont van egy Range mƱvelet, mely kivĂĄlogatja a lista egyedi elemeit, s nem marad nekĂŒnk mĂĄs hĂĄtra, mint megszĂĄmolni, hĂĄnyas is vannak (Count).
i:,/{(0$(2 _ x))#`$*x}'(0:"test09.txt")
n:,/{(0$(2 _ x))#`$*x}'(0:"input09.txt")
s:{(x>0)-(x<0)}
c:{[x;y;u;v]1<(_abs x-u)|_abs y-v}
d:{x+s[y-x]}
f:{[x;y;u;v] :[c[x;y;u;v];d[u;x];u]}
g:{[x;y;u;v] :[c[x;y;u;v];d[v;y];v]}
a: .((`R;1);(`L;-1);(`U;0);(`D,0))
b: .((`R;0);(`L;0);(`U;1);(`D,-1))
h: {p:(a@y)+*x; q:(b@y)+x@1; r:x@2; t:x@3; (p;q;f[p;q;r;t];g[p;q;r;t])}
j:{(x@3)+1000*x@2}
#?j' (0;0;0;0) h\ i
A feladat mĂĄsodik rĂ©szĂ©ben hosszabb kötet kell szimulĂĄlni, amely 10 olyan darabbĂłl ĂĄll, melyek mindegyike Ășgy viselkedik, mint a korĂĄbbi kötelecske. Az elĆbb nĂ©gy vĂĄltozĂłt hasznĂĄltunk az ĂĄllapot leĂrĂĄsĂĄra, ugyanĂgy dolgozva most 20 vĂĄltozĂłra lenne szĂŒksĂ©gĂŒnk, tehĂĄt jobb, ha ĂĄtĂrjuk a korĂĄbbi programot, Ă©s az egyes koordinĂĄtĂĄk helyett pozĂciĂłkat jelölnek a vĂĄltozĂłink. Az i, s, a Ă©s b definĂciĂłja nem vĂĄltozott. A c, d Ă©s j szerepe ugyanaz, viszont a definĂciĂłja mĂĄs. A c-nek csak kĂ©t argumentuma van - kĂ©t pozĂciĂł, Ăgy ki kell nyerni az egyes koordinĂĄtĂĄkat, hogy kiszĂĄmolhassuk az eltĂ©rĂ©sĂŒket. Ugyanez a helyzet a d esetĂ©n is. Az e fĂŒggvĂ©ny is kĂ©t koordinĂĄtĂĄt vĂĄr - kĂ©t egymĂĄst követĆ kötĂ©ldarabĂ©t -, s hĂĄtrĂĄbb lĂ©vĆ pozĂciĂłjĂĄt frissĂti. A korĂĄbbi h szerepĂ©t most az m veszi ĂĄt, ezzel tudjuk a kötĂ©l kezdetĂ©t az elĆĂrt irĂĄnynak megfelĆen elmozdĂtani.
A p fĂŒggvĂ©ny egy teljes kötelet (pozĂciĂłsorozatot) vĂĄr, valamint egy irĂĄnyt. A fejet ennek megfelelĆen elmozdĂtja (q),
majd a kötĂ©l hĂĄtralevĆ rĂ©szĂ©re ettĆl a fejtĆl elindĂtva vĂ©grehajtja a frissĂtĂ©st. Az elĆbb lĂĄtott x f\ y
szerkezetet hasznĂĄljuk erre, ahol x
-nek a kötél y
-nak az irĂĄny felel meg. A Scan Dyad miatt a teljes kötelet kapjuk eredmĂ©nyĂŒl.
Emiatt ha eggyel kijjebb Ășjra ezt a szerkezetet hasznĂĄljuk, immĂĄr a kiindulĂł kötĂ©llel, Ă©s a mozgĂĄssorozattal, akkor minden közbensĆ ĂĄllapotot visszakapunk. A j korĂĄbban a mĂĄsodik - egyben utolsĂł - pozĂciĂłt kĂłdolta. Hosszabb kötĂ©l esetĂ©n ez nem esik egybe, Ăgy Ă©rdemes a last (Reverse - First) fĂŒggvĂ©nyt felhasznĂĄlni, s egy szĂĄmmĂĄ kĂłdolni a pozĂciĂłt. EzutĂĄn a korĂĄbban lĂĄtott mĂłdszerrel összeszĂĄmoljuk az egyedi pozĂciĂłk szĂĄmĂĄt.
i:,/{(0$(2 _ x))#`$*x}'(0:"test09.txt")
s:{(x>0)-(x<0)}
a: .((`R;1);(`L;-1);(`U;0);(`D,0))
b: .((`R;0);(`L;0);(`U;1);(`D,-1))
c:{1<(_abs x[0]-*y)|_abs x[1]-y[1]}
d:{(y[0]+s[x[0]-*y];y[1]+s[x[1]-y@1])}
e:{ :[c[x;y];d[x;y];y]}
m:{(a[y]+*x; b[y]+x[1])}
p:{q:m[*x;y]; r:q e\ (1 _ x); r}
j:{k:*|x; k[1]+1000*k[0]}
#?j'( ((0;0);(0;0)) p\ i)
#?j'(((0;0);(0;0);(0;0);(0;0);(0;0);(0;0);(0;0);(0;0);(0;0);(0;0)) p\ n)
Az utolsĂł kĂ©t sorbĂłl sejthetĆ, hogy ez a kĂłd megfelelĆ lesz a feladat mindkĂ©t rĂ©szfeladatĂĄnak megoldĂĄsĂĄra, csak a kötelet mĂĄskĂ©pp kell kĂłdolni a kĂ©t esetben.
A soron következĆ feladat egy egyszerƱ szimulĂĄciĂł. KĂ©t fajta sor szerepel az inputban, a NOP, illetve egy regiszter mĂłdosĂtĂł utasĂtĂĄs. Az a nehezĂtĂ©s, hogy az elĆbbi egy ciklus, mĂg az utĂłbbi kĂ©t ciklus alatt hajtĂłdik vĂ©gre, valamint a regiszter Ă©rtĂ©ke csak az utasĂtĂĄs vĂ©grehajtĂĄsa utĂĄn mĂłdosul, mĂg a kĂ©rdĂ©s a ciklus közbeni regiszterĂ©rtĂ©kre kĂvĂĄncsi.
noop
addx 3
addx -5
Ăpp ezĂ©rt az ĂĄllapotunk egy pĂĄros lesz, elsĆ eleme a regiszter Ășj Ă©rtĂ©ke, mĂg a mĂĄsik fele a vĂ©grehajtĂĄs alatti Ă©rtĂ©k vagy Ă©rtĂ©kek. Az f fĂŒggvĂ©ny argumentumai az ĂĄllapot Ă©s a soron következĆ sor tartalma lesz. EbbĆl elĂ©g az elsĆ betƱt figyelni, mert ha az n, akkor egy ciklussal kell szĂĄmolni, Ă©s a regiszter Ă©rtĂ©ke nem mĂłdosul, azaz a kezdeti Ă©rtĂ©ket kell tovĂĄbbadni duplĂĄn. Ha viszont a regiszter Ă©rtĂ©ke mĂłdosul, akkor ki kell vadĂĄszni a szĂĄmot a mnemonik mögĂŒl. AkĂĄr az is megfelelĆ lett volna, hogy ekkor az input elsĆ Ă¶t karakterĂ©t eldobjuk, de elsĆre kĂ©nyelmesebb volt a szĂłközig terjedĆ rĂ©sz kukĂĄzni, Ă©s a maradĂ©kot szĂĄmmĂĄ alakĂtani. TermĂ©sztesen mĂĄr megint a xf\y
szerkezetet hasznĂĄltam, mellyel az ĂĄllapotvĂĄltozĂĄsokkal haladva fel tudjuk dolgozni a teljes inputot. Viszont nem lesz szĂŒksĂ©gĂŒnk mindarra, amit kiszĂĄmoltunk, az pĂĄrosaink elsĆ tagjĂĄt eldobhatjuk. Ha valaki figyelmes, akkor lĂĄtja, hogy bekerĂŒlt egy felesleges nulladik ĂĄllapot, de ez pont segĂt a feladat megoldĂĄsĂĄban. A regiszter Ă©rtĂ©kĂ©nek törtĂ©netĂ©t az a listĂĄban mentettĂŒk el. A kĂ©rdĂ©sben feltett arithmetikai sorozatot nem nehĂ©z elĆĂĄllĂtani az Enumerate Ă©s szorzĂĄs meg összeadĂĄs segĂtsĂ©gĂ©vel, Ă©s helyben definiĂĄlt fĂŒggvĂ©nnyel az index Ă©s Ă©rtĂ©k szorzatokat könnyedĂ©n kiszĂĄmĂthatjuk, mĂg az Add-Over pedig gondoskodik a szummĂĄzĂĄsrĂłl.
i:0:"test10a.txt"
f:{:["n"=*y;(*x;*x);((*x)+0$((1+y?" ") _ y); (*x;*x) ) ]}
a:,/{x[1]}'(1;1) f\ i
+/{x*a[x]} 20+40*!6
A feladat mĂĄsodik rĂ©szĂ©nek a szövege igencsak el lett bonyolĂtva. ValĂłjĂĄban az a kĂ©rdĂ©s, hogy mikor kerĂŒl közel a regiszter Ă©rtĂ©ke egy folyamatosan vĂĄltozĂł Ă©rtĂ©khez (elektronsugĂĄr helyzete). Ez utĂłbbit könnyƱ generĂĄlni az Enumerate majd a Mod segĂtsĂ©gĂ©vel. Venni kell az eltĂ©rĂ©st az a vĂĄltozĂłban tĂĄrolt Ă©rtĂ©kektĆl, amit a Minus Ă©s abszolĂșt Ă©rtĂ©k szĂĄmĂtĂĄssal oldunk meg. A feladatban emlegetett hĂĄrom tĂĄvolsĂĄgnak, a -1, 0 Ă©s 1 felel meg, tehĂĄt csak azok melyeknĂ©l kettĆnĂ©l kisebb Ă©rtĂ©ket kapunk az eltĂ©rĂ©sre. A megoldĂĄs ebben az esetben egy kĂ©p, tehĂĄt a logikai Ă©rtĂ©knek megfelelĆ karakterĂ©t vĂĄlasszuk a stringnek (At), majd az elĆbb lĂĄtott mĂłdon generĂĄljuk azokat a pontokat, ahol a karaktersorozatunkat szĂ©tvagdaljuk.
(40*!6) _ ".#"@ 2 > _abs (1 _ a) - (!240)!40
Nincs mås dolgunk, mint hunyorogva kiolvasni a betƱket.
("####.#..#...##.####.###....##.####.####."
"...#.#.#.....#.#....#..#....#.#.......#."
"..#..##......#.###..###.....#.###....#.."
".#...#.#.....#.#....#..#....#.#.....#..."
"#....#.#..#..#.#....#..#.#..#.#....#...."
"####.#..#..##..#....###...##..#....####.")
Ez a feladat szĂĄmomra az eddigiek közĂŒl a legszemetebbnek tƱnik, bĂĄr tudom, hogy mĂ©g nem tartunk a felĂ©nĂ©l. Nem igazĂĄn K kompatibilis, ezĂ©rt fĂ©lrelibbentem a fĂŒggönyt a feladat megoldĂĄsĂĄnĂĄk menetĂ©rĆl, Ă©s nem csak egy letisztĂĄzott megoldĂĄst mutatok be. A feladat inputjĂĄban egy pszeudokĂłd szerepel, amit ha nagyon illedelmesek vagyunk, a programunkkal kellene Ă©rtelmezni. Ezt a lĂ©pĂ©st hĂĄtrĂĄbb rakom a teendĆk listĂĄjĂĄban, Ă©s a maradĂ©kra összpontosĂtok. Annak Ă©rdekĂ©ben, hogy a pszeudĂłkĂłdokat Ă©rtelmezni lehessen felhasznĂĄlom az Eval mƱveletet, mely egy sztringben szereplĆ kĂłdot futtat le - ezĂ©rt is Ă©rdemes interpretert hasznĂĄlni -, Ă©s minden majomhoz megadok egy-egy ilyen sztringet, melyek a p vĂĄltozĂłban kapnak helyet. A lista minden elemĂ©bĆl egy fĂŒggvĂ©ny generĂĄlĂłdik majd, ami megfelel annak, amit a feladat szövege leĂr, Ăgy lehet most a szĂĄmolĂĄsra összpontosĂtani.
p: ("{w:(x*19)%3; :[w!23;(3;w);(2;w)]}"; "{w:(x+6)%3; :[w!19;(0;w);(2;w)]}"; "{w:(x*x)%3; :[w!13;(3;w);(1;w)]}"; "{w:(x+3)%3; :[w!17;(1;w);(0;w)]}")
Mi a feladatunk egy ĂĄllapota? Tudnunk kell, hogy mely tĂĄrgy mely majomnĂĄl van, illetve az adott tĂĄrgyhoz milyen szintƱ aggodalom jĂĄrul. Ezzel a szinttel azonosĂtuk is ezt a tĂĄrgyat, mert mĂĄs informĂĄciĂłra nincs szĂŒksĂ©gĂŒnk. Azaz egy-egy tĂĄrgyhoz egy pĂĄros tartozik, melynek elsĆ tagja legyen a majom sorszĂĄma. A összes tĂĄrgyat Ăgy pĂĄrok egy listĂĄja Ărja le. Mely majomhoz kerĂŒl legközelebb egy tĂĄrgy? Ehhez le kell futtatni a majomhoz tartozĂł programot - azaz az index a majom sorszĂĄma, a pĂĄr elsĆ tagja lesz, mĂg egyetlen paramĂ©tere az aggodalom szintje, azaz a pĂĄr mĂĄsodik tagja. Ezt az f fĂŒggvĂ©ny Ărja le.
Sokkal egyszerƱbb lett volna, ha a majmok nem a rangsor szerint dolgoznĂĄnak - szigorĂșan egymĂĄs utĂĄn -, hanem pĂĄrhuzamosan. De mivel ez a feladat, elĆbb vĂĄlogassuk ki a listĂĄbĂłl, hogy mely tĂĄrgyak vannak az i.-dik majomnĂĄl. A sorszĂĄm lesz az x
argumentum, maga a lista egy-egy tagja - azaz egy pĂĄr - pedig az y
argumentum. Ha a pĂĄr elsĆ tagja egyezik a sorszĂĄmmal, akkor azzal most dolgoznunk kell. Az a vĂĄltozĂł egy bitlistĂĄt tartalmaz, ahol az igaz jelöli az izgalmas pĂĄrokat, amelyeket hamarosan feldolgozunk. Az a-hoz tartozĂł kĂłdrĂ©szlet kapcsos zĂĄrĂłjelĂ©n kĂvĂŒl Ășjabb elĆfordulĂĄsa van az x
-nek Ă©s y
-nak, amelyek mĂĄr mĂĄst jelentenek, mint belĂŒl. Egy parciĂĄlis fĂŒggvĂ©nyt alkottunk meg, melynek az i.-dik sorszĂĄmĂĄt a mostani y
szolgĂĄltatja, mĂg az x
a teljes listĂĄt jelöli. Az Each miatt pĂĄronkĂ©nt hasznĂĄlja fel az elĆbbi parcinĂĄlis fĂŒggvĂ©nyt. A b vĂĄltozĂłba mĂĄr az kerĂŒl, hogy mely majomhoz kerĂŒltek Ă©s aggodalmi szinten az i-dik majom ĂĄltal megvizsgĂĄlt tĂĄrgyak, ehhez a Where + At segĂtsĂ©gĂ©vel kivĂĄlasztottuk a pĂĄrokat, Ă©s mindre (Each) vĂ©grehajtottuk az f fĂŒggvĂ©nyt.
TermĂ©szetesen szĂŒksĂ©g van a többi majomnĂĄl lĂ©vĆ tĂĄrgyakra is. Ehhez az a vektort negĂĄljuk (Negate), majd ismĂ©t jön a Where-At pĂĄros, Ă©s a kivĂĄlogatott pĂĄrok a c vĂĄltozĂłba kerĂŒlnek. A fĂŒggvĂ©ny visszatĂ©rĂ©si Ă©rtĂ©ke a b Ă©s c "uniĂłja" lesz (Join). Ezzel kĂ©sz is a g fĂŒggvĂ©ny.
Ha az i tĂĄrolja a pĂĄrok listĂĄjĂĄt, Ă©s 4 majomrĂłl van szĂł összesen - ahogy a feladatismertetĆben, akkor a i g/0 1 2 3
leĂr egy majom-fordulĂłt.
MiutĂĄn a feladat kĂ©rdĂ©se, hogy melyik majom hĂĄny tĂĄrgyat vizsgĂĄlt meg, nem csak az egyes fordulĂłk vĂ©geredmĂ©nyĂ©re vagyunk kĂvĂĄncsiak, hanem a teljes folyamatra.
EzĂ©rt a tesztben szereplĆ feladat esetĂ©n 20 fordulĂłra lenne szĂŒksĂ©g, ami g nyolcvan futĂĄsĂĄt igĂ©nyli. Ăm miutĂĄn nem a vĂ©geredmĂ©ny - mely majomnĂĄl mi talĂĄlhatĂł a folyamat vĂ©gĂ©n - Ă©rdekel minket, elĂ©g lesz ennĂ©l eggyel kevesebb is, viszont az Over helyett Scan-t kell hasznĂĄlni, hogy a közbensĆ Ă©rtĂ©kekhez is hozzĂĄfĂ©rjĂŒnk. Azt, hogy körbe-körbe megy a szerep a majmok között, az elĆzĆ feladat megoldĂĄsĂĄnĂĄl lĂĄthatĂł Enumerate-Mod pĂĄrossal Ă©rjĂŒk el, s a pĂĄrok listĂĄjĂĄnak listĂĄjĂĄt a t vĂĄltozĂłba mentjĂŒk. A feladat megvĂĄlaszolĂĄsĂĄhoz arra van szĂŒksĂ©g, hogy adott majom hĂĄny tĂĄrggyal foglalkozott a folyamat sorĂĄn. TehĂĄt a pĂĄrok elsĆ tagjĂĄt kell kinyerni. Ezt az Each dupla alkalmazĂĄsĂĄval Ă©rjĂŒk el, illetve egy fĂŒggvĂ©nnyel, mely a First-öt hasznĂĄlja. Ennek erdmĂ©nyekĂ©ppen kapunk egy szĂ©p mĂĄtrixot. Arra vagyunk kĂvĂĄncsiak, hogy az elsĆ sorĂĄban hĂĄny nullĂĄs, a mĂĄsodik sorĂĄban hĂĄny egyes szerepel, Ă©s Ăgy szĂ©pen tovĂĄbb. Ehhez kĂ©szĂtĂŒnk egy vektort, melyben sorra ezek a szĂĄmok szerepelnek - Ășjfent az Enumerate-Mod pĂĄrossal -, s jöhet az egyenlĆsĂ©g, persze soronkĂ©nt (Each). Ezzel az egy Ă©rtĂ©k egy lista egyenlĆsĂ©gĂ©nĂ©l a lista minden elemĂ©t összehasonlĂtja a megadott elemmel, s kapunk egy bitsorozatot. Azt, hogy hĂĄny igaz/egyes szerepel a sorban, annak összegzĂ©sĂ©vel tudjuk meg: Add Over Each. Nincs mĂĄs dolgunk mint minden negyedik Ă©rtĂ©ket összeadni, mert Ăgy követik egymĂĄst az ugyanahhoz a majomhoz tartozĂł Ă©rtĂ©kek. Ez kicsit komplikĂĄlt, ezĂ©rt trĂŒkközĂŒnk egy kicsit, a vektorbĂłl egy mĂĄtrixot kĂ©szĂtĂŒnk a Reshape segĂtsĂ©gĂ©vel. Ha valamelyik mĂ©retet -1-nek vĂĄlasztjuk, akkor az automatikusan beĂĄllĂtĂłdik. Ăgy elĂ©g azt megadni, hogy a mĂĄtrixnak legyen 20 sora, utĂĄna összegezzĂŒk az egymĂĄshoz tartozĂł - egy oszlopban szereplĆ szĂĄmokat - megszokott mĂłdon. Ennek eredmĂ©nye kerĂŒl az u vĂĄltozĂłba.
Nics mĂĄs dolgunk, mint összeszorozni a kĂ©t legnagyobb Ă©rtĂ©ket, ehhez sorbarendezzĂŒk a szĂĄmokat (Grade Down+At), majd vesszĂŒk a kĂ©t elsĆt ebbĆl a rendezett listĂĄbĂłl, Ă©s vesszĂŒk a szorzatukat.
m:4
f:{ (. p[*x]) x[1]}
i:(0 79;0 98; 1 54; 1 65; 1 75; 1 74; 2 79; 2 60; 2 97; 3 74)
g:{a:{x=*y}[y;]'x; b:f'x@&a; c:x@&~a; b,c}
t: i g\((!-1+m*20)!m)
u:+/(20;-1)#+/'({*x}''t) =' ((!m*20)!m)
*/2#u@>u
Most mĂĄr foglalkozhatunk a pszeudokĂłdok feldolgozĂĄsĂĄval is! Egy-egy majomra vonatkozĂł kĂłd a következĆkĂ©ppen nĂ©z ki:
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Az input több hasonlĂłt tartalmaz, melyek egy-egy ĂŒres sorral vannak elvĂĄlasztva. EgyszerƱbb dolgunk lesz, ha az inputot ezek alapjĂĄn feldaraboljuk. Az ĂŒres sort is beleszĂĄmĂtva 7 sorbĂłl ĂĄll egy ilyen rĂ©sz, tehĂĄt vesszĂŒk a hĂ©t többszöröseit a teljes input hosszĂĄig, Ă©s ezeknĂ©l szĂ©tszabdaljuk az inputot (Cut), s ennek eredmĂ©nye lesz a d. SzĂŒksĂ©gĂŒnk volt a tĂĄrgyak listĂĄjĂĄra. Ezt a j fĂŒggvĂ©ny segĂtsĂ©gĂ©vel alkotjuk meg. A k vĂĄltozĂłba kigyƱjtjĂŒk a majom azonosĂtĂłjĂĄt, amihez szĂŒksĂ©ge lesz az elsĆ sor hosszĂĄra, ebbĆl kettĆt levonunk - egyet az indexelĂ©s kezdete, egyet meg a sorzĂĄrĂł kettĆspont miatt -, majd az ezen a pozĂciĂłn ĂĄllĂł szĂĄmjegyet szĂĄmmĂĄ alakĂtjuk. A mĂĄsodik sorban kettĆspontot követĆen vannak a szĂĄmok, ezĂ©rt megkeressĂŒk a kettĆspont helyĂ©t, majd ennĂ©l kettĆvel több karaktert eldobunk a sztring elejĂ©rĆl. A szĂĄmunkra fontos szĂĄmok a mĂĄr vesszĆvel elvĂĄlasztva szerepelnek, ami most nem zavarĂł, s trĂŒkkösen Ășjra az Eval-ra hivatkozunk, ez automatikus szĂĄmlistĂĄt generĂĄl. MĂĄr csak a pĂĄrokat kell kialakĂtani, melyhez a Join Each-right kombinĂĄciĂłt alkalmazzuk, ha az l valĂłdi listĂĄt tartalmaz. Abban a speciĂĄlis esetben, ha csak egy Ă©rtĂ©k szerepel itt (Atom), akkor az Enlist-et is hasznĂĄlni kell, hogy megfelelĆ szerkezetet kapjunk. VĂ©gĂŒl a Join-Over Each adja meg a vĂĄrt pĂĄrok listĂĄjĂĄt: ,/j'd
.
d:(7*!(1+(#c)%7)) _ c:0:"test11.txt"
j:{k: 0$x[0]@-2+#*x; l:.(2+x[1]?":") _ x[1]; :[@l;,(k;l); k,/:l]}
i:,/j'd
m:#d
Meg kellene alkotnunk az egyes majmok programjĂĄt. SzerencsĂ©re a szerkezet igen egyszerƱ, a harmadik sor egy kĂ©plettel Ă©r vĂ©get, a negyediktĆl a hatodik pedig egy-egy szĂĄmmal. A hĂĄrom utolsĂł sor feldolgozĂĄsĂĄhoz bevezetĂŒnk egy Ășj fĂŒggvĂ©nyt: e, amely a mĂĄsodik argumentumkĂ©nt megadott sztringbĆl csak az elsĆkĂ©nt megadott szĂĄm hosszĂșsĂĄgĂș szuffixĂ©t hagyja meg. Mehetne mindez a sztring hossza szerinti jĂĄtszadozĂĄssal Ă©s a Drop segĂtsĂ©gĂ©vel, de a Reverse-Take-Reverse rövidebben leĂrhatĂł, mert csak megfordĂtjuk a sztringet, levĂĄlasztjuk a kellĆ szĂĄmĂș karaktert most mĂĄr az elejĂ©rĆl, s visszafordĂtjuk, hogy nagyobb szĂĄmok esetĂ©n is helyes legyen.
A képletben a régi értéket az old
testesĂti meg, ezĂ©rt egy olyan sztringet rakunk össze, mely egy olyan fĂŒggvĂ©nyt generĂĄl, melynek a vĂĄltozĂłja pont ez, Ăgy pĂ©ldĂĄul egy ilyen sztring lehet a következĆ: {[old]w:(old * 19)%3; :[w! 7;(3;w);(2;w)]}
. Ăgy semmi dolgunk nincs a kĂ©plettel, egy az egyben bemĂĄsolhatjuk, csak le kell vĂĄlasztani a harmadik sorban az egyenlĆsĂ©gjel mögötti rĂ©szt. Kicsit pontosabban cĂ©lzunk, nem hagyjuk meg a kezdĆ szĂłközöt sem. A következĆ hĂĄrom sor megfelelĆ zĂĄrĂł karaktereit pedig a megfelelelĆ helyekre rakjuk be. Fontos figyelni arra, hogy ezeket sztingkĂ©nt kezeljĂŒk, ezĂ©rt nem csinĂĄltunk belĆlĂŒk szĂĄmokat. Ezek utĂĄn peding nincs mĂĄs dolgunk, mint a d összes elemĂ©re alkalmazzuk ezt a fĂŒggvĂ©nyt.
e:{|x#|y}
q:{"{[old]w:(", ((2+x[2]?"=") _ x[2]), ")%3; :[w!", e[2;x[3]], ";(", e[1;x[5]], ";w);(", e[1;x[4]], ";w)]}" }
p:q'd
A lényegi våltozås, hogy
- a hĂșsz kör helyett tĂzezerrel kell dolgoznunk; ezĂ©rt jĂł, hogy nem nĂ©gyzetes vagy exponenciĂĄlis bonyolĂșltsĂĄgĂș megoldĂĄsunk van,
- a hĂĄrommal törtĂ©nĆ osztĂĄs elmarad; emiatt egyre nagyobb szĂĄmokkal dolgozunk, melyek azĂ©rt a több ezernyi lĂ©pĂ©sben csak tĂșllĂ©pnek a programnyelv ĂĄbrĂĄzolĂĄsi tartomĂĄnyĂĄn.
MatematikuskĂ©nt könnyƱ dolgom van, a majmok programjaiban lĂ©vĆ tesztek kĂŒlönbözĆ prĂmszĂĄmokat hasznĂĄlnak, Ăgy ha szĂĄmokat helyettesĂtjĂŒk e prĂmek szorzata szerint vett maradĂ©kkal, akkor nem lĂ©pĂŒnk tĂșl az egĂ©szek Ă©rtelmezĂ©si tartomĂĄnyĂĄn. A tesztfeladat eset */23 19 13 17
azaz 96577
a szorzat; mĂg Ă©lesben ugyanez mĂĄr */7 19 5 11 17 13 2 3
azaz 9699690
lesz. Ezt a szorzatot berakjuk az a vĂĄltozĂłba. Az lenne a szĂ©p, ha most erre is ĂrnĂ©k egy fĂŒggvĂ©nyt, de a korĂĄbbi kĂłdrĂ©szletek alapjĂĄn Ășgy gondolom, hogy mĂĄr mindenki ki tudja nyerni a negyedik sor vĂ©gĂ©n talĂĄlhatĂł szĂĄmot szĂĄm formĂĄjĂĄban is, onnan meg egyĂ©rtelmƱ a fĂŒggvĂ©ny elkĂ©szĂtĂ©se, elemenkĂ©nti alkalmazĂĄsa d-re, s a szorzat alkalmazĂĄsa. Emiatt nĂ©zzĂŒk, mi mindennek kell vĂĄltozni a korĂĄbbi programban!
- A hĂĄrommal valĂł osztĂĄst az a szerinti maradĂ©kkal kell kicserĂ©lni a q fĂŒggvĂ©nyben,
- bevezetĂŒnk egy
r
konstanst, ami a körök szĂĄmĂĄt jelöli, ezzel lehet a megadott Ă©rtĂ©kekhez hasonlĂtani a sajĂĄt megoldĂĄsunkat, Ă©s a korĂĄbbi20
szĂĄmot mindenĂŒtt - azaz a t, az u Ă©s a v definĂciĂłjĂĄban - lecserĂ©ljĂŒk erre, azazr
-re.
q:{"{[old]w:(", ((2+x[2]?"=") _ x[2]), ")!a; :[w!", e[2;x[3]], ";(", e[1;x[5]], ";w);(", e[1;x[4]], ";w)]}" }
p:q'd
r:10000
t: i g\((!-1+m*r)!m)
v:(+/'({*x}''t) =' ((!m*r)!m))
u:+/(r;m)#v
HasonlĂłan kell eljĂĄrni, mint korĂĄbban, termĂ©szetesen ha ötszĂĄzszor több sorunk van, akkor negyedmilliĂłszor nagyobb szĂĄmot vĂĄrhatunk megoldĂĄskĂ©nt mint az elĆtt. SzerencsĂ©re ezt a 11 jegyƱ szĂĄmot a K automatikusan kezeli, nem kell BigInt-re ĂĄtĂrni a programunkat.
A soron következĆ feladatban a legrövidebb utat kell megtalĂĄlni. Valamilyen formĂĄban a Dijkstra algoritmus minden Ă©vben elĆfordul.
MiutĂĄn a hivatalos megvalĂłsĂtĂĄs kupacot hasznĂĄl, ezt inkĂĄbb hanyagolom,
ahogy a szĂ©lessĂ©gi keresĂ©st is, amely pedig a sor hasznĂĄlatĂĄra Ă©pĂt.
AzĂ©rt megoldĂĄsom nyomokban tartalmazza a szĂ©lessĂ©gi keresĂ©st, ĂĄm nem Ă©pĂt keresĆfĂĄt, hanem egy mĂĄtrixszal helyettesĂti,
amivel ugyan elveszĂtjĂŒk annak lehetĆsĂ©gĂ©t, hogy megadjuk a pontos utat, de ezt nem is vĂĄrja el a feladat.
MĂĄr az eredeti tĂ©rkĂ©p is egy mĂĄtrix formĂĄjĂĄban kaphatĂł meg, Ăgy egy hasonlĂł mĂĄtrixot kĂ©szĂtĂŒnk, melyben az egyes pontokhoz a hozzĂĄjuk tartozĂł mĂ©lysĂ©gi szĂĄmokat tĂĄroljuk.
Az inputban egyes betƱk az adott pont magassĂĄgĂĄt jelölik, Ăgy a
jelöli a legalacsonyabb, a z
a legmagasabb pontot.
Mivel a
Ă©s z
nem csak egyszer szerepelhet, egy S
Ă©s E
betƱ jelöli a start és a cél helyét.
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi
Ez a kĂ©t nagybetƱ bekavar a beolvasĂĄsba, Ăgy bevezetĂŒnk egy f fĂŒggvĂ©nyt, ami a kisbetƱket Ă©s Ă©s ezt a kĂ©t nagybetƱt is magassĂĄggĂĄ alakĂtja, felhasznĂĄlva a betƱkhöz tartozĂł ASCII kĂłdokat.
MiutĂĄn az input sztringek - azaz karakterlistĂĄk - listĂĄja, ezĂ©rt dupla Each segĂtsĂ©gĂ©vel tudunk feldolgozni kĂŒlön-kĂŒlön minden karaktert.
Viszont szĂŒksĂ©gĂŒnk van a kĂ©t nagybetƱ helyĂ©re, ehhez szintĂ©n egy fĂŒggvĂ©nyt kĂ©szĂtĂŒnk. A w fĂŒggvĂ©ny a Find utasĂtĂĄst hasznĂĄlja, s ezt rĂĄeresztjĂŒk az input minden sorĂĄra. Ha az adott sorban nem talĂĄlhatĂł a keresetett karakter - ami igen ĂĄltalĂĄnos -, akkor az utolsĂł karakter utĂĄni pozĂciĂłt kapjuk vissza. Mivel biztosak lehetĂŒnk abban, hogy a keresett karakter valamelyik sorban csak megjelenik, Ăgy a visszakapott szĂĄmok minimuma adja meg a keresett x
pozĂciĂłt. Az y
pizĂciĂłhoz pedig az kell, hogy a keresett minimum hol fordul elĆ, azaz a minimumra, Ă©s a szĂĄmsorra alkalmazzuk az Equals-t, ami egy bitvektort generĂĄl, Ăgy a Where visszaadja azt a pozĂciĂłt, ahol az egyetlen egyes talĂĄlhatĂł.
f:{:[x=83;0;x=69;26;x-97]}
i:0:"test12.txt"
i:0:"input12.txt"
a:f'' _ic i
w:{s:x?'y; u:&/s; v:&u=s;(u,v)}
ws:w[i;"S"]; we:w[i;"E"]
BevezetĂŒnk egy konstanst m nĂ©vvel, ami egy nagy szĂĄmot jelöl - olyan nagyot melyet a lĂ©pĂ©sek szĂĄmozĂĄsa nem Ă©rhet el - Ăgy ezzel tudjuk jelölni, hogy hol nem jĂĄrtunk mĂ©g.
Az a méreteit (Shape) követve létrehozunk egy hasonló d måtrixot, kezdetben ezzel a konstanssal feltöltve, majd megvåltoztatjuk az S
helyĂ©n, a kiindulĂłpontban egy egyest szerepeltetĂŒnk.
m:1000
d:(^a)#m
d[ws[0];ws@1]:1
A feladatnak megfelelĆen akkor tudunk egy szomszĂ©dos mezĆre lĂ©pni, ha az maximum egy Ă©rtĂ©kkel van magasabban. ĂsszpontosĂtjuk a figyelmĂŒnket egy irĂĄnyra, modjuk dĂ©lre. Minden mezĆt az "alatta"/tĆle dĂ©lre lĂ©vĆvel kell összehasonlĂtani. Ehhez toljuk el az egĂ©sz mĂĄtrixot eggyel feljebb: azaz töröljĂŒk az elsĆ sorĂĄt (Drop), s hogy a mĂ©retekkel ne legyen problĂ©ma, majd alul egĂ©szĂtsĂŒk ki egy konstansokbĂłl ĂĄllĂł sorral! Ez utĂłbbihoz szĂŒksĂ©g van a mĂĄtrix szĂ©lessĂ©gĂ©re, azaz egy-egy sorĂĄnak hosszĂĄra. Ezt a mĂ©retĂ©t (Shape) jelzĆ szĂĄmpĂĄr mĂĄsodik tagja adja meg, azaz itt is eldobhatjuk az elsĆt, s a Take segĂtsĂ©gĂ©vel alakĂthatunk ki a konstansunkbĂłl egy vektort, ĂĄm ne feletkezzĂŒnk meg az Enlist-rĆl, mellyel a vektor mĂĄtrixszĂĄ minĆsĂŒl ĂĄt, Ă©s mĂĄr illeszhetĆ (Join) az elĆbbi csonkhoz. EbbĆl az eltolt mĂĄtrixbĂłl kivonva az eredetit megkapjuk az egymĂĄs alatt szereplĆ mezĆk tĂĄvolsĂĄgĂĄt, s ott lehet tovĂĄbblĂ©pni, ahol maximum 1 ez a tĂĄvolsĂĄg, magyarul kisebb, mint 2. Ez az összehasonlĂtĂĄs egy bitmĂĄtrixot eredmĂ©nyez.
Annak Ă©rdekĂ©ben, hogy ezt a mƱveletsort ne kelljen megismĂ©telni a fennmaradĂł hĂĄrom irĂĄnyra a programkĂłdban, ezt a bitmĂĄtrix generĂĄlĂĄst az n fĂŒggvĂ©nyben eltĂĄroltuk, Ă©s ezt alkalmazzuk az eredeti feladatunk a mĂĄtrixĂĄnak kĂŒlönfĂ©le tĂŒkrözĂ©seire, melyek vĂ©gĂŒl kiadjĂĄk a nĂ©gy irĂĄnyt. Mivel ezeket a bitmĂĄtrixokat Ășjra Ă©s Ășjra felhasznĂĄljuk, elmentjĂŒk nĂ©gy vĂĄltozĂłba:
n:{s:2>((1 _ x), ,(1 _ ^x)#m) - x}
ad:n[a]; au:n[|a]; ar:n[+a]; al:n[|+a]
Ahol egyes bitek vannak az ad mĂĄtrixban - mely a dĂ©l felĂ© haladĂĄsi lehetĆsĂ©geket tĂĄrolja -, ott a d mĂĄtrixban feljegyzett lĂ©pĂ©sszĂĄmnĂĄl az alatta lĂ©vĆ mezĆben feljegyzĂ©sre kerĂŒlĆ eggyel nagyobb lesz - feltĂ©ve, ha oda mĂĄshonnan nem jutottunk mĂ©g el. Ha adott mezĆbĆl tovĂĄbblĂ©phetnĂ©nk, de a d megfelelĆ mezĆje nagy szĂĄmot tartalmaz, akkor felesleges figyelembe venni. Ha pedig valahonnan nem lehet tovĂĄbblĂ©pni - az ad ott nullĂĄst tartalmaz, akkor az a nagy szĂĄmmal tudjuk jelezni.
A g fĂŒggvĂ©ny a következĆkĂ©ppen mƱködik: megkapja az ad Ă©s d mĂĄtrixokat, veszi ezeknek a pontonkĂ©nti szorzatĂĄt - tehĂĄt ahol az ad-ban 1 van, ott d Ă©rtĂ©ke megmarad, ahol pedig 0, ott nullĂĄzzuk, majd ad negĂĄltjĂĄnak szorzatĂĄt d-vel amit hozzĂĄ is adunk az elĆbbi szorzathoz, azaz a korĂĄbban kapott nullĂĄk helyett mĂĄr nagy szĂĄmok szerepelnek. Az Ăgy kapott mĂĄtrix utolsĂł sorĂĄt eldobjuk - pontosabban vesszĂŒk az elĆtte lĂ©vĆ sorokat, s hogy letoljuk ezt a csonkot, mĂ©g kiegĂ©szĂtjĂŒk egy elsĆ sorral. Annak Ă©rdekĂ©ben, hogy a lĂ©ptetĂ©s megtörtĂ©njen, a csonk elemeit eggyel növeljĂŒk az összeillesztĂ©s elĆtt.
g:{(,(1 _ ^y)#m),1+((*^y)-1)#((x*y)+(m*~x))}
Ezzel mĂĄr tudjuk kezelni a dĂ©lre törtĂ©nĆ lĂ©pĂ©seket. De ha a d mĂĄtrixot tĂŒkrözzĂŒk ide-oda, akkor a többi irĂĄnyyal is elboldogulunk. Persze az eredmĂ©nyt illik visszaforgatni. VĂ©gĂŒl tekintjĂŒk a nĂ©gy irĂĄnyban megtehetĆ lĂ©pĂ©seket, valamint a kiindulĂł ĂĄllapotot, Ă©s tekintjĂŒk ezek minimumĂĄt. Ennek mi az Ă©rtelme? A d az adott pontba eljutĂĄs minimĂĄlĂĄs lĂ©pĂ©sszĂĄmĂĄt adja meg. Oda-vissza lĂ©pĂ©ssel a lĂ©pĂ©sszĂĄm mĂĄr nagyobb lenne, de a minimum miatt nem Ărjuk felĂŒl. Ha viszont mĂ©g felfedezetlen terĂŒletre jutunk, az ott szereplĆ nagy szĂĄmot egy kisebbre cserĂ©ljĂŒk le. Ha valahova több irĂĄnybĂłl is el lehet jutni, a versenyhelyzet miatt mindig a legkisebb szĂĄm fog bekerĂŒlni.
h:{gd:g[ad;x]; gu:|g[au;|x]; gr:+g[ar;+x]; gl:+|g[al;|+x]; x&gd&gu&gl&gr}
KorĂĄbban mĂĄr hasznĂĄltuk a xf/y
Ă©s xf\y
szerkezeteket, ennek van egyargumentumĂș pĂĄrja is. Mivel az a mĂĄtrixbĂłl generĂĄlt bitmĂĄtixok nem vĂĄltoznak, a h fĂŒggvĂ©nynek csak egy argumentuma van, a d mĂĄtrix; s egy hasonlĂł, csak egy lĂ©pĂ©ssel kiegĂ©szĂtett mĂĄtrixot ad vissza, Ăgy arra megint alkalmazhatĂł a h fĂŒggvĂ©ny, s ez akkor ĂĄll meg, ha Ășjra ugyanazt az eredmĂ©nyt kapjuk vissza.
Ha mĂĄr leĂĄllt a folyamat, akkor csak ki kell olvasni az E
betƱ helyĂ©n ĂĄllĂł szĂĄmot, s mivel egytĆl indult a szĂĄmozĂĄs, ebbĆl egyet ki kell vonni:
z:h/d
z[*we;we@1]-1
A feladat mĂĄsodik felĂ©ben azt a pozĂciĂłt kell megkeresni, amelyhez a
tartozik, Ă©s melybĆl a legkevesebb lĂ©pĂ©ssel Ă©rhetĆ el E
. Persze le lehetne futtatni az elĆbbi megoldĂĄst minden egyes olyan pozĂciĂłbĂłl, melyhez a
tartozik, de az elég munkås lenne.
InkĂĄbb fordĂtsuk meg a helyzetet, Ă©s nĂ©zzĂŒk meg, hogy az E
-bĆl hĂĄny lĂ©pĂ©sbĆl lehet elĂ©rni az egyes pozĂciĂłkat. Mihez kell ezen vĂĄltoztani. TermĂ©szetesen mĂĄs lesz a kezdĆpont, nem az ws-t hanem a we-t kell hasznĂĄlni a d mĂłdosĂtĂĄsĂĄhoz. Az n fĂŒggvĂ©ny szabta meg, hogy mikor lehet tovĂĄbblĂ©pni. Ott a feltĂ©tel az volt, hogy az eltĂ©rĂ©s kisebb mint kettĆ. Ha megfordĂtjuk a keresĂ©s irĂĄnyĂĄt, akkor fordĂtva vĂ©gezzĂŒk el a kivonĂĄst, Ăgy mĂłdosĂtott fĂŒggvĂ©nyben nagyobb mint minusz kettĆ szerepel helyette. A z-be most is begyƱjtjĂŒk az összes szĂĄmot. Viszont ezek közĂŒl csak az Ă©rdekes, melyhez a
tartozik.
A kĂłdolĂĄsban ez a 0
Ă©rtĂ©ket jelenti, tehĂĄt az a kĂ©rdĂ©s, hogy az a vektorban hol szerepel nulla. Ez Ășjra bitmĂĄtrixot ad, ezzel beszorozva a z mĂĄtrixot, mĂĄr majdnem kĂ©sz is vagyunk. Sajnos vannak olyan pozĂciĂłk, melyek a szabĂĄlyok szerint nem elĂ©rhetĆk, közöttĂŒk olyan is, melyhez a
tartozik, itt az m Ă©rtĂ©k talĂĄlhatĂł, illetve ott vannak a nullĂĄk. A Range segĂtsĂ©gĂ©vel felsorolhatjuk az egyedi Ă©rtĂ©keket - melyeket elmentĂŒnk az y vĂĄltozĂłba -, de ehhez a mĂĄtrixbĂłl vektort kell csinĂĄlni, amit a Join-Over segĂtsĂ©gĂ©vel Ă©rhetĂŒnk el. RendezzĂŒk sorba a szĂĄmokat a megszokott mĂłdon, s a nullĂĄt követĆ szĂĄmot kellene visszaadni, pontosabban ennĂ©l eggyel kisebbet, mert tovĂĄbbra is eggyel indult a szĂĄmozĂĄs.
d[we[0];we@1]:1
n:{s:-2<((1 _ x), ,(1 _ ^x)#m) - x}
y:?,/(a=0)*z
-1+y[<y]@1