../images/Emo26.gif
מה שאהבתי בשאלה הוא לא הקושי שבה, אלא הפשטות... שימו לב לפתרון נחמד הנעזר בסימטריות: א. כידוע, סימטריה היא איזומטריה, וכל איזומטריה ניתנת להצגה כמכפלה של שיקופים. יש ארבעה שיקופים אפשריים במטריצה: שניים אורכיים ושניים אלכסוניים. נקרא להם n, e, ne, nw לפי כיוון ציר השיקוף עפ"י שושנת הרוחות. אפשר בקלות לאמת את הטרנספורמציות הבאות:
n: (i,j) -> (i, n + 1 - i) {We assume the numbering is 1..n} e: (i,j) -> (n 1 - i, j) nw: (i,j) -> (j,i) ne: (i,j) -> (n 1-i, n 1-j)
אם נסמן ב-(Td(i,j הטרנספורמציה המתאימה לשיקוף בכיוון d עבור d = n, e, ne, nw, נקבל את הקוד הג'נרי הבא:
Reflect(A, d): {B is a new matrix} for i = 1..n, j = 1..n do B[Td(i,j)] := A[i,j]
מכאן נקבל, למשל, בפשטות את הסיבוב בזוית של 90 מעלות:
RotateLeft := Reflect(Reflect(A, n), nw)
ב. אם אנחנו רוצים גם להיות יעילים מבחינת מקום, נשים לב שאנו יכולים לעבור רק על אברים שנמצאים בצד אחד של ציר השיקוף, ופשוט להחליף כל אבר בשיקוף שלו. נוכל לעשות זאת ע"י יצירת איטרטור שמחזיר את האינדקסים שנמצאים בצד אחד של השיקוף. אשאיר כתרגיל אימות של הקו-רוטינות הבאות:
IterateN: for i= 1..n, j = 1..[n/2] do return (i,j) return done; IterateE is similar IterateNW: for i = 2..n, j = 1..i-1 do return (i,j) return done; IterateNE is similar
ואז הקוד עבור השיקוף יהיה:
Reflect(A, d): ind := iterateD while (ind <> done) do switch(A(ind), A(Td(ind)) ind := iterateD
מה דעתכם? אהד.