Kurzusok
/
Factor
Factor
/
Feladatok
/
Kevert gyümölcslevek
Kevert gyümölcslevek

Kevert gyümölcslevek

Tanulófeladat

Bevezetés

Vannak olyan ciklusok, amelyeket nem lehet úgy megírni, hogy »csináld ezt egy sorozat minden elemére«, hanem addig kell menni, amíg valamilyen feltétel át nem billen. A Factor while kombinátora épp erre való: egy predikátum quotation azt mondja, hogy »tovább?«, egy body quotation elvégzi egy lépés munkáját, a while pedig addig ismétel, amíg a predikátum f-et nem ad.

while és until

while ( pred body -- )
until ( pred body -- )

A pred és a body is quotation, és mindkettő az adatvermen dolgozik. A while addig ismétel, amíg a pred igaz értéket hagy maga után; az until ennek az ellenkezője: addig ismétel, amíg a pred igazzá nem válik (vagyis amíg a pred f-et hagy).

Egyetlen állapotérték is áramolhat a vermen a predikátum és a body között:

USING: kernel math ;

5 [ dup 0 > ] [ dup . 1 - ] while drop
! prints 5 4 3 2 1

Nyomkövetés: a dup 0 > predikátum ránéz a futó számlálóra, a dup . 1 - body kiírja és eggyel csökkenti, a ciklus pedig leáll, amint a számláló eléri a 0-t. A záró drop eldobja ezt a végső 0-t a veremből.

while*: megőrzi a predikátum értékét

while* ( pred body -- )

A while számára csak az számít, hogy a predikátuma igaz értéket hagyott-e, magát az értéket eldobja, mielőtt lefuttatná a bodyt. A while* ezzel szemben átadja ezt az értéket a bodynak. Akkor nyúlj hozzá, amikor a feltétel és a body ugyanazt a frissen kiszámított dolgot akarja használni: egy keresést, egy egyezést, egy beolvasott tokent.

Itt minden név a lánc következő elemére mutat. A predikátum kikeresi az aktuális nevet, és amíg van következő név, a while* átadja azt a bodynak, amely kiírja, majd onnan folytatja:

USING: assocs kernel locals prettyprint ;

:: print-chain ( start links -- )
    start [ links at ] [ dup . ] while* ;

"a" H{ { "a" "b" } { "b" "c" } } print-chain
! prints "b" then "c"

A links at visszaadja a következő nevet, vagy f-et, ha egy névhez már nem tartozik bejegyzés. Amíg nevet ad vissza, a while* átadja azt a dup .-nak, amely kiírja, és a következő keresés kulcsaként hagyja a vermen. Az első f leállítja a ciklust, a while* eldobja, így nem marad semmi a vermen.

Több állapotérték lokális változókkal

Amikor a ciklus egynél több értéket hordoz magával, mondjuk egy hátralévő listát és egy futó összeget, a veremmel való zsonglőrködés zajossá válik. A legtisztább minta, ha lokálisokat deklarálunk ::-tal:

:: word ( inputs -- outputs ) ... ;

A bodyban a :> name! egy módosítható lokálist ad hozzá; olvasáshoz a name-et, íráshoz a name!-ot használjuk (ez utóbbi leveszi az új értéket a veremről, és hozzárendeli).

USING: kernel locals math sequences ;

! Walk a sequence from the front, summing as we go
:: sum-by-hand ( seq -- total )
    seq :> rest!
    0   :> running!
    [ rest empty? ] [
        rest unclip [ rest! ] dip
        running + running!
    ] until
    running ;

Ez a két lokális (rest és running) lefedi a teljes ciklus állapotát: a predikátum megnézi őket, a body frissíti őket, a végső érték pedig a végén adódik vissza.

Az unclip ( seq -- rest first ) lehántja egy sorozat első elemét, ami kényelmes, amikor a ciklus iterációnként egy elemet akar elfogyasztani a listából. A [ rest! ] dip alak a rest-et a hátralévő végére frissíti, miközben az imént kivett elemet a vermen hagyja, hogy a body használhassa.

Utasítások

