חידת אלגוריתם

עריסטו

Active member
חידת אלגוריתם

יש לכם תמונה מלבנית שמורכבת מפיקסלים שחורים ולבנים. אתם צריכים לספור כמה גושים שחורים יש בתמונה. גוש שחור מוגדר כקבוצת פיקסלים שחורים שמחוברים זה לזה במאוזן או במאונך. גוש לבן מוגדר באופן דומה. ידוע מראש שאין גוש שחור שבתוכו גוש לבן. כמו כן ידוע שלתמונה יש שוליים לבנים, כלומר כל הפיקסלים הסמוכים לשולי התמונה לבנים. אתם צריכם לפתור בדרך היעילה והפשוטה ביותר.
 

עריסטו

Active member
לא

גוש שחור מוגדר כקבוצת משבצות שחורות, שמכל אחת מהן ניתן להגיע לכל אחת אחרת על ידי צעדים במאוזן ו/או במאונך, כאשר כל הצעדים הם למשבצות שחורות. גוש לבן מוגדר באופן דומה. (אל תשכחו שנתון שאין גוש שחור המכיל גוש לבן. באופן שקול ניתן לומר: כל המשבצות הלבנות מהוות גוש אחד.) להמחשה מצורפת תמונה של כל הגושים האפשריים המורכבים משש משבצות.
 

עריסטו

Active member
הערה

שימו לב שהתמונה שצירפתי מתאימה לנתוני הבעיה, כלומר האלגוריתם אמור לזהות שיש בה 35 גושים שחורים. לא צריך שום backtracking, רקורסיה, מחסנית או תור.
 

מספר6

New member
../images/Emo62.gif

לרוץ בלולאה על כל הפיקסלים ובכל פעם שמוצאים פיקסל שחור, לצבוע את הגוש שלו בלבן, להוסיף 1 לספירה, ולהמשיך את הלולאה. לחילופין, אם אסור לשנות את הקלט, אפשר להשתמש ב-union find (זה לא ברשימת האיסורים).
 

עריסטו

Active member
../images/Emo128.gif

ראשית, איך צובעים את הגוש שלו בלבן בלי רקורסיה, Backtracking, מחסנית או תור? שנית, זה אינו האלגוריתם הפשוט ביותר.
 

בסג

New member
../images/Emo62.gifחידת אגב

לפי מה הוחלט באיזה צבע תצבע כל צורה בתמונה הזו? תשובה למטה...
אדום = סימטריה אופקית או אנכית כחול = סימטריה של 180 מעלות ירוק = סימטריה אלכסונית סגול = סימטריה אופקית ואנכית (וממילא - גם 180 מעלות) שחור = כל השאר
 

עריסטו

Active member
../images/Emo128.gif אם הבנתי נכון זה בדיוק

מה שהציע "מספר 6". ראה תשובתו ותגובתי עליה. כמו כן ציינתי שבאלגוריתם אליו אני מתכוון אין (בין השאר) רקורסיה.
 

עריסטו

Active member
עוד הבהרות

האלגוריתם אליו אני מתכוון הוא שונה לחלוטין, כלומר הוא אינו יישום יותר פשוט או יותר יעיל של מה שכתבת אלא פשוט אלגוריתם אחר. למי שרוצה לדבר על סיבוכיות - הוא עובד בסיבוכיות זמן O(n), כמובן, כאשר n הוא מספר המשבצות (הרי חייבים לעבור על המשבצות), ובסיבוכיות מקום O(1), כלומר פרט לזכרון הדרוש לאחסון מערך הפיקסלים הוא דורש כמות זכרון קבועה, שאינה גדלה עם גידול מערך הפיקסלים (באלגוריתם שלך זה לא כך). גם מבחינת אורך הקוד ומורכבותו הוא פשוט הרבה יותר מהאלגוריתם שלך. האלגוריתם שלך הוא האלגוריתם הטוב ביותר שיש במקרה הכללי; שים לב שבבעיה שלי יש נתון נוסף - כל המשבצות הלבנות מהוות גוש אחד, כלומר אין גוש שחור המקיף גוש לבן. עובדה זו מאפשרת לכתוב אלגוריתם פשוט יותר. (למעשה יש בבעיה שלי עוד נתון - שהשוליים של מערך המשבצות לבנים, כלומר אין גוש שחור שנוגע בשוליים; זה נתון שהוספתי רק כדי לפשט את האלגוריתם - הרי גם אם לא היה כך אזי היה ניתן להוסיף שולים לבנים כאלה ואז להריץ את האלגוריתם הפשוט.)
 
ננסה משהו כזה

(למרות שלא ממש הבנתי את כל מה שנכתב לעיל). יש מונה בו נצבר מספר הגושים. בתחילה הוא כמובן מאופס. רצים שורה שורה. בכל שורה זוכרים מידע מסוים, אחרי ששומרים אותו מידע מהשורה הקודמת. כלומר, מוקצה זיכרון למידע זה של שתי שורות. מידע זה הוא: רשימת הקטעים השחורים הרצופים בשורה. משווים את קטעי השורה הנוכחית עם קטעי השורה הקודמת. אם הופיע בשורה החדשה קטע שאינו מחובר לאף אחד מקטעי השורה הקודמת - מוסיפים 1 למונה הגושים. אם הופיע בשורה החדשה קטע המחובר לקטע אחד בלבד מהשורה הקודמת - לא משנים את מונה הגושים. אם הופיעו בשורה החדשה מספר קטעים המחוברים לאותו קטע מהשורה הקודמת - גם כן לא משנים את מונה הגושים. אם הופיע בשורה החדשה קטע המחובר ל-m קטעים מהשורה הקודמת - מחסרים ממונה הגושים m-1.
 
~ ~ ~

שומרים את רשימת הקטעים מהשורה הקודמת. מאפסים את רשימת הקטעים החדשה. רצים על השורה החדשה ומחפסים בה קטעים שחורים. עם כל קטע שחור מבצעים את הפעולות הבאות: יהי m מספר הקטעים מהשורה הקודמת המחוברים לקטע הנוכחי מהשורה החדשה. מחסרים ממונה הגושים את המספר m-1.
 
בשפת MUMPS זה קל מאוד,

כאשר רשמתי את הנתונים כשורות טקסט מסוג:
110000110000011 110000110000011 110000000000011 110000000000011 111111111111111 111111111111111​
(מספר הגושים = 2). הודות לרישום הנתונים בצורת עץ, השימוש בפונקציה "האח הבא" ופונקצית "מצא" בשורת טקסט. ואכן התכנית אינה עובדת נכון אם יש גוש לבן בתוך גוש שחור.
 

עריסטו

Active member
קודם כל,

התכוונתי למשהו (הרבה) יותר פשוט. שנית, כמות הזכרון שהאלגוריתם שלך דורש אינה קבועה - היא גדלה עם גידול המערך.
 
אבל גודל הזיכרון

פרופורציונלי לגודל שורה אחת בלבד (שתי רשימות של קטעים שחורים), והריצה על שורה כזאת היא מהירה מאוד ב-MUMPS, ואני מעריך שגם ב-++C עם שימוש בסוג מיוחד של רשימה. חשבתי על אלגוריתם שרץ על ההיקף של גוש, אבל לא ברור לי איך לחפש אח"כ את הגושים האחרים.
 

עריסטו

Active member
נכון, אבל הוא עדיין לא קבוע ../images/Emo3.gif

וחוץ מזה, כאמור, התכוונתי לאלגוריתם פשוט יותר.
 
למעלה