ABA


"חידה חמודה - יצירת פרמוטציה אקראית ב-O(n)."
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15418 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15418
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   19:01   24.07.09   
אל הפורום  
  חידה חמודה - יצירת פרמוטציה אקראית ב-O(n).  
 
כדי שכל אחד יוכל לחשוב, אגדיר את החידה בצורה קלה יותר.
בהינתן המספרים:

1,2,3,...,n

אני רוצה להחזיר סידור אקראי שלהם.
נניח עבור n=4, דוגמא לסידור אקראי:
4213

המטרה:
לבנות אלגוריתם שב-O(n) מחזיר תמורה/פרמוטציה אקראית.






                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  לא הבנתי מה הכוונה להחזיר פרמוטציה אקראית? shay86  24.07.09 21:29 1
     אממ תחזיר פרמוטציה בכל דרך שתרצה ... Deuce  24.07.09 21:37 2
         אוקיי אני אנסה shay86  24.07.09 21:59 4
             לא כזה ברור לי ... Deuce  24.07.09 22:44 5
                 אני בעצם מגריל אינדקס החל מ- i+1 ומבצע החלפה shay86  24.07.09 22:54 6
                     למה החלטת דווקא להגריל מ-i+1? Deuce  25.07.09 04:25 8
                     אם הבנתי אותך נכון אז אתה טועה, כי לכל היותר ldan192  25.07.09 11:38 9
  חידה נחמדה מאד , ווינר לפותר Net_Boy  24.07.09 21:54 3
  טוב, אני רואה שאין היענות אז אני אענה. האמת היא ldan192  25.07.09 23:21 10
     ההטבה שלך עם הערבול פוגעת באלגוריתם. Deuce  26.07.09 01:02 11
         כל פרמוטציה בהסתברות שונה. וצודק האמת היא, התוספת מיותרת ldan192  26.07.09 09:05 12
     יפה:), חח הפתרון שלי:) akoka 26.07.09 12:24 13
  פתרון החידה. Deuce  26.07.09 12:26 14
     תיקנתי את הקוד.. תודה על החידה וברכות לזוכה :) Nesher  26.07.09 19:14 15
         לצערנו הרב הקוד קצת משוחד. Deuce  26.07.09 23:13 16
  זה דרש קצת מחשבה אבל להלן קוד לא משוחד: Deuce  26.07.09 23:58 17

       
shay86 
חבר מתאריך 13.5.06
197 הודעות
   21:29   24.07.09   
אל הפורום  
  1. לא הבנתי מה הכוונה להחזיר פרמוטציה אקראית?  
בתגובה להודעה מספר 0
 
   לצורך העניין נתון לי מערך עם כל המספרים עד N.
מה אתה רוצה בדיוק לקבל?
אני מניח שלא בדיקה אם יש פרמוטציה באינדקס I אלא משהו אחר.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   21:37   24.07.09   
אל הפורום  
  2. אממ תחזיר פרמוטציה בכל דרך שתרצה ...  
בתגובה להודעה מספר 1
 
הפונקציה שלך מקבלת קלט מספר שלם מטיפוס int - נסמנו ב-n.
ואז אתה מחזיר תמורה, נניח תמורת הזהות היא:
123456...n

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






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
shay86 
חבר מתאריך 13.5.06
197 הודעות
   21:59   24.07.09   
אל הפורום  
  4. אוקיי אני אנסה  
בתגובה להודעה מספר 2
 
   בהנחה שהגרלת מספר בין 0 ל K-1 היא פעולה של (O(1
נבנה מערך של N תאים ונשים בו את כל המספרים עד ל- N.
נעבור על המערך ובכל איטרציה:
1. נגריל מספר בין 0 ל- N-i ונוסיף לו את ה-i הנוכחי,
2. נבצע החלפה בין המיקום ה- i לבין התוצאה מסעיף 1.

סה"כ: (O(n


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   22:44   24.07.09   
אל הפורום  
  5. לא כזה ברור לי ...  
בתגובה להודעה מספר 4
 
אתה אומר נגריל מספר בין 0 ל-N-i ונוסיף לו את ה-i הנוכחי. זה אומר שאתה מגריל מספר בעצם בין i ל-N? מה זה נותן לך ... למה זה נכון?






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
shay86 
חבר מתאריך 13.5.06
197 הודעות
   22:54   24.07.09   
אל הפורום  
  6. אני בעצם מגריל אינדקס החל מ- i+1 ומבצע החלפה  
בתגובה להודעה מספר 5
 
   במקרה הכי גרוע יוצא לי שלאחר כל ההחלפות האיבר הראשון לא יהיה 1.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   04:25   25.07.09   
אל הפורום  
  8. למה החלטת דווקא להגריל מ-i+1?  
בתגובה להודעה מספר 6
 
אתה דיי בכיוון, אבל האם זה נכון שבדרך שפתרת לכל תמורה הסתברות זהה להתקבל?






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   11:38   25.07.09   
אל הפורום  
  9. אם הבנתי אותך נכון אז אתה טועה, כי לכל היותר  
בתגובה להודעה מספר 6
 
כי נגיד ואתה תקבל רצף של 1-ים.
אז בפעם הראשונה תזיז תא אחד,
בפעם השניה שני תאים וכן הלאה.
סה"כ סיבוכיות: (O(n(n-1+1)/2) = O(n^2


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק
   21:54   24.07.09   
אל הפורום  
  3. חידה נחמדה מאד , ווינר לפותר  
בתגובה להודעה מספר 0
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   23:21   25.07.09   
אל הפורום  
  10. טוב, אני רואה שאין היענות אז אני אענה. האמת היא  
בתגובה להודעה מספר 0
 
שיש מלא דרכים לפתור את זה, חלק יותר מורכבות ומשתמשות במבני נתונים מורכבים אך שיתנו אקראיות אופטימלית ויש כאלה פחות מתוחכמים אך ברורים וקלים להסברה כמו שאני אתן עכשיו.

ניקח מערך ונשים בו ב-n התאים מספרים מ-1 עד n.
נבצע n פעמים (אפשר גם 5n בשביל לערבל יותר) את האיטרציה הבאה:
- נבצע הגרלה פעמיים (הגרלה מודולו n). נבצע החלפה של המספרים בין התאים i ו-j המתקבלים.
- ניתן בשביל קצת להטיב עם הערבול - אם i=j אז נבחר [j=[i/2 (למשל).

מבצעים kn איטרציות (K קבוע) של (o(1.
סיבוכיות (O(n
בסיום נקבל פרמוטציה רנדומלית כלשהי.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   01:02   26.07.09   
אל הפורום  
  11. ההטבה שלך עם הערבול פוגעת באלגוריתם.  
בתגובה להודעה מספר 10
 
עדיף לא להטיב, כי זה נותן הסתברות לפרמוטציה מסויימת על פני פרמוטציות אחרות.

האם הפתרון שלך נותן אגב לכל פרמוטציה הסתברות זהה?
זה דיי נכון בכל אופן






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   09:05   26.07.09   
אל הפורום  
  12. כל פרמוטציה בהסתברות שונה. וצודק האמת היא, התוספת מיותרת  
בתגובה להודעה מספר 11
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
akoka

   12:24   26.07.09   
אל הפורום  
  13. יפה:), חח הפתרון שלי:)  
בתגובה להודעה מספר 10
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   12:26   26.07.09   
אל הפורום  
  14. פתרון החידה.  
בתגובה להודעה מספר 0
 
עבר עריכה לאחרונה בתאריך 26.07.09 בשעה 12:26:28 על-ידי Nesher (מנהל הפורום)
 
מכיוון שעידן כבר גיבש פתרון יחסית נכון, אני רק אתן את החותם והאלגוריתם אליו בידיוק התכוונתי. כמו כן גם יוחאי akoka פתר נכונה את החידה, אך ביקשתי ממנו לא לפרסם את הפתרון כאן כדי לתת במה לאחרים.

כשאני מגדיר אקראיות בפרמוטציות אני למעשה ארצה לתת לכל פרמוטציה הזדמנות שווה לצאת. יש n! תמורות. אני ארצה שאם נניח אני אבצע n!^2 עירבולים אז מבחינת התפלגות, אני אראה שכל תמורה הוגרלה מספר דומה של פעמים. לפחות ארצה לשאוף לזה.

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

הפתרון:
נאתחל מערך באופן ש-A[i] = i (נניח שהאינדקסים שלו הם מ-1 ועד n לצורך נוחיות).
עבור i החל מ-1 ועד n בצע:
- הגרל מספר שלם בין 1 ל-n; בצע השמה ל-j.
- החלף בין A[i] ל-A[j].

הפרמוטציה תהיה הדפסת המערך לפי סדר איבריו.

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

נ.ב:
בלי פלצנות שאין דבר כזה אקראיות ואני מניח שהפונקציה שמגרילה מספר בין 1 ל-n מתפלגת אחיד. זה לא מעניין לצורך הדיון הזה.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Nesher  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 2.7.02
2 הודעות, 24 פידבק
   19:14   26.07.09   
אל הפורום  
  15. תיקנתי את הקוד.. תודה על החידה וברכות לזוכה :)  
בתגובה להודעה מספר 14
 


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   23:13   26.07.09   
אל הפורום  
  16. לצערנו הרב הקוד קצת משוחד.  
בתגובה להודעה מספר 15
 
הפרמוטציות לא מספיק אקראיות.
חישוב מתמטי מראה את זה.

אני אוריד את הכובע בפני אדם שיצליח להגריל פרמוטציה בצורה לא משוחדת.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   23:58   26.07.09   
אל הפורום  
  17. זה דרש קצת מחשבה אבל להלן קוד לא משוחד:  
בתגובה להודעה מספר 0
 

public static void shuffle (int[] array)
{
Random myRand = new Random();
int n = array.length;
for (int i=0; i<n-1; ++i)
{
int k = myRand.nextInt(n-i)+i; // a number between i and n
int tmp = array[k];
array[k] = array[i];
array[i] = tmp;
}
}

חישוב הסתברותי מראה שלכל פרומטציה הזדמנות שווה - נסו לצייר לכם את זה ותבינו לבד למה.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net