مسیرها
/
Factor
Factor
/
تمرین‌ها
/
تریاژ صندوق‌دارها
تریاژ صندوق‌دارها

تریاژ صندوق‌دارها

تمرین یادگیری

مقدمه

«کپه» مجموعه‌ای است که همیشه کوچک‌ترین عنصرش را می‌شناسد و به شما اجازه می‌دهد آن عنصر را به‌سرعت بیرون بیاورید. این ابزار طبیعی برای یک «صف اولویت» است، یعنی صفی که در آن نوبت به مهم‌ترین عنصر می‌رسد، نه به عنصری که بیشتر از همه منتظر مانده است. کپه‌ها در واژگان heaps قرار دارند.

ساخت یک کپه

<min-heap> یک کپه‌ی خالی می‌سازد که ابتدا کوچک‌ترین کلیدش بیرون می‌آید؛ <max-heap> تصویر آینه‌ای آن است.

<min-heap> ( -- min-heap )
<max-heap> ( -- max-heap )

افزودن عنصرها

هر عنصر به‌صورت یک «مقدار» همراه با یک «کلید» ذخیره می‌شود؛ کلید همان اولویتی است که Factor بر مبنای آن عنصرها را مرتب می‌کند. heap-push یک عنصر اضافه می‌کند:

heap-push ( value key heap -- )
USING: heaps ;

<min-heap>
"alice" 5 pick heap-push   ! value "alice", priority 5
"bob"   2 pick heap-push   ! value "bob",   priority 2

کپه «تغییرپذیر» است: heap-push آن را در جای خودش تغییر می‌دهد، نه اینکه یک کپه‌ی جدید برگرداند. اگر بخواهید پس از آنکه heap-push کپه را مصرف کرد، آن را دوباره روی پشته داشته باشید، keep به کارتان می‌آید.

نگاه کردن به عنصر جلویی و حذف آن

heap-peek عنصر جلویی را برمی‌گرداند، یعنی مقداری که کوچک‌ترین کلید را دارد، و آن را حذف نمی‌کند. heap-pop همان عنصر را برمی‌گرداند و حذفش می‌کند. heap-empty? گزارش می‌دهد که آیا هنوز عنصری باقی مانده است یا نه، تا بدانید چه زمانی باید از بیرون آوردن عنصرها دست بکشید. heap-pop-all همه را یک‌جا حذف می‌کند و یک «لیست انجمنی» از جفت‌های { key value } را به ترتیب اولویت برمی‌گرداند.

heap-peek    ( heap -- value key )
heap-pop     ( heap -- value key )
heap-empty?  ( heap -- ? )
heap-pop-all ( heap -- alist )
USING: assocs heaps kernel prettyprint ;

<min-heap>
"alice" 5 pick heap-push
"bob"   2 pick heap-push
dup heap-empty? .        ! => f      (two items waiting)
dup heap-peek drop .     ! => "bob"  (smallest key, still in the heap)
dup heap-pop drop .      ! => "bob"  (smallest key, now removed)
heap-pop-all .           ! => { { 5 "alice" } }

heap-pop و heap-empty? بلوک‌های سازنده برای تحویل دادن عنصرها یکی‌یکی هستند: به عنصر جلویی نگاه کنید یا بیرونش بیاورید، روی آن عمل کنید و به‌محض اینکه heap-empty? مقدار t را برگرداند متوقف شوید. تمرین‌های زیر از heap-pop-all استفاده می‌کنند تا کل صف را در یک مرحله خالی کنند، اما همین ترتیب از بیرون آوردن عنصرها تا خالی شدن کپه هم به دست می‌آید.

جفت‌های حاصل از heap-pop-all یک لیست انجمنی هستند: values (در assocs) فقط مقدارها را نگه می‌دارد و کلیدها را دور می‌ریزد.

دستورالعمل‌ها

یک بانک شلوغ به مشتریان منتظر بر اساس «اولویت» رسیدگی می‌کند، نه به ترتیبی که رسیده‌اند. به هر مشتری وقتی بلیت می‌گیرد یک شماره‌ی اولویت داده می‌شود و متصدی باجه همیشه اول به کم‌ترین شماره رسیدگی می‌کند (1 فوری‌ترین است). یک «هیپ کمینه» صف انتظار ایده‌آل است.

1. صف را باز کنید

new-queue را تعریف کنید؛ این تابع چیزی نمی‌گیرد و یک صف اولویت‌دار تازه و خالی برمی‌گرداند.

new-queue
! => an empty priority queue

2. یک مشتری اضافه کنید

join-queue را تعریف کنید؛ این تابع اسم مشتری، یک شماره‌ی اولویت و یک صف می‌گیرد. مشتری را به صف اضافه می‌کند و صف را برمی‌گرداند، بنابراین می‌توان مشتری‌ها را یکی پس از دیگری اضافه کرد.

new-queue "alice" 5 rot join-queue "bob" 2 rot join-queue
! => the queue, now holding alice (5) and bob (2)

3. نفر بعدی کیست؟

next-name را تعریف کنید؛ این تابع یک صف می‌گیرد و اسم مشتری‌ای را برمی‌گرداند که باید بعدی به او رسیدگی شود (کسی که کم‌ترین شماره‌ی اولویت را دارد)، بدون این که او را از صف حذف کند.

new-queue "alice" 5 rot join-queue "bob" 2 rot join-queue next-name .
! => "bob"

4. به همه رسیدگی کنید

serve-all را تعریف کنید؛ این تابع یک صف می‌گیرد و اسم همه‌ی مشتریان منتظر را به همان ترتیبی برمی‌گرداند که به آن‌ها رسیدگی می‌شود.

new-queue "alice" 5 rot join-queue "bob" 2 rot join-queue
"carol" 9 rot join-queue serve-all .
! => { "bob" "alice" "carol" }
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Factor Exercism

آماده‌اید تریاژ صندوق‌دارها را شروع کنید؟

در Exercism ثبت‌نام کنید تا Factor را همراه با 47 مفهوم163 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.