A barátod, Li Mei gyümölcslébárt vezet, ahol finom kevert gyümölcsleveket árul. Gyakori vendég vagy a boltjában, és rájöttél, hogy egy kis Factor-kóddal megkönnyíthetnéd az életét.

1. Határozd meg, mennyi ideig tart egy gyümölcslé összekeverése

Li Mei szeret előre megmondani a vendégeinek, mennyit kell várniuk egy-egy gyümölcslére a menüből. Nehezen jegyzi meg a pontos számokat, mert a gyümölcslevek összekeverése különböző ideig tart:

  • A "Pure Strawberry Joy" 0.5 percet vesz igénybe.
  • Az "Energizer" és a "Green Garden" 1.5 percet vesz igénybe.
  • A "Tropical Island" 3 percet vesz igénybe.
  • Az "All or Nothing" 5 percet vesz igénybe.
  • Minden más ital (például az akciós ajánlatok) 2.5 percet vesz igénybe.

Definiáld a time-to-mix-juice függvényt úgy, hogy elvesz egy gyümölcslénevet a veremről, és visszaadja, hány percig tart összekeverni azt az italt.

"Tropical Island" time-to-mix-juice .
! => 3

"Berries & Lime" time-to-mix-juice .
! => 2.5

2. Töltsd fel a lime-cikkek készletét

Li Mei sok kreációjához kell lime-cikk, akár hozzávalóként, akár a díszítés részeként. Ezért amikor reggel elkezdi a műszakot, gondoskodik róla, hogy a lime-cikkeket tartó láda tele legyen a következő napra.

Definiáld a wedges-from-lime függvényt, amely egy lime méretét kapja, és visszaadja, hány cikk lesz belőle: egy "small" méretű lime-ból 6, egy "medium" méretűből 8, egy "large" méretűből 10.

Ezután definiáld a limes-to-cut függvényt, amely a needed cikkek számát és a limes tömböt kapja (a lime-ok méretei vágási sorrendben). A függvény egyesével, sorrendben vágja fel a lime-okat, és leáll, amint vagy összegyűlt elég cikk, vagy elfogytak a lime-ok. Add vissza, hány lime-ot kellett felvágni.

25 { "small" "small" "large" "medium" "small" } limes-to-cut .
! => 4

3. Sorold fel, mennyi ideig tart az egyes rendelések összekeverése a sorban

Li Mei szereti nyomon követni, mennyi ideig tart majd összekeverni azokat a rendeléseket, amelyekre a vendégek várnak.

Definiáld az order-times függvényt, amely egy rendeléstömböt kap, és visszaad egy tömböt, amelyben minden rendelés összekeverésének ideje szerepel, ugyanabban a sorrendben.

{ "Energizer" "Tropical Island" } order-times .
! => { 1.5 3 }

4. Zárd le a műszakot

Li Mei mindig délután 3-ig dolgozik. Utána az alkalmazottja, Dmitry veszi át a helyét. Gyakran előfordul, hogy Li Mei műszakjának végén vannak olyan italok, amelyeket már megrendeltek, de még nem készültek el; ilyenkor Dmitry készíti el a maradék gyümölcsleveket.

Hogy a váltás könnyebb legyen, definiáld a remaining-orders függvényt, amely Li Mei műszakjából hátralévő time-left percet és az orders tömböt kapja (a megrendelt, de még el nem készített gyümölcslevelek). Add vissza azokat a rendeléseket, amelyeket Dmitrynek át kell vennie, vagyis azokat, amelyeket Li Mei nem tud elkezdeni a műszakja vége előtt.

A time-left mindig nagyobb, mint 0. A rendeléseket abban a sorrendben készítik el, ahogyan a tömbben szerepelnek. Ha Li Mei elkezd egy gyümölcslevet, mindig be is fejezi, még akkor is, ha kicsit tovább kell dolgoznia. Ha minden rendelés elkezdésére van ideje, adj vissza egy üres tömböt.

5 { "Energizer" "All or Nothing" "Green Garden" } remaining-orders .
! => { "Green Garden" }
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Factor Exercism

Készen állsz elkezdeni a(z) Kevert gyümölcslevek feladatot?

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.