المسارات
/
Factor
Factor
/
التمارين
/
سيارات، تجمّعوا!
سيارات، تجمّعوا!

سيارات، تجمّعوا!

تمرين تعلّمي

مقدمة

يقدّم هذا التمرين الجمل الشرطية: الاختيار بين مسارين أو أكثر من مسارات العمل بناءً على قيمة. وهو يبني على القيم المنطقية التي تعرّفت عليها في تسلل أنالين وعلى الحساب على الأعداد الصحيحة من تحويل العملات.

كلمات المقارنة

توجد هذه كلها في math (وفي kernel بالنسبة إلى =):

=  ( x y -- ? )    ! equal
<  ( x y -- ? )    ! less than
<= ( x y -- ? )    ! less than or equal
>  ( x y -- ? )    ! greater than
>= ( x y -- ? )    ! greater than or equal
3 3 = .     ! => t
2 3 < .     ! => t
3 3 <= .    ! => t
3 4 = not . ! => t    (inequality: combine = with not)

‏zero? (في math) اختصار لفحص 0 = الشائع، فهي تستهلك العدد وتدفع ما إذا كان صفرًا:

zero? ( n -- ? )    ! t when n is 0

فحوص النطاق

‏between? (في math.order) تفحص ما إذا كانت قيمة تقع ضمن نطاق شامل للطرفين. وهي مفيدة عندما يعتمد إجراء ما على النطاق الذي يقع فيه العدد:

between? ( x lo hi -- ? )    ! lo <= x <= hi (inclusive)
5 1 10 between? .    ! => t
0 1 10 between? .    ! => f
10 1 10 between? .   ! => t   (inclusive at both ends)

ستراها غالبًا كشرط في cond، مثل dup 1 4 between?، لاختيار فرع حسب النطاق بدلًا من قيمة واحدة.

الاقتباسات

تُنتج كلمات المقارنة أعلاه قيمًا منطقية؛ ولكي تتصرّف بناءً على قيمة منطقية، تسلّم الجملة الشرطية اقتباسًا واحدًا أو أكثر. الاقتباس مقتطف من الكود محاط بأقواس مربعة، [ ... ]. وكتابته تدفع الكود إلى المكدس كقيمة بدلًا من تنفيذه، ثم تقرّر كلمة مثل if أي اقتباس يُنفَّذ.

[ neg ]   ! a quotation that negates the top of the stack
[ ]       ! the empty quotation — does nothing

يتناول تمرين لاحق الاقتباسات بالتفصيل؛ أما الآن، فاقرأ [ ... ] على أنها «الكود الذي سيُنفَّذ لهذا الفرع».

if, when, unless

‏if (في kernel) تأخذ قيمة منطقية واقتباسين. تُنفّذ الاقتباس الأول عندما تكون القيمة المنطقية صحيحة، والثاني عندما تكون خطأ:

if ( ? then-quot else-quot -- )
: abs ( x -- y ) dup 0 < [ neg ] [ ] if ;

تُنفّذ when اقتباسها فقط عندما تكون القيمة المنطقية صحيحة، وتُنفّذ unless اقتباسها فقط عندما تكون خطأ:

when   ( ? quot -- )
unless ( ? quot -- )

if* وwhen* وunless*

تتعامل ثلاث صيغ من drop مع القيمة المنطقية باعتبارها قيمة تستحق الإبقاء عليها عندما تكون صحيحة، وهذا مفيد عندما تُرجع كلمة «الشيء أو f»:

if*     ( ? true false -- )    ! truthy: true is called WITH ? on stack
when*   ( ? true       -- )    ! truthy: true is called WITH ? on stack
unless* ( ? false      -- )    ! falsy: false runs and pushes a default

‏if* هي الصيغة ذات الفرعين. يُستدعى فرع الصحة والقيمة لا تزال على المكدس، ويُستدعى فرع الخطأ بدونها:

42 [ ] [ "nothing" ] if* .   ! prints 42
f  [ ] [ "nothing" ] if* .   ! prints "nothing"

‏unless* هي التعبير القياسي لـ«قيمة أو افتراضي». إذا كانت القيمة صحيحة تُترك كما هي، وإذا كانت f تُسقَط القيمة ويُنفَّذ الاقتباس ليدفع قيمة بديلة:

"hello" [ "anonymous" ] unless* .   ! => "hello"
f       [ "anonymous" ] unless* .   ! => "anonymous"

‏when* هي الصيغة ذات الفرع الواحد من if*: فهي تُنفّذ اقتباسها (والقيمة لا تزال على المكدس) فقط عندما تكون القيمة صحيحة، وتُسقط القيمة ببساطة عندما تكون f. استخدمها لطيّ نتيجة «الشيء أو f» في قيمة جارية دون عناء معالجة حالة f:

0 41 [ + ] when* .   ! => 41   (truthy: 41 added to the running total)
0 f  [ + ] when* .   ! => 0    (falsy: f dropped, total left untouched)

cond

عندما تكون لديك عدة إجراءات بديلة للاختيار بينها، فإن cond (في combinators) هي الخيار الطبيعي. تأخذ مصفوفة من أزواج { predicate body } وتُنفّذ جسم أول شرط يُنتج قيمة صحيحة:

USING: combinators ;

: classify ( n -- label )
    {
        { [ dup 0 <  ] [ drop "negative" ] }
        { [ dup 0 =  ] [ drop "zero"     ] }
        [ drop "positive" ]
    } cond ;

بعض التفاصيل الجديرة بالذكر:

  • تُجرَّب الأزواج بالترتيب، وأول تطابق يفوز.
  • المدخل الذي لا يحتوي على شرط (اقتباس واحد فقط) في النهاية يعمل كحالة افتراضية.
  • يفحص كل شرط المدخل، لكن ينبغي أن يترك مكدس البيانات كما وجده، والصيغة المعتادة هي dup ... <test>.
  • يستقبل جسم الزوج المختار المكدس نفسه الذي رآه الشرط، لذا يبدأ عادةً بإسقاط المدخل ودفع النتيجة.

التعليمات

في هذا التمرين ستكتب كودًا لتحليل الإنتاج في خط تجميع في مصنع سيارات. يمكن أن تتراوح سرعة خط التجميع بين 0 (متوقف) و10 (الحد الأقصى).

عند أدنى سرعة غير صفرية (1)، يُنتَج 221 سيارة كل ساعة. يزداد الإنتاج خطيًا مع السرعة، فعند السرعة 4 يُنتج الخط 4 * 221 = 884 سيارة في الساعة. غير أن السرعات الأعلى تزيد احتمال إنتاج سيارات معيبة يجب التخلص منها بعد ذلك.

لديك أربع مهام. تأخذ كل مهمة معاملًا واحدًا من نوع عدد صحيح، هو سرعة خط التجميع، من المكدس.

1. بيّن ما إذا كان الخط يعمل

عرّف production-status لتُرجع "stopped" عندما تكون السرعة 0، و"running" لأي سرعة أخرى:

0 production-status .
! => "stopped"
3 production-status .
! => "running"

2. احسب معدل النجاح

عرّف success-rate لتُرجع احتمال إنتاج عنصر دون خطأ:

  • 0: 0.0
  • من 1 إلى 4: 1.0
  • من 5 إلى 8: 0.9
  • 9: 0.8
  • 10: 0.77
10 success-rate .
! => 0.77

3. احسب معدل الإنتاج في الساعة

عرّف production-rate-per-hour لتُرجع معدل إنتاج خط التجميع في الساعة، مع أخذ معدل النجاح في الحسبان.

ستحتاج إلى تعريف base-speed أولًا، وهو الثابت 221.

6 production-rate-per-hour .
! => 1193.4

القيمة المُرجَعة عدد عشري.

4. احسب عدد القطع العاملة المُنتَجة في الدقيقة

عرّف working-items-per-minute لتُرجع عدد السيارات العاملة التي تُنتَج في الدقيقة. النتيجة عدد صحيح، ولا تُحتسب السيارات الجزئية.

6 working-items-per-minute .
! => 19
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Factor Exercism

مستعد لبدء سيارات، تجمّعوا!؟

سجّل في Exercism لتتعلّم وتتقن Factor عبر 47 مفهومًا163 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.