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

חמש ושבע

זמן קריאה: 4 דקות

היום לא ממש אלגוריתם אלא חידה תכנותית מאוד חמודה שסיפרו לי עליה.
החידה היא כזו – 

צריך לכתוב 4 פונקציות שונות שמקבלות מספר אחד – 5 או 7 ומחזירות את המספר השני.
הפונקציות צריכות להיות שונות אחת מהשנייה במהותן ואסור להן להשתמש בשום סוג של if,switch וכיוצ"ב.

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

אז לפניכן ולהנאתכן, הפונקציות – 

פונקציה ראשונה, סופר פשוטה, פשוט חישבתי את הסכום של 5 ו-7, ואני אחסר ממנו את המספר שקיבלתי, ובכך אחזיר את השני.

def five_and_seven_a(x):
	sum = 12
	return sum - x

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

def five_and_seven_b(x):
	arr = [5,7]
	arr.remove(x)
	return arr[0]

השיטה השלישית לא מושלמת בעיני, כי היא קצת דומה מדי לשיטה הראשונה, אני אשאיר לכן לשפוט האם היא מספיק שונה ומעניינת. בשיטה הזו אני משתמש בפעולת XOR על הביטים של המספרים, במקום המספרים עצמם. פעולת XOR מחזירה 0 על ביטים זהים ו-1 על ביטים שונים. כלומר, XOR על שני מספרים זהים "מאפס" את ההשפעה שלהם.
התוצאה של XOR על שלושה מספרים ששניים מהם זהים מחזירה את השלישי – 

x ^ y ^ x = y y ^ x ^ y = x

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

def five_and_seven_c(x):
	return 5 ^ 7 ^ x

השיטה הרביעית היא הכי מסובכת שלא לצורך, אבל זה בגלל שכבר ממש נגמרו לי הרעיונות.
הרעיון הוא כזה – אני מחשבת את ההפרש בין המספר שקיבלתי ל-7 – אם קיבלתי 7 ההפרש יהיה אפס, ואם קיבלתי 5 ההפרש יהיה מינוס 2.
איך מגיעים מההפרש למספר הנגדי?
מחסרים ממנו 5 ומחזירים את הערך החיובי של התוצאה.
אם ההפרש הוא 0, תוצאת החיסור תיתן 5-, והערך החיובי יהיה 5. אם ההפרש הוא 2- תוצאת החיסור תיתן 7- והערך החיובי יהיה 7.

def five_and_seven_d(x):
	diff = x - 7
	return abs(diff - 5)

זהו! אלו היו כל הרעיונות שלי!

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

ואם יש לכן עוד חידות לתת לי לחשוב עליהן תעשו את זה, כי אני נהנית מחידות 🙂

אין קוד בגיט!

11 תגובות בנושא “חמש ושבע

  1. עוד כמה אפשרויות:
    1. ערך אבסולוטי של x – 12.
    2. לחלק 35 ב-x (חשבתי על זה לפני שראיתי שכבר הציעו בתגובה אחרת).
    3. להכין מערך שבמקום 5 מכיל 7 ובמקום 7 מכיל 5. לשלוף את איבר x.
    4. אפשר לייעל: לשלוף את האיבר ((x פחות 3) חלקי 2) מהמערך [7,5].
    5. לספור כמה פעמים x מופיע במחרוזת '75275571555775' (או במערך דומה).
    6. למצוא את המיקום של x במחרוזת '1098765' (או במערך דומה).
    7. לחלק את x ב-(x פחות 5), להוסיף לתוצאה 1.5 ולהחזיר. כל זה בתוך try…catch ואם יש חריג להחזיר 7.
    8. לולאה: בוחרים מספר אקראי בין 0 ל-1. מכפילים ב-4. מוסיפים 4. מעגלים לשלם הקרוב. אם המספר זוגי או שווה ל-x חוזרים לתחילת הלולאה. אחרת מחזירים אותו כתוצאה.
    9. מוסיפים ל-x עוד (8 פחות x) ועוד (3 פחות x) ועוד 1.
    10. לקרוא לכל הפונקציות הקודמות ולחשב את הממוצע, או (בהנחה שמספרן אי זוגי) לקרוא להן בשרשור 😉

    1. היישור לעברית הורס, אז אכתוב במילים: מעלים את x בחזקת 15 ועושים מודולו 17.

  2. גם אני חשבתי קודם כל על פתרון חשבוני (12 פחות הקלט).
    הפתרון הבא היה מניפולציית ביטים (אפשר לעשות XOR של הקלט עם 2)
    בשלישי חשבתי על מה ש"חיים ארוכים" הציע/ה (בהכללה, זה פתרון של טבלת Lookup)

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

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

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

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

    בפייתונית (מקווה שיישור יעבוד):

    def t(x): return (-12/35)*x*x + (109/35)*x

  4. עוד הערה:
    כדאי לשים לב שהשיטה הראשונה שלך, השיטה הרביעית שלך, והשיטה הראשונה של 'חיים ארוכים' ( ערך אבסולוטי של x – 12), הן בדיוק אותו דבר, ההבדל היחיד הוא סימן מינוס.

השאר תגובה