Néha egy sorozatot egyetlen értékké szeretnél összevonni, néha viszont minden köztes értéket látni szeretnél, amelyet az összevonás közben előállít. A Factor ezeket két eszközre bontja: az egyetlen értékre hajtogatáshoz a reduce-t (a sequences szótárban), a futó változathoz pedig a math.statistics kumulatív családját.
reduce - az általános hajtogatásreduce ( seq init quot: ( prev elt -- next ) -- result )
A reduce egyesével halad végig a sorozaton, magával hordozva egy futó eredményt (az akkumulátort), és azt egy kétargumentumú quotationnek adja át. A quotation megkapja a futó akkumulátort és a következő elemet; ami a vermen marad, az lesz az új akkumulátor.
USING: math sequences ;
{ 1 2 3 4 } 0 [ + ] reduce . ! => 10
{ 1 2 3 4 } 1 [ * ] reduce . ! => 24
A nem nulla kezdőérték és a saját kombináló függvény azok a részei a reduce-nak, amelyeket a sum és a product nem tud elérni. Például egy sorozat legnagyobb értéke, egy alapértelmezett értékkel arra az esetre, ha semmi sem múlja felül:
USING: math.order ;
{ 3 1 -4 5 -2 } 0 [ max ] reduce . ! => 5
{ -3 -1 -4 } 0 [ max ] reduce . ! => 0
A 0 kezdőérték részt vesz az összehasonlításban: akkor lesz belőle az eredmény, amikor minden elem veszít, így a csupa negatív értékből álló sorozat is 0-t ad eredményül, nem pedig egy tetszőleges legkisebb értéket.
Néha minden köztes eredményre szükséged van, nem csak a végsőre. A math.statistics kumulatív családja egy ugyanolyan hosszú sorozatot ad vissza, mint a bemenet, ahol minden pozíció az adott pozícióig tartó előtagra végzett redukció:
cum-sum ( seq -- newseq ) ! running total
cum-product ( seq -- newseq ) ! running product
cum-min ( seq -- newseq ) ! running minimum
cum-max ( seq -- newseq ) ! running maximum
USING: math.statistics ;
{ 3 1 4 1 5 9 2 6 } cum-sum . ! => { 3 4 8 9 14 23 25 31 }
{ 1 2 3 4 } cum-product . ! => { 1 2 6 24 }
{ 3 1 4 1 5 9 2 6 } cum-min . ! => { 3 1 1 1 1 1 1 1 }
{ 3 1 4 1 5 9 2 6 } cum-max . ! => { 3 3 4 4 5 9 9 9 }
Hasznos minta a láncolt kumulatív redukció: az egyik kimenete maga is sorozat, amely készen áll arra, hogy egy másikba kerüljön. Így a „futó összegzés futó összegzése” két szóval kifejezhető. A kombinációk rugalmasak, párosítsd őket aszerint, hogy az egyes lépések mit összegeznek.
produce - a kihajtogatásA reduce egy sorozatot fogyaszt el egyetlen értékké. A produce (a sequences szótárban) az ellenkező irányba megy: előállít egy sorozatot egy kezdőértékből, ismételt vizsgálattal és léptetéssel:
produce ( pred quot -- seq )
Minden iteráció először lefuttatja a pred-et az aktuális állapoton; ha igaz értéket ad vissza, meghívódik a quot, hogy előállítsa a következő elemet és frissítse az állapotot. Amikor a pred f-et ad vissza, az iteráció leáll, és a begyűjtött elemek visszaadásra kerülnek.
Klasszikus példa a Fibonacci-sorozat (minden szám az előző kettő összege). A futó állapot az (a, b) pár. Minden lépés kiadja a b-t, majd a párt (b, a + b)-re cseréli:
USING: kernel math sequences ;
! Fibonacci numbers strictly below 100:
0 1 [ dup 100 < ] [ tuck + over ] produce 2nip .
! => { 1 1 2 3 5 8 13 21 34 55 89 }
A futó állapot két értéket fog át, ezért a törzs a tuck-kal (a kernel szótárban; ez a háromelemű keverés, amely a legfelsőt a második alá másolja) lépteti a párt, a végén pedig a 2nip (szintén a kernel szótárban, a nip kételemű megfelelője) tesz rendet. A hívást balról jobbra olvasva:
[ dup 100 < ] predikátum a pár tetejére pillant (a következő kiadandó számra), és addig folytatja, amíg az még a korlát alatt van.[ tuck + over ] törzs (b, a + b)-re lépteti az állapotot, és kiadja a b-t, így három érték marad a vermen: alul az új pár, felül a kiadott szám.produce leáll, a két záró értéket (a végső párt) a 2nip eldobja, és csak az előállított sorozat marad.A produce a reduce pontos duálisa: ahol a reduce egy sorozatot hajtogat le egyetlen értékig, ott a produce egy értéket hajtogat ki sorozattá.
Te vagy a könyvtáros, aki az olvasói számlák főkönyvét vezeti. Hetente kétféle munka kerül az asztalodra:
Minden héten összesíted a könyveket: egy záró egyenleget, miután a kéréseket teljesítetted, a tranzakciókból számított napi folyó egyenleget, valamint egy folyó mélypontot, amely megjelöli azokat az időszakokat, amikor megugrottak a bírságok.
Definiáld a protected-balance függvényt úgy, hogy egy opening egyenleget és requests (előjeles összegek) tömbjét kapja, és adja vissza a záró egyenleget, miután minden kérést sorban teljesítettél. Egy olyan kérés, amely nulla alá csökkentené az egyenleget, csak a rendelkezésre álló összegig teljesül, így a folyó egyenleg nullánál áll meg.
100 { 50 -200 30 } protected-balance .
! => 30
500 { 100 -300 -250 } protected-balance .
! => 50
0 { -10 50 } protected-balance .
! => 50
Definiáld a running-balance függvényt úgy, hogy transactions tömbjét kapja, és egy ugyanilyen hosszú sorozatot adjon vissza, amelynek i-edik eleme az első i+1 tranzakció utáni egyenleg (nulla kezdőegyenleghez viszonyítva).
{ 50 -30 -20 100 } running-balance .
! => { 50 20 0 100 }
Definiáld a least-balance-so-far függvényt úgy, hogy transactions tömbjét kapja, és egy ugyanilyen hosszú sorozatot adjon vissza, amelynek i-edik eleme az i pozícióig (beleértve) látott legalacsonyabb folyó egyenleg. Ez a folyó mélypont, ami hasznos, hogy kiszúrjuk azokat a napokat, amikor kockázatosnak tűnt a számla.
{ 50 -30 -20 100 } least-balance-so-far .
! => { 50 20 0 0 }
{ 200 -50 -100 -200 } least-balance-so-far .
! => { 200 150 50 -150 }
A könyvtár bírságamnesztia-programot indít: az olvasó fennálló tartozása minden fizetési időszakban feleződik, amíg el nem éri vagy alá nem esik egy elengedési küszöbnek. Definiáld a halve-until függvényt úgy, hogy egy principal és egy target értéket kapjon, és adja vissza a felezett értékek sorozatát (egész osztást használva), az első felezéstől kezdve, addig folytatva, amíg a folyó érték szigorúan target fölött van. Az utolsó kiadott érték lesz az első, amely eléri vagy aláesik a target-nek.
100 5 halve-until .
! => { 50 25 12 6 3 }
64 1 halve-until .
! => { 32 16 8 4 2 1 }
3 5 halve-until .
! => { }
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Factor nyelvet 47 fogalom163 feladat segítségével, valódi emberi mentorálással, mindez ingyen.