Skip to content

Advent of Code solutions in Kona (in Hungarian)

License

Notifications You must be signed in to change notification settings

aszalosl/aoc2022

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 

Repository files navigation

Advent of Code 2022 in Kona (in Hungarian)

Bevezetés

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.

1. Calorie Counting

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]

2. Rock Paper Scissors

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

3. Rucksack Reorganization

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

4. Camp Cleanup

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

5. Supply Stacks

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

6. Tuning Trouble

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

7. No Space Left On Device

$ 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])

8. Treetop Tree House

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

9. Rope Bridge

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.

10. Cathode-Ray Tube

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.

("####.#..#...##.####.###....##.####.####."
 "...#.#.#.....#.#....#..#....#.#.......#."
 "..#..##......#.###..###.....#.###....#.."
 ".#...#.#.....#.#....#..#....#.#.....#..."
 "#....#.#..#..#.#....#..#.#..#.#....#...."
 "####.#..#..##..#....###...##..#....####.")

11. Monkey in the Middle

FelĂŒtĂ©s

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)]}")

SzĂĄmolgatunk

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

Az input értelmezése

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

Måsodik rész

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ĂĄbbi 20 szĂĄmot mindenĂŒtt - azaz a t, az u Ă©s a v definĂ­ciĂłjĂĄban - lecserĂ©ljĂŒk erre, azaz r-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.

12. Hill Climbing Algorithm

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

13. Distress Signal

14. Regolith Reservoir

15. Beacon Exclusion Zone

16. Proboscidea Volcanium

17. Pyroclastic Flow

18. Boiling Boulders

19. Not Enough Minerals

20. Grove Positioning System

21. Monkey Math

22. Monkey Map

23. Unstable Diffusion

24. Blizzard Basin

25. Full of Hot Air

About

Advent of Code solutions in Kona (in Hungarian)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published