כותב |
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 27 August 2007 בשעה 18:02 | | IP רשוּם
|
|
|
|
הכותרת של הפורום היא תיכנות,חידות,ושאלות.
תיכנות יש והרבה. שאלות לא חסר. חידות קצת פחות...
אז אני פותח שירשור לחידות מעניינות שיגרמו לגלגלים להסתובב. בשביל להתחיל ברגל ימין 2 חידות ראשונות:
1. נתונה מחרוזת מילים המורכבת מאותיות ומספרים, בהינתן מחרוזת כזו יש להפוך את כל המילים בה לפי הסדר. אילוצים: הפתרון חייב להיות יעיל ביותר. לדוגמה: המחרוזת: UNDER WAR ROCKS תתקבל: REDNU RAW SKCOR
2. נתון עץ, כתוב תוכנית איטרטיבית המדפיסה את תוכן העץ לפי רמותיו מהנמוכה לגבוה. לדוגמה:   ; 1 \ / 3 2 / \ / 7 6 8 יודפס: 8,7,6,2,3,1
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 27 August 2007 בשעה 22:03 | | IP רשוּם
|
|
|
|
יוזמה נחמדת (:
עוד כמה תגובות שמישהו יזכיר להפוך את הנושא לדביק...
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 03:22 | | IP רשוּם
|
|
|
|
נו... מה קורה?
|
חזרה לתחילת העמוד |
|
|
oded אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 11:23 | | IP רשוּם
|
|
|
|
|
חזרה לתחילת העמוד |
|
|
אורח אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 12:34 | | IP רשוּם
|
|
|
|
1. די קל, אפשר ב-O של N, או עם מחסנית כשזוכרים את ההתחלה של המילה האחרונה או עם swap כשמזהים את הסוף של המילה באינדקס מסויים וגם זוכרים את האינדקס של התחלת המילה.
2. סריקה לפי רמות (מוזמן להסתכל בויקיפדיה, BFS כל איבר דוחפים למחסנית, בסוף מדפיסים את האיברים במחסנית.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 18:23 | | IP רשוּם
|
|
|
|
יפה מאוד אורח!!!
כל הכבוד.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 18:35 | | IP רשוּם
|
|
|
|
אוקיי קצת יותר קשה...
1. יש לכתוב אלגוריתם המקבל מס' שלם ובודק אם הוא חזקה של 2 במינימום צעדים.
2. נתונה רשימה מקושרת, יש לכתוב תוכנית הבודקת האם קיים מעגל ברשימה, כלומר הרשימה אינסופית. אילוצים : אסור שימוש במערכים. הערות: יש להסתכל על רשימה מקושרת כמבנה. כלומר, תשובה כגון: להפעיל אלגוריתם למציאת מעגלים לא נכונה.
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 19:35 | | IP רשוּם
|
|
|
|
1. מפרקים את המספר לבסיס בינארי, אם יש רק 1 אחד ויחיד אז זאת חזקת של 2.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 19:50 | | IP רשוּם
|
|
|
|
זה נכון, מס' שהוא חזקה של 2 בייצוג בינארי הוא בעל 1 יחידי.
אבל השאלה היא לספק אלגוריתם יעיל שמחזיר אמת או שקר אם המס' הוא חזקה של 2.
|
חזרה לתחילת העמוד |
|
|
11010010110 פורומיסט על
הצטרף / הצטרפה: 23 April 2006
משתמש: מנותק/ת הודעות: 2621
|
נשלח בתאריך: 03 September 2007 בשעה 19:58 | | IP רשוּם
|
|
|
|
ניתן לצאת מתחום התיכנות ?
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 20:10 | | IP רשוּם
|
|
|
|
תשמע אין צורך לכתוב תוכנית שרצה...
אבל למרות זאת התשובה אמורה מבחינה צריכה רעיונית להיות ברת מימוש על מערכת מחשב. כלומר באופן כזה שניתן יהיה לתרגם אותה לתוכנית יעילה שרצה.
|
חזרה לתחילת העמוד |
|
|
חחחחח חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 20:12 | | IP רשוּם
|
|
|
|
מצטער על בילבול שם עם הצריכה אמורה...
חחחחחחחחח
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 20:57 | | IP רשוּם
|
|
|
|
אוקיי זה מעניין אם יש משהו יותר יעיל מ-O של log(n) כאשר N המספר הנתון...
האם-חזקה-של-2(N) {הנחה: N גדול מ-0,
אם זאת לא ההנחה צריך להוסיף ולידציה} כל עוד N שונה מ-1 בצע אם N איזוגי אזי החזר שקר (וסיים את פעולה האלגוריתם). {משום שיש לנו את הביט הנוכחי שהוא 1, ועוד ביט משום שאחרת המספר היה 1, זה כבר שני ביטים} חלק את N ב-2. החזר אמת.
השאלה אם מבחינה לוגית יש משהו יותר מגניב (:
מימוש cpp
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 03 September 2007 בשעה 21:16 | | IP רשוּם
|
|
|
|
אפשר גם
בהנחה שמספר הביטים סופי אפשר לחלק את המספר לשני חלקים שלו ואז אם שני החלקים שונים מ-0 זאת לא חזקה של 2, אחרת את האחד שלא 0 בודקים באופן רקורסיבי...
קוד CPP:
קוד:
bool isPowerOf22(int n, int bits) { if (bits <= 1) return true; bits >>= 1; int n1 = n >> bits; int n2 = (n << (32-bits)) >> (32-bits); if (n1 == 0) return isPowerOf22(n2, bits); else if (n2 == 0) return isPowerOf22(n1, bits); return false; } |
|
|
לדעתי אפשר להוכיח שזה ביעילות של log log n די בקלות...
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 21:55 | | IP רשוּם
|
|
|
|
שושן,
הדרך שלך מניבה פתרון טוב ומקובל. אבל ישנו פתרון יעיל יותר.
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 22:39 | | IP רשוּם
|
|
|
|
אוקיי, מכיוון שמספר שהוא חזקה של 2, בהצגה בינארית הוא בסגנון
0000 0000 0000 1000
אם נחסר ממנו 1 ישאר
1111 1111 1111 0111
כלומר כל הביטים משתנים...
ולכן אפשר בגודל קבוע פשוט להשוות בין N ל- N פחות 1, ולראות אם כל הביטים השתנו
n & (n-1) == 0
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 22:46 | | IP רשוּם
|
|
|
|
יפה מאד!!!
הפתרון בשפת C לדוגמה:
כל הכבוד שושן!
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 03 September 2007 בשעה 23:10 | | IP רשוּם
|
|
|
|
אוקיי, את הזה עם הבדיקה אם רשימה היא מעגלית כבר היה בפורום לפני כ-5 חודשים, אני לא אהרוס עם הבאת הפתרון, רק אגיד שהוא חמוד ויצירתי וקרדיט ל - צחי@ - (:
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 04 September 2007 בשעה 18:24 | | IP רשוּם
|
|
|
|
לא ידעתי שהחידה כבר כאן,
הפתרון שלי הוא אותו פתרון כלומר, להריץ בלולאה שני מצביעים שאחד קופץ מס' זוגי של צמתים והשני מס' איזוגי של צמתים. אם הרשימה היא מעגלית מובטח לנו שהם יפגשו מתישהו (הוכחה ע"י אינדוקציה מתמטית) אחרת אם הרשימה איננה מעגלית אז המצביע שמדלג מהר יותר יגיע לסוף הרשימה ולכן היא איננה מעגלית.
יפה צחי.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 04 September 2007 בשעה 18:48 | | IP רשוּם
|
|
|
|
חידה אלגוריתמית תיכנותית קלאסית:
ידוע שבמערך ממויין הזמן הטוב ביותר לחיפוש איבר לוקח (O(LOG n.
נתון מערך ממויין שהוזז עפ"י אינדקס מסויים בצורה מעגלית: לדוגמה (בהנחה שאינדקס מערך מתחיל מ-0): 12345 מוזז עפ"י אינדקס 2 יתן: 34512. 43 39 38 21 10 5 מוזז עפ"י אינדקס 3 יתן: 10 5 43 39 38 21.
(שימו לב: במקום של אינדקס ההזזה ימצא המס' הגדול ביותר במערך מימינו המס' הקטן ביותר ואחריו כל שאר האיברים הממויינים הממלאים את המערך בצורה מעגלית.)
יש לכתוב תוכנית המוצאת איבר כלשהו במערך המוזז כאשר האינדקס אינו ידוע בזמן שלא יעלה על (O(LOG n.
|
חזרה לתחילת העמוד |
|
|
צחי@ משתמש חבר
הצטרף / הצטרפה: 02 January 2007 מדינה: Israel
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 05 September 2007 בשעה 13:24 | | IP רשוּם
|
|
|
|
אם יש איבר שחוזר יותר מפעם אחת, לא ניתן בוודאות לעשות זאת ב-(O(log n
תחשבו על מערך שנראה כך:
1 , 0 , 0 , ... , 0 , 0
הוא ממויין אבל לאחר הזזה הוא יראה למשל כך:
0, 0 , ... , 0 , 1 , 0 , 0, 0, 0 , ... , 0 , 0
אם מחפשים את האיבר 1 , אזי כל חיפוש ב-( O(log n
לא ימצא בוודאות את האיבר. תמקד את השאלה למערך ממויין שכל האיברים בו הם ייחודיים.
ד"א, תודה על הקרדיט
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 05 September 2007 בשעה 14:35 | | IP רשוּם
|
|
|
|
(מה שצחי אמר)
ואז עושים משהו שמאוד מזכיר חיפוש בינארי למציאת כמה הזיזו את המערך, ואז עושים חיפוש בינארי בחלק המתאים של המערך (עד ההזזה או אחרי).
ככה מוצאים את האמצע:
קוד:
private static int getPost(int[ ] arr) { int left = 0; int right = arr.Length - 1; while ( left < right ) { if ( arr[left] >= arr[right] ) // the hole part is sorted return right; int middle = ( left + right ) / 2; if ( arr[left] < arr[middle] ) // left side is not sorted right = middle - 1; else if ( left < middle ) // still some right side to check left = middle; else return middle; } return left; } |
|
|
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 06 September 2007 בשעה 00:44 | | IP רשוּם
|
|
|
|
צחי תודה...
שכחתי לציין שכמובן שהאיברים חייבים להיות שונים זה מזה.
שושן,לגבי התוכנית ששלחת המשפט הבא יחזיר את האינדקס הימני ביותר לפי הדוגמה שנתתי בשאלה, וכאמור זה לא האמצע:
קוד:
if ( arr[left] >= arr[right] ) return right; |
|
|
דבר שני לא הבנתי איך אתה מחליט איפה לחפש אחרי מצאת את את האמצע.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 06 September 2007 בשעה 00:51 | | IP רשוּם
|
|
|
|
למי שמתקשה עם השאלה הקודמת ניתן עוד שאלה פשוטה יותר:
כתוב תוכנית המקבלת מס' טיבעי כלשהו ומדפיסה את כל האיברים הראשוניים מ-0 ועד אליו. אילוצים: אין להשתמש בחילוק.
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 06 September 2007 בשעה 01:07 | | IP רשוּם
|
|
|
|
אפשר לחלק את המערך לשני מערכים ממויינים שאפשר לעשות בהם חיפוש בינארי, הראשון מ-0 עד מה שכיניתי האמצע, והשני מאמצע ועוד 1 עד הסוף...
ובשורה ששלחת באמת נראה לי שצריך אם left הוא גדול מ-0 להחזיר את right, אחרת left-1
מה שעשיתי בשורה הזאת זה להניח שאם החלק שאנחנו מסתכלים עליו כבר ממויין זה כנראה כל המערך שממויין, ולכן להחזיר את סוף המערך ולהגיד לחפש בכל המערך..
אני לא בטוח שלא ניתן להניח את זה אבל לא משנה...
פשוט לא כתבתי את הפונציה המלאה כול להחיפוש הבינארי בגלל שהחיפוש הבינארי המובנה במערך הוא למערך ממויין מקטן לגדול, ולא מגדול לקטן...
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 06 September 2007 בשעה 01:37 | | IP רשוּם
|
|
|
|
יפה זה פתרון טוב בהנחה שאתה מוצא את אינדקס ההזזה בזמן של (O(LOG n
אלגוריתם: 1.מצא אינדקס(A). 2.חיפוש בינארי משמאל לאינדקס(A). 3.חיפוש בינארי מימין לאינדקס(A). 4.החזר תשובה.
צעד 1: (O(LOG n צעד 2: (O(LOG n צעד 3: (O(LOG n
סה"כ אלגוריתם בזמן של (O(LOG n (דרך אגב עובד גם כאשר ישנם איברים דומים).
אבל... כל זה טוב ויפה בתנאי שאתה כותב אלגוריתם שמוצא את האינדקס ב-(O(LOG n, לכן בשביל שהפתרון יהיה מלא עליך לספק אלגוריתם כזה.
(אגב, ישנו פתרון אחר שעובד בזמן של (O(LOG n בתנאי שהאיברים שונים זה מזה.)
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 06 September 2007 בשעה 02:18 | | IP רשוּם
|
|
|
|
זה הקוד ששלחתי (:
getPost זה טעות, התכוונתי getPos
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 06 September 2007 בשעה 04:45 | | IP רשוּם
|
|
|
|
שושן הקוד ששלחת לא עובד (גם לא אחרי התיקון).
אם תוכל להסביר את ההגיון מאחורי הקוד זה יעזור.
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 06 September 2007 בשעה 14:04 | | IP רשוּם
|
|
|
|
הוא עבד בנסיונות שהרצתי...
נגיד שיש לנו את המערך
ועשינו לו shift
כל איבר בחלק הממויין הראשון (ה-4 מספרים הראשונים) קטן מכל שאר המספרים (בחלק הממויןי השני) כמובן.
כל איבר בחלקים הממויינים קטן מקודמו.
לכן אני מחלק את המערך לשני חלקים (חצי חצי) ואם החלק שאני מסתכל עליו ממויין כבר, אז זה המקרה קצה שהקוד תיקון מטפל בו, אם האיבר בתחילת החל הימני גדול או שווה לאיבר בסוף החלק הימני אז כל החלק של המערך שאנחנו מסתכלים עליו ממויין ואפשר להחזיר את הסוף שלו (כי המטרה שלנ להחזיר את סוף החלק הממויין הראשון).
לכן אני מחלק את המערך לשני חלקים (חצי חצי) ואם החלק שאני מסתכל עליו ממויין כבר, אז זה המקרה קצה שהקוד תיקון מטפל בו, אם האיבר בתחילת החל הימני גדול או שווה לאיבר בסוף החלק הימני אז כל החלק של המערך שאנחנו מסתכלים עליו ממויין ואפשר להחזיר את הסוף שלו (כי המטרה שלנו להחזיר את סוף החלק הממויין הראשון).
לעומת זאת, אם זה לא המצב אני רוצה להתמקד על החצי שבו נמצא ה"אמצע" ולהמשיך את פעולת האלגוריתם עליו (באופן רקורסיבי).
אז אם האיבר בתחילת החלק השמאלי גדול מהאיבר שבאמצע אז נתמקד בצד הימני, אחרת נתמקד בצד השמאלי, ואם אנחנו באיזור בגודל 1 משום מה, מה שלא אמור לקרות, אז נחזיר את המקום שלו...
ועכשיו בדקתי אותו שוב והוא עובד...
פשוט על מערכים ממויינים מגדול לקטן (לא יודע, ככה שלחת את השאלה (: )
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 07 September 2007 בשעה 00:49 | | IP רשוּם
|
|
|
|
כלומר בסופו של דבר אתה מסתכל על טווחים ומסיק איפה האמצע על פיהם כאשר האיברים שונים זה מזה.
הפתרון שנתת די קרוב לפתרון שאני מכיר לשאלה, גם הוא פועל על סמך ההנחות שאתה הצגת ועובד רק כאשר האיברים שונים אחד מן השני. כיוון שהפתרון שלך די דומה אני אציג את הפתרון שאני מכיר לשאלה:
הרעיון בגדול הוא להסתכל על טווחים. כיוון שהמערך מוזז אם נסתכל על טווח מסוים שני דברים יאמרו לנו אם האיבר אותו אנו מחפשים נמצא בתחום: אם הקצה השמאלי של התחום קטן מן המס' אותו אנו מחפשים והקצה השמאלי קטן מן הקצה הימני. או שהקצה השמאלי גדול מן הקצה הימני והקצה הימני גדול מן המס' אותו אנו מחפשים.
בשביל חיפוש בזמן של (O(LOG n נבצע חילוק של המערך לשני חלקים שווים (פחות או יותר), נבדוק את התנאים לעיל ונמשיך לחלק באופן רקורסיבי. הפתרון כמובן יעבוד אך ורק אם האיברים שונים אחד מן השני.
בכל מקרה כל הכבוד שושן
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 07 September 2007 בשעה 01:24 | | IP רשוּם
|
|
|
|
שאלה שנאבדה בין הפתרונות:
1.כתוב תוכנית המקבלת מס' טיבעי כלשהו ומדפיסה את כל האיברים הראשוניים מ-0 ועד אליו. אילוצים: אין להשתמש בחילוק.
חבר'ה זרקו גם אתם משהו...
|
חזרה לתחילת העמוד |
|
|
צחי@ משתמש חבר
הצטרף / הצטרפה: 02 January 2007 מדינה: Israel
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 07 September 2007 בשעה 08:41 | | IP רשוּם
|
|
|
|
נפת ארתוסטנס http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 07 September 2007 בשעה 13:55 | | IP רשוּם
|
|
|
|
או במילים אחרות צריך לבדוק התחלקות רק בכל המספרים הראשוניים עד השורש של המספר שבודקים...
וזה די נוח במקרה הזזה כי גם ככה צריך למצוא אותם.
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 07 September 2007 בשעה 15:01 | | IP רשוּם
|
|
|
|
שאלה: כתוב תכנית שתקבל מספר N ותדפיס ללא שימוש במערכים או בזיכרון נוסף ספירלה של המספרים 0 עד N*N-1.
לדוגמא עבוד N=10 התוכנית תדפיס
קוד:
99 98 97 96 95 94 93 92 91 90 64 63 62 61 60 59 58 57 56 89 65 36 35 34 33 32 31 30 55 88 66 37 16 15 14 13 12 29 54 87 67 38 17 4 3 2 11 28 53 86 68 39 18 5 0 1 10 27 52 85 69 40 19 6 7 8 9 26 51 84 70 41 20 21 22 23 24 25 50 83 71 42 43 44 45 46 47 48 49 82 72 73 74 75 76 77 78 79 80 81 |
|
|
|
חזרה לתחילת העמוד |
|
|
אורח אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 12 September 2007 בשעה 06:39 | | IP רשוּם
|
|
|
|
נו מה עם פתרון?
|
חזרה לתחילת העמוד |
|
|
תיקון קטן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 12 September 2007 בשעה 15:02 | | IP רשוּם
|
|
|
|
שושן כתב:
...צריך לבדוק התחלקות רק בכל המספרים הראשוניים עד השורש של המספר שבודקים... |
|
|
זה לא מדוייק כלכך כי לפי מה שאתה אומר אתה אמור לדעת את כל המס' הראשוניים בין 1 לשורש המס' הנתון. מה אם זה מס' גדול מאד? לדוגמה 10000 שורשו 100 ומס' ראשוניים מ-1 עד 100 לא ידועים לכולם.
ההנפה של ארטוסתנס היא שיטת אלמינציה שמורידה כפולות של מספרים החל מ-2 ועד לשורש המס' המבוקש. לדוגמה: n = 25.
יוצרים מערך 1..25. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
מוחקים כפולות של 2. 1 3 5 7 9 11 13 15 17 19 21 23 25
לאחר מכן המס' הבא במערך הוא 3 לכן מוחקים את כל הכפולות שלו. 1 3 5 7 11 13 17 19 23 25
לאחר מכן המס' הבא הוא 5 שהוא גם שורש של 25 מוחקים את הכפולות שלו וסיימנו. 1 3 5 7 11 13 17 19 23.
קיבלנו את כל המס' הראשוניים מ-1 עד 25 ללא צורך בידע מי המס' הראשוניים מ-1 עד 5.
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 12 September 2007 בשעה 15:51 | | IP רשוּם
|
|
|
|
אם רוצים להשתמש בקצת פחות זכרון (אם N גבוה),
במקרה הזה שגם ככה צריך להדפיס את כל המספרים הראשוניים עד N, אפשר להשתמש ברשימה מקושרת לשמירת כל הראשוניים עד כה עד שורש N, כי גם ככה צריך לבדוק את כל המספרים עד כה.
ואז עוברים על האי זוגיים מ-1 עד N ובודקים אותם, ואם הם ראשוניים מוסיפים אותם לרשימה...
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 12 September 2007 בשעה 15:51 | | IP רשוּם
|
|
|
|
אורח כתב:
נו מה עם פתרון?
|
|
|
באיזה שאלה ?
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
אורח אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 12 September 2007 בשעה 15:56 | | IP רשוּם
|
|
|
|
עם הספירלה...
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 12 September 2007 בשעה 16:14 | | IP רשוּם
|
|
|
|
זה הפתרון שלי, לא טרחתי להתאים ל-N זוגי.
הוא מתבסס על התייחסות לספירלה כריבוע בתוך ריבוע בתוך ריבוע וכן הלאה...
יש נוסחא לחישוב המספר הראשון בכל ריבוע, ואז לפי מספר הריבוע והמיקום היחסי של המספר הנוכחי מחשבים כמה צירך להוסיף למספר הראשון הזה.
לקוד 1 לקוד 2
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 12 September 2007 בשעה 18:10 | | IP רשוּם
|
|
|
|
שלום שוב לכולם ושנה טובה.
השאלה ששושן שאל היא שאלה במקור מראיון עבודה במיקרוסופט.
לטעמי השאלה הזו היא מתמטית מידי, היא משלבת שתי נוסחאות מתמטיות ופירוק לינארי יותר מאשר חשיבה רעיונית ויצירתית.
בכל מקרה הנה פירוט הפתרון המקובל:
פתרון: לדוגמה כאשר 6 = n.
ניתן לפרק את המטריצה לשתי מטריצות A ו- B כאשר חיבורן יתן את המטריצה המבוקשת.
המטריצה A:
36 36 36 36 36 36
16 16 16 16 16 36
16 04 04 04 16 36
16 04 00 04 16 36
16 04 04 04 16 36
16 16 16 16 16 36
והמטריצה B:
-1 -2 -3 -4 -5 -6
0 -1 -2 -3 -4 -7
1 0 -1 -2 -5 -8
2 1 0 -3 -6 -9
3 2 3 4 -7 -10
4 5 6 7 8 -11
כמו כן ידועים לנו מראש הקוארדינטות (אינדקסים) של כל איבר ואיבר במטריצה המבוקשת בצורה הבאה:
(0,0) (1,0) (2,0) (3,0) (4,0)
(0,1) (1,1) (2,1) (3,1) (4,1)
(0,2) (1,2) (2,2) (3,2) (4,2)
(0,3) (1,3) (2,3) (3,3) (4,3) (0,4) (1,4) (2,4) (3,4) (4,4)
המטריצה A:
אם נתבונן במטריצה A נוכל לראות שהשורה הראשונה והעמודה האחרונה מורכבות מאיברים השווים ל-N. אם נוריד שורה ועמודה זו נקבל את המטריצה הבאה:
16 16 16 16 16
16 04 04 04 16
16 04 00 04 16
16 04 04 04 16 16 16 16 16 16
במטריצה שהתקבלה ניתן לראות מעין "טבעות" המקיימות באופן דומה את אותה החוקיות כאשר כל איבר בטבעת מתקבל ע"י הריבוע של (מס' הטבעת * 2 – N). כלומר, האיבר בטבעת החיצונית ביותר במטריצה הוא
12(N ג€“ 2)2' type="#_x0000_t75">, בטבעת הפנימית הבאה וכן הלאה עד 0.
מכאן שאפשרי לכתוב נוסחה מתמטית שתתן לנו כל איבר במטריצה A עפ"י הכללים לעיל ובהסתמך על קוארדינטות כל איבר. למען פישוט הנוסחה נוציא שורש מכל איבר במטריצה A ונקבל את המטריצה הבאה:
6 6 6 6 6 6
4 4 4 4 4 6
4 2 2 2 4 6
4 2 0 2 4 6
4 2 2 2 4 6
4 4 4 4 4 6
הנוסחה הבאה תחזיר כל איבר במטריצה זו לפי הקוארדינטות שלו:
F(x,y) = N – 2 * MIN (x+1, y, N - x+1, N-y)
לדוגמה: הקוארדינטות לאיבר 0 במטריצה הן (2,3) הצבתן בנוסחה תיתן:
F(2,3) = 6 – 2 * MIN (3, 3, 3, 3) = 6 – 2 * 3 = 0
כל מה שנותר הוא לעלות בריבוע את תוצאת הנוסחה וכך לבנות את המטריצה A.
המטריצה B:
אם נתבונן במטריצה B לאחר שנוריד את העמודה האחרונה והשורה הראשונה נקבל:
0 -1 -2 -3 -4
1 0 -1 -2 -5
2 1 0 -3 -6
3 2 3 4 -7
4 5 6 7 8
נשים לב שמטריצה זו היא מעין מטריצה סימטרית סביב האלכסון כאשר האיברים מעל האלכסון שליליים ומתחתיו חיוביים. לכן אין צורך לכתוב נוסחה לכל האיברים אלא רק לאיברים שמתחת לאלכסון ולאלכסון עצמו.
0
1 0
2 1 0
3 2 3 4
4 5 6 7 8
(נשים לב: y גדול שווה בערכו ל – x בחלק התחתון כולל האלכסון.)
הכללים לנוסחה ואופן החישוב:
(הקוארדינטות מתייחסות למטריצה המקורית B).
1.איברים שחיבור הקוארדינטות שלהםx+y קטן שווה מ-N מתקבלים ע"י חישוב פשוט: y – x - 1
לדוגמה: הקוארדינטות של האיבר 2 הם (0,3) לכן נקבל 2 = 3-0-1.
2.איברים שחיבור הקוארדינטות שלהםx+y גדול מ-N מתקבלים ע"י החישוב:
U(x,y) = ((x+y) – ((N – y)*2)) + 1
לדוגמה: הקוארדינטות של האיבר 6 הם (2,5) לכן נקבל:
7 – 2 + 1 = 6= U(2,5) = ((2+5) – ((6 – 5)*2)) + 1
3.איברי החלק העליון יכולים להתקבל מאותה נוסחה ע"י סידור הקוארדינטות הצבה והכפלה ב- 1-.
4.איברי השורה העליונה והעמודה האחרונה במטריצה המקורית Bיחושבו באופן נפרד כך:
(-1)*(x+y) – 1
לדוגמה קוארדינטות האיבר 11- במטריצה B הן (5,5) הצבה תתן:
(-1)*(5+5) – 1 = -11
פתרון בשפת C:
פונקצית חישוב מינימום בין 2 איברים:
int minimum(int i, int j)
{
if (i < j) return i; else return j;
}
פונקציה לחישוב המטריצה A:
int A(int i, int j, int Size)
{
int v = Size- 2*minimum(minimum(i+1,j),minimum(Size-(i+1),Size-j));
return v*v;
}
פונקציה לחישוב המטריצה B:
int B(int i, int j, int Size)
{
if (j == 0 || i == Size - 1) // האם האיבר בשורה הראשונה או בעמודה האחרונה לפי 4
return (-1 * (i + j) -1);
if (j > i) בדיקה האם באלכסון התחתון //
if (j + i < Size) // לפי 2N-בדיקה האם סכום הקוארדינטות קטן מ
return (j - i - 1);
else
return ((j + i) - (Size - j) * 2 + 1);
else return (-1 * B(j - 1, i + 1, Size)); // לא באלכסון התחתון
סידור הקוארדינטות הכפלה במינוס 1 וקריאה רקורסיבית //
}
קובץ MAIN:
#define N 6
void main()
{
for (int j = 0;j < N; j++)
{
for (int i = 0; i < N; i++)
cout<<A(i,j,N) + B(i,j,N)<<" ";
cout<<endl;
}
}
|
חזרה לתחילת העמוד |
|
|
צחי@ משתמש חבר
הצטרף / הצטרפה: 02 January 2007 מדינה: Israel
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 20 September 2007 בשעה 11:16 | | IP רשוּם
|
|
|
|
נתקלתי לאחרונה בבעיה הנ"ל (בעיה אמיתית - לא תרגיל):
נתון מערך A של n מספרים. המספרים [A[i ו-[A[j נחשבים כצמד אם הם עומדים
ביחס C כלשהו, כלומר אם ([C(A[i],A[j הוא אמת. את ערכו של C ניתן לחשב
בזמן (O(1.
האם קיים אלגוריתם בעל זמן ריצה פולינומיאלי למציאת מספר מקסימלי של צמדים העומדים ביחס C, כאשר כל מספר יכול להשתתף בצמד אחד לכל היותר ?
יש לי השערות בנושא אבל עדיין לא הצלחתי להראות בוודאות שהן נכונות.
כל מחשבה תתקבל בברכה.
|
חזרה לתחילת העמוד |
|
|
לוק אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 20 September 2007 בשעה 16:09 | | IP רשוּם
|
|
|
|
פתרון טוב לדעתי יהיה:
- נבנה גרף מכוון כאשר בין a ל-b קיימת קשת אם ורק אם (C(a,b מתקיים. - נבחר מבין הקודקודים קודקוד v שדרגת היציאה שלו היא מינימלית אך גדולה מ-0. - מבין הקודקודים שקיימת אליהם קשת מקודקוד v נבחר קודקוד u כך שדרגת הכניסה שלו היא מינימלית. - נוציא קודקודים אלה כזוג (v,u), נבנה גרף חדש ונחזור על פעולות אלה עד אשר לא נותרו זוגות אפשריים.
אם מסתכלים על גרף מכוון במבנה של מטריצת שכנות אזי:
צעד 1: (O(n^2 צעד 2: (O(n^2 צעד 3: (O(n^2 צעד 4: (O(n (ניתן פשוט למחוק את השורה ועמודה של כל קודקוד שמוציאים).
צעדים 1-4 מתבצעים לכל היותר n פעמים, לכן סה"כ אלגוריתם שניתן לבנות בהסתמך על פעולות אלה הוא בזמן של (O(n^3.
פתרון בשפת ++C:
bool C(int a,int b){
// The relation a >= b AND a - b > 2.
return ((a >= b) && (a - b > 2));
}
void BuildGraphMat(bool B[][10] , int A[], int size){
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
B[j] = C(A,A[j]);
}
int FindMinOutDegree(bool B[][10], int size){
// Maximun out degree of a given vertex v, should be n-1 at the most.
int degree = size - 1;
int index = -1;
for (int i = 0; i < 10; i++)
{
int count = 0;
for (int j = 0; j < 10; j++)
if (B[j]) count++;
if (count > 0 && count <= degree)
{
degree = count;
index = i;
}
}
return index;
}
int FindMinInDegree(bool B[][10], int vertex, int size){
// Maximun in degree of a given vertex v, should also be n-1 at the most.
int degree = size - 1;
int index = -1;
for (int i = 0; i < size; i++)
{
if (B[vertex])
{
int count = 0;
for (int j = 0; j < size; j++)
if (B[j]) count++;
if (count <= degree)
{
degree = count;
index = i;
}
}
}
return index;
}
void RemoveFromGraphMat(bool B[][10], int index, int size){
for (int i = 0; i < size; i++)
{
B[index] = false;
B[index] = false;
}
}
void PrintAllCouples(bool B[][10] , int A[], int size){
int i = FindMinOutDegree(B,10);
int j = FindMinInDegree(B,i,10);
while(j != -1 && i!= -1)
{
cout<<"("<<A<<","<<A[j]<<") ";
RemoveFromGraphMat(B,i,10);
RemoveFromGraphMat(B,j,10);
i = FindMinOutDegree(B,10);
j = FindMinInDegree(B,i,10);
}
}
void main(){
int A[10] = {-6, 31, 2, 10, -17, 6, 7, -3, 33, 10};
bool B[10][10];
BuildGraphMat(B,A,10);
PrintAllCouples(B,A,10);
{
|
חזרה לתחילת העמוד |
|
|
צחי@ משתמש חבר
הצטרף / הצטרפה: 02 January 2007 מדינה: Israel
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 20 September 2007 בשעה 16:12 | | IP רשוּם
|
|
|
|
האם האלגוריתם הזה מבטיח שלכל מערך של n מספרים יימצא תמיד מספר הצמדים המקסימלי האפשרי ?
|
חזרה לתחילת העמוד |
|
|
לוק אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 20 September 2007 בשעה 16:15 | | IP רשוּם
|
|
|
|
לא יודע למה אבל הקוד טיפה שונה בשליחה, אז אני אשלח אותו שוב כקוד.
קוד:
bool C(int a,int b){
// The relation a >= b AND a - b > 2.
return ((a >= b) && (a - b > 2));
}
void BuildGraphMat(bool B[][10] , int A[], int size){
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
B[i][j] = C(A[i],A[j]);
}
int FindMinOutDegree(bool B[][10], int size){
// Maximun out degree of a given vertex v, should be n-1 at the most.
int degree = size - 1;
int index = -1;
for (int i = 0; i < 10; i++)
{
int count = 0;
for (int j = 0; j < 10; j++)
if (B[i][j]) count++;
if (count > 0 && count <= degree)
{
degree = count;
index = i;
}
}
return index;
}
int FindMinInDegree(bool B[][10], int vertex, int size){
// Maximun in degree of a given vertex v, should also be n-1 at the most.
int degree = size - 1;
int index = -1;
for (int i = 0; i < size; i++)
{
if (B[vertex][i])
{
int count = 0;
for (int j = 0; j < size; j++)
if (B[i][j]) count++;
if (count <= degree)
{
degree = count;
index = i;
}
}
}
return index;
}
void RemoveFromGraphMat(bool B[][10], int index, int size){
for (int i = 0; i < size; i++)
{
B[i][index] = false;
B[index][i] = false;
}
}
void PrintAllCouples(bool B[][10] , int A[], int size){
int i = FindMinOutDegree(B,10);
int j = FindMinInDegree(B,i,10);
while(j != -1 && i!= -1)
{
cout<<"("<<A[i]<<","<<A[j]<<") ";
RemoveFromGraphMat(B,i,10);
RemoveFromGraphMat(B,j,10);
i = FindMinOutDegree(B,10);
j = FindMinInDegree(B,i,10);
}
}
void main(){
int A[10] = {-6, 31, 2, 10, -17, 6, 7, -3, 33, 10};
bool B[10][10];
BuildGraphMat(B,A,10);
PrintAllCouples(B,A,10);
{ |
|
|
|
חזרה לתחילת העמוד |
|
|
לוק אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 20 September 2007 בשעה 16:44 | | IP רשוּם
|
|
|
|
תראה זה סה"כ רעיון שחשבתי עליו אינטואיטיבית, כמובן שצריך להוכיח אותו באינדוקציה מתמטית לכל מערך בגודל אפשרי, ולכל יחס אפשרי. אבל אין לי כח לזה... אני לא הצלחתי למצוא אחד ששולל את הרעיון אז בוא תנסה אתה.
עוד שתי הערות לגבי התוכנית: 1. צריך לשלול התייחסות של איבר לעצמו. 2. צריך לתת ערך שלילי לכל אברי המטריצה B לפני בנייתה.
לכן תיקון פונקציית הבניה:
קוד:
void BuildGraphMat(bool B[][10] , int A[], int size){
// Initiate matrix with a false value.
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
B[i][j] = false;
// Building a directed matrix.
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
if (j != i)
B[i][j] = C(A[i],A[j]);
} |
|
|
דרך אגב אשמח אם תפרט על הרעיון שלך.
|
חזרה לתחילת העמוד |
|
|
צחי@ משתמש חבר
הצטרף / הצטרפה: 02 January 2007 מדינה: Israel
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 20 September 2007 בשעה 16:59 | | IP רשוּם
|
|
|
|
האינטואיציה שלי לגבי פתרון דומה לשלך, למעט העובדה שבאלגוריתם שלי אני מחלק דירוג לכל הקשתות לפי סכום הדרגות של הקדקודים שלהן, ולפי הדירוג הזה אני בוחר איזה קשת להוציא, מחשב את הדירוג החדש וכו'.
למרות זאת, אני לא מרגיש עדיין טוב עם הפתרון הזה, הוא יותר מדי חמדן לטעמי ולכן ללא הוכחה שהוא תמיד מוצא את מקסימום הצמדים ללא תלות בתוכן המערך אני לא מרגיש בטוח להשתמש בו. הפתרון שאני מחפש חייב להיות נכון ב-100% מהמקרים.
אגב, היחס C הוא חסר משמעות לצורך הוכחה, הוכחה יכולה להתבסס על המבנה של הגרף בלבד, כל יחס C משרה מבנה אחר.
אני כרגע בשלב של לנסות לראות אם קיים גרף שעבורו האלגוריתם שוגה - כלומר לא מוצא את מס' הצמדים המקסימלי.
|
חזרה לתחילת העמוד |
|
|
לוק אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 20 September 2007 בשעה 19:09 | | IP רשוּם
|
|
|
|
למה אתה צריך את זה בכלל?
כלומר, שתף אותנו...
|
חזרה לתחילת העמוד |
|
|
צחי@ משתמש חבר
הצטרף / הצטרפה: 02 January 2007 מדינה: Israel
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 20 September 2007 בשעה 21:47 | | IP רשוּם
|
|
|
|
צר לי אבל אני לא יכול לשתף. אני יכול לומר רק שיכולים להיות לזה יישומים רבים. אגב, שכחתי לציין מקודם, חשיבה יפה - הגעת כמעט בדיוק לאותו אלגוריתם שאני חשבתי עליו וסחתיין על ההשקעה עם הקוד.
|
חזרה לתחילת העמוד |
|
|
לוק אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 20 September 2007 בשעה 22:16 | | IP רשוּם
|
|
|
|
קודם כל תודה רבה.
בעקרון יש פתרון מהיר יותר עם הוכחה לכל המקרים האפשריים.
אבל, אני אשאיר לך לחשוב על זה כיוון שלך תדע...
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 01:00 | | IP רשוּם
|
|
|
|
שתי שאלות חדשות (פשוטות) לשנה החדשה.
1. יש לכתוב תוכנית כאשר בהינתן מערך מספרים חיוביים וסכום תקבע האם קיימת קבוצה חלקית של מספרים מתוך המערך שסכומם יהיה זהה לסכום הנתון.
2.בהינתן מס' טיבעי כלשהו יש להדפיס את כל תת הקבוצות למס' זה. לדוגמה: קלט: 3. פלט: {{1,2,3}, {1,2}, {1,3}, {1}, {2,3}, {2}, {3}, {} } הערות: אפשר גם בלי סוגריים.
|
חזרה לתחילת העמוד |
|
|
ולוסט אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 15:45 | | IP רשוּם
|
|
|
|
שלום,
השאלה ששאלת חמציר הינה בעיית "NP-Complete" הקלאסית ביותר שיש, ולכן ל-N גדול, אין לה תשובה יעילה (או לפחות לא מצאו ב-10 שנים האחרונות).
|
חזרה לתחילת העמוד |
|
|
חמיצר אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 16:45 | | IP רשוּם
|
|
|
|
ולוסט תודה אני יודע,
ישנו פתרון לא יעיל המתאים ל-N-ים קטנים (יחסית) אותו אני מבקש. כמובן שלא דרשתי יעילות בפתרון.
|
חזרה לתחילת העמוד |
|
|
ולוסט אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 16:53 | | IP רשוּם
|
|
|
|
כתבתי תשובה לשאלה השניה ב C# אך גם הוא לא יעיל ל N גדול (אולי עוד NP?):
קוד:
class Program { public static void Sub(int N, string SUB, ref List<string> allSubs) { if (N > 0) { Sub(N - 1, SUB + Convert.ToString(N) + " ", ref allSubs); Sub(N - 1, SUB, ref allSubs); } else allSubs.Add(SUB); } static void Main(string[] args) { List<string> Allsubs = new List<string>(); string SUB = null; Allsubs.Add(""); int N = Convert.ToInt32(Console.ReadLine()); Sub(N, SUB, ref Allsubs); foreach (string s in Allsubs) { Console.WriteLine(s); } } }
|
|
|
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 17:20 | | IP רשוּם
|
|
|
|
הקוד היה יכול להיות יותר נחמד אם היה שימוש ב-string builder או stream לפלט, ולא היה מחבר מחרוזות כל הזמן...
ואגב, רשימה היא מחלקה, לכן Allsubs הוא מצביע, ולכן לא צריך להעביר כ-ref, אוטומטית עובד במצביע...
|
חזרה לתחילת העמוד |
|
|
ולוסט אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 17:31 | | IP רשוּם
|
|
|
|
תודה שושן , באמת חששתי שה ref לא הכרחי אבל מה לעשות אני חדש בC#.
בכל זאת, אם הייתי רוצה להוציא את התשובה כפלט ישירות מהפונקציה לא הייתי צריך להשתמש ברשימת allSubs בכלל, אבל בחרתי לשמור את הנתונים ע"מ שיהיה קל לבצע איתם עוד פעולות אם רוצים. אני ישמח לראות אם מישהו מצא פתרון ל N גדול.
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 17:56 | | IP רשוּם
|
|
|
|
זהו, בגלל זה הצעתי להשתמש ב-Stream או TextWriter או משהו כזה לפלט, או אפילו לממש את IEnumrable שמחזיר רשימות מספרים, ככה זה קוד גנרי אבל לא תלוי שימוש.
|
חזרה לתחילת העמוד |
|
|
צחי@ משתמש חבר
הצטרף / הצטרפה: 02 January 2007 מדינה: Israel
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 24 September 2007 בשעה 21:32 | | IP רשוּם
|
|
|
|
ולוסט כתב:
כתבתי תשובה לשאלה השניה ב C# אך גם הוא לא יעיל ל N גדול (אולי עוד NP?): |
|
|
רק בשביל הסדר הטוב: הבעיה היא למצוא את כל תתי הקבוצות של קב' המספרים, כפי שניתן לראות, מס' תתי הקבוצות של קב' בגודל n הוא אקספוננציאלי ביחס ל-n, ולכן כל אלגוריתם שמדפיס את כל תתי הקבוצות, מבצע בהכרח לפחות מס' אקספוננציאלי של צעדים ולכן בוודאות אינו פולינומיאלי ובפרט אינו NP complete. הוא למעשה שייך למחלקה EXP.
|
חזרה לתחילת העמוד |
|
|
ולוסט אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 23:05 | | IP רשוּם
|
|
|
|
כתבתי קוד לשאלת הספירלה שנשאלה פה קודם לכן:
קוד:
class Program { public static void Spiral(int N, ref int[,] graph, int X, int Y, int oN, int ooN) { if (N > 0) { N--; if (X == ooN - oN && Y + 1 != oN) //Go RIGHT { graph[X, Y] = N; Spiral(N, ref graph, X, Y + 1, oN, ooN); } if (Y + 1 == oN && X + 1 != oN) //GO DOWN { graph[X, Y] = N; Spiral(N, ref graph, X + 1, Y, oN, ooN); } if (X + 1 == oN && Y > ooN - oN) //GO RIGHT { graph[X, Y] = N; Spiral(N, ref graph, X, Y - 1, oN, ooN); } if (X >= ooN - oN + 1 && Y == ooN - oN) //GO UP { if (Y == ooN - oN && X == ooN - oN + 2) //RECUR { graph[X, Y] = N; oN--; Spiral(N, ref graph, X - 1, Y, oN, ooN); } else { graph[X, Y] = N; Spiral(N, ref graph, X - 1, Y, oN, ooN); } } } } static void Main(string[] args) { Console.WriteLine("Insert a perfect square number to create the spiral"); int N = Convert.ToInt32(Console.ReadLine()); int D = (int)Math.Sqrt(N); int[,] graph = new int[D,D]; Spiral(N, ref graph, 0, 0, D,D); for (int i = 0; i < D; i++) { for (int j = 0; j < D; j++) Console.Write("{0,6}", graph[i, j]); Console.WriteLine(); Console.WriteLine(); } } }
|
|
|
תוכנית זאת מצרפת את המספרים ההולכים וקטנים מ-N למטריצה בסדר נגדי לכיוון הספירלה (פנימה במקום החוצה) דרך פונקציה ריקורסיבית ומדפיסה את המטריצה. זה אפשרי לשחק מעט עם הפרמטרים של הפונקציה כך שיהיה אפשר ליצור ספירלה בעלת שני מימדים שונים זה מזה, אך כמובן שמכפלתם תמיד יהיה חייב להיות שווה ל-N.
|
חזרה לתחילת העמוד |
|
|
לוק אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 23:10 | | IP רשוּם
|
|
|
|
בראש ובראשונה צחי צודק, כלומר כיוון שמס' תתי הקבוצות לקבוצה נתונה היא אקספוננציאלית, (שתיים בחזקת N בדיוק), וכיוון שאין דרך להדפיס את הקבוצות מבלי ליצור אותם שידועה לי, הסיבוכיות הטובה ביותר שניתן להשיג היא אקספוננציאלית. בכל מקרה כל הכבוד לך . עוד פתרון טיפה שונה:
ניתן לקבוע באופן בינארי מי מהאיברים נמצא בקבוצה ומי לא עפ"י עקרון קוד גריי, קוד בינארי זה מתנהג בצורה בה בין כל שני אברים ברצף יש שינוי של ביט אחד לכל היותר. (ניתן לקרוא עליו כאן -[URL=http://he.wikipedia.org/wiki/%D7%A7%D7%95%D7%93_%D7%92%D7%A8%D7%99%D7%99]קוד גריי[/URL).
כעץ ניקח לדוגמה 3 = n תתי הקבוצות הם: , , , , , , , . אם נתבונן היטב בתתי הקבוצות מימין לשמאל בסדר זה, נוכל לראות כי מקבוצה לקבוצה האיברים משתנים ע"י הוצאה או הכנסה של איבר אחד בדיוק. אם נסתכל על סדרת האיברים שמוכנסים או יוצאים מהקבוצה נקבל את הסדרה הבאה: 1 2 1 3 1 2 1 אחרי זמן מה ניתן לזהות חוקיות רקורסיבית האומרת:
(T(n+1) = T(n),n+1,T(n T(1) = 1
כעת ניתן לבנות אלגוריתם שבנוי על עקרון זה ומטפל ביצירת הקבוצות ע"י הכנסה והוצאה של איבר אחד בדיוק בכל איטרציה. האלגוריתם יניב פתרון איטרטיבי בהנחה שסדרת האיברים שיש להכניס ולהוציא מהקבוצה ידועה לנו מראש וזמן הדפסת הקבוצה זניח.
אלגוריתם: 1.צור את סדרת המספרים. 2.הדפס קבוצה ריקה. 3.בעבור כל איבר מסדרת האיברים בצע: 1.3 אם האיבר לא מופיע בקבוצה הכנס אותו לקבוצה אחרת הוצא אותו מהקבוצה. 2.3 הדפס קבוצה נוכחית.
סיבוכיות: יצירת סדרת המספרים - שתיים בחזקת N. כמות האיטרציות המינימלית הנדרשת היא כגודל הסדרה פחות הקבוצה הריקה כלומר - 1 - שתיים בחזקת N. סה"כ אלגוריתם (לא יעיל) ב- (O(2^N.
מחלקה הממשת רעיון זה ב-CPP:
קוד:
class BRGC{
private:
int *g;
bool *bool_arr;
// bool_arr is a boolean array that determines which value is
// in the set for example: {true,false,true} means the
// set is {1,3}.
int index,N;
public:
// Constructor:
// - allocates an int array of 2^N -1 to g;
// - allocates a bool array of N to bool_arr;
BRGC(int n){}
// Destructor.
~BRGC(){}
// Recursion building the number series.
void Build_BRGC_Array(int n)
{
if (n > 0)
{
Build_BRGC_Array(n-1);
g[index++] = n;
Build_BRGC_Array(n-1);
}
}
// Printing current set.
void Print_Set(){}
// Printing the number series.
void Print_Sequens(){}
// Main Algorithm: Printing All Subsets.
void Print_All_SubSets()
{
Print_Sequens();
cout<<"The Total "<<index+1<<" Subsets Are:"<<endl;
Print_Set();
for (int i = 0; i < index; ++i)
{
if (!bool_arr[g[i]- 1])
bool_arr[g[i] -1] = true;
else bool_arr[g[i] -1] = false;
Print_Set();
}
for (int i = 0; i < N; ++i)
bool_arr[i] = false;
}
};
|
|
|
|
חזרה לתחילת העמוד |
|
|
שושן אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 September 2007 בשעה 23:27 | | IP רשוּם
|
|
|
|
רק התשובה לשאלת הספירלה, צוין בשאלה שלא להשתמש במערכים, בניגוד לתשובה,
[ומה שמבינים זה - אלא להגיע לחישוב מספר לפי אינדקס]
וה-N שנקלט זה ישר ה-D שעשית שורש ל-N.
|
חזרה לתחילת העמוד |
|
|
linux rules משתמש מתחיל
הצטרף / הצטרפה: 27 December 2007
משתמש: מנותק/ת הודעות: 1
|
נשלח בתאריך: 27 December 2007 בשעה 20:47 | | IP רשוּם
|
|
|
|
הפתרון שהועלה אינו יעיל אם מדובר בקבוצה שהיא לא של int אלא של אובייקטים, לדוגמא אובייקטים מסוג HashTable. בעיה לדוגמא: נתון מערך של HashMaps, המכילים איזשהו data. אנו רוצים למצוא את הסכום המקסימלי שניתן להרכיב מאיברי המערך. כלומר, למצוא את כל תתי הקבוצות של מערך זה (באמצעות מערך בוליאני) ולהחזיר את סכום תת הקבוצה המקסימלי. פתרון לא יעיל יהיה לבנות מערך של (2^n) של מצביעים ל HashMap
|
חזרה לתחילת העמוד |
|
|
king445 משתמש מתחיל
הצטרף / הצטרפה: 23 January 2008 מדינה: Israel
משתמש: מנותק/ת הודעות: 44
|
נשלח בתאריך: 23 January 2008 בשעה 22:26 | | IP רשוּם
|
|
|
|
1. תוכנית לקולטת מחרוז מסוימת ומדפיסה את האותיות המחרוזת כך שרווח בינהם
הדפסה בסוף היא של מחרוזת שלמה.
*נראה אותכם, אני אכנס מחר אם לא תדעו אני אשלח את התשובה
זה אחד החזקים!
__________________ מיכאל המלך!
|
חזרה לתחילת העמוד |
|
|
הקיפוד אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 20 February 2008 בשעה 18:39 | | IP רשוּם
|
|
|
|
לא הבנתי- אתה רוצה שנקלוט מחרוזת ונדפיס את המחרוזת שבין כל זוג אותיות צמודות ישנו רווח?
(אולי זה בגלל שאני לא יודע תכנות- אבל לא הבנת)
|
חזרה לתחילת העמוד |
|
|
Morishani אורח
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 22 May 2008 בשעה 11:07 | | IP רשוּם
|
|
|
|
shoshan כתב:
שאלה: כתוב תכנית שתקבל מספר N ותדפיס ללא שימוש במערכים או בזיכרון נוסף ספירלה של המספרים 0 עד N*N-1.
לדוגמא עבוד N=10 התוכנית תדפיס
|
|
|
מה הכוונה שימוש בזיכרון נוסף?
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 22 May 2008 בשעה 17:23 | | IP רשוּם
|
|
|
|
הכוונה ליצירת מערך בגודל N או בגודל N על N, כלומר כתלות ב-N.
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
wavenator משתמש מתחיל
הצטרף / הצטרפה: 07 October 2008
משתמש: מנותק/ת הודעות: 2
|
נשלח בתאריך: 12 April 2009 בשעה 11:19 | | IP רשוּם
|
|
|
|
king445 כתב:
1. תוכנית לקולטת מחרוז מסוימת ומדפיסה את האותיות המחרוזת כך שרווח בינהם
הדפסה בסוף היא של מחרוזת שלמה.
*נראה אותכם, אני אכנס מחר אם לא תדעו אני אשלח את התשובה
זה אחד החזקים! |
|
|
אתה רציני? לא הייתי קורא לזה חידה
|
חזרה לתחילת העמוד |
|
|