• בלוג
  • האופרטור % וקריאה אחרי סוף המערך

האופרטור % וקריאה אחרי סוף המערך

19/09/2018

השבוע פתרתי יחד עם כמה חברים ותלמידים את היום הראשון מ Advent Of Code 2017. עשינו את זה לאט כך שאפשר היה לראות גישות שונות ולהתעכב על רעיונות שחוזרים על עצמם בתכנות בכל שפה בה אתם עובדים. אם בא לכם להצטרף למשחק החידה השניה באוויר בקישור הזה:

https://forum.tocode.co.il/t/advent-of-code/778

במהלך הדיון על החידה הראשונה עלה הנושא של קריאה ממערך בצורה מעגלית - לדוגמא בהינתן המערך:

arr = [10, 20, 30, 40]

אנחנו יודעים שהערך באינדקס 0 הוא 10, באינדקס 1 הוא 20 וכן הלאה. אבל מה אם נתקדם 10 מקומות מתחילת המערך וכל פעם שנעבור את אינדקס 3 נחזור אחורה ונאפס את האינדקס... לאיזה ערך נגיע?

מסתבר שהאופרטור % עוזר לפתור מהר שאלות מסוג זה. האופרטור % מחזיר את שארית החלוקה לדוגמא:

5 % 2 == 1

בגלל שהכפולה של 2 שהכי קרובה ל-5 היא המספר 4 (זה הכי קרוב שנגיע ל-5), ונשאר עוד 1 שנקרא שארית. שיטה די מקובלת לרוץ בצורה מעגלית על מערך היא להסתכל על שארית החלוקה באורך המערך. לדוגמא המערך שלנו הוא באורך 4. לכן קל לשאול מה האיבר באינדקס 0 (זה 10) או באינדקס 2 (זה 30). אבל, מה האיבר באינדקס 4? באינדקס 10? באינדקס 12? כלומר מה יקרה כשתקדם במערך אחרי האורך שלו?

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

real_index = i % len(arr)

לדוגמא האינדקסים שכתבתי קודם:

arr[4 % len(arr)] == arr[0] == 10

arr[5 % len(arr)] == arr[1] == 20

arr[10 % len(arr)] == arr[2] == 30

arr[12 % len(arr)] == arr[0] == 10

שימוש באופרטור % הוא הרבה יותר מהיר מחישוב האינדקס בלולאה למשל ולכן נרצה להשתמש בו גם בתרגילים ב Advent Of Code אבל כמובן גם בחיים בכלל.

הנה דוגמא נוספת לאותו מנגנון הפעם בשפת JavaScript שבוחרת צבע מתוך מערך של צבעים בצורה מחזורית:

const colors = ['red', 'blue', 'green', 'white', 'yellow', 'brown', 'magenta', 'cyan', 'pink', 'orange'];
let idx = 0;

function changeColor() {
  idx = (idx + 1) % colors.length;
  document.body.style.backgroundColor = colors[idx];
}

אפשר לראות אותה בפעולה בקודפן הבא - פשוט לחצו בכל מקום בתוך התיבה כדי לראות את הצבע משתנה: