פתרון Advent Of Code 2025 יום 6
אני ממשיך עם סדרת Advent Of Code לשמחתנו השנה יש רק 12 חידות אז יש סיכוי שאצליח לפתור ולפרסם את כולם לפני שיעלו האתגרים של 2026. אנחנו היום באמצע הדרך עם יום 6 ותרגיל שאני חשבתי שהיה סופר מעניין. בואו נראה את המספרים.
1. האתגר
נתון קלט שנראה די פשוט:
123 328 51 64
45 64 387 23
6 98 215 314
* + * +
יש פה טורים של מספרים ובתחתית כל טור מופיע סימן פלוס או כפול. המשימה שלנו לכפול או לחבר את המספרים בטור (לפי הסימן) ובסוף לחבר את התוצאות. בדוגמה התוצאה היא 4277556.
2. הפתרון
הדרך לפתרון די פשוטה: קוראים את הקלט שורה שורה, שוברים כל שורה לפי רווחים, כי אנחנו יודעים שיש את אותו מספר עמודות בכל שורה ובונים מערך דו מימדי של כל הגריד. בסוף לוקחים את הסימן האחרון בכל עמודה בתור פעולה ומפעילים אותה על כל הפריטים באותה עמודה. זה הקוד ברובי:
class Day6
def initialize(filename)
@filename = filename
end
def part1
columns = []
File.read(@filename).lines do |line|
columns << line.strip.split(/\s+/)
end
@operators = columns.pop
@values = columns
results = @operators.each_with_index.map do |op, idx|
@values.map {|v| v[idx].to_i }.reduce(op.to_sym)
end
pp results.sum
end
end
3. הטוויסט
אחרי שמגישים את החלק הראשון מגלים את הטוויסט בתרגיל - שימו לב אומרים לנו שחלק מהמספרים מיושרים לימין וחלק לשמאל:
123 328 51 64
45 64 387 23
6 98 215 314
* + * +
בעצם המספרים בכל טור כתובים מלמעלה למטה ולא רגיל משמאל לימין, לכן בטור הימני המספר הראשון הוא 4 (הטור הימני ביותר), אחריו יש לנו טור בו יש את 4, 3 ו-1 ולכן המספר הוא 431 והמספר האחרון בטור הימני הוא 623. חיבור שלושתם נותן 1058.
השינוי הזה משפיע ישירות על הבלוק:
File.read(@filename).lines do |line|
columns << line.strip.split(/\s+/)
end
בחלק הראשון חשבנו שאפשר להתעלם מרווחים ושיש אותו מספר של עמודות בכל שורה. עכשיו אנחנו מגלים שעדיין יש אותו מספר עמודות בכל שורה אבל חשוב לשמור על הריווח כי 64 שמיושר לשמאל לא מתנהג כמו 51 שמיושר לימין שיושב ממש משמאלו.
האתגר השני שלא רואים בנתוני הדוגמה הוא שכל עמודה יכולה להיות באורך שונה. בנתוני הדוגמה כל העמודות כללו מספרים בני 3 ספרות ולכן לכולן היה אותו אורך אבל במקרה הכללי קל לראות שאם יש טור עם מספרים בני שתי ספרות או ספרה אחת נדרש טיפול שונה, כלומר קלט כזה לגמרי יכול לקרות:
123 32 51 64
45 64 387 23
6 98 215 314
* + * +
מה עושים? הפעם אנחנו צריכים לזהות מה אורך כל עמודה ואז לפצל את השורה לעמודות בצורה קשיחה לפי מספר התווים שאנחנו יודעים שיש בכל עמודה. אפשר להגיד שבחלק הקודם שברנו את השורה לפי תו הפרדה ועכשיו אנחנו שוברים לפי אורך או אינדקסים. בשביל לגלות את האורך של כל עמודה אפשר להסתכל על השורה האחרונה שורת הפעולות. זה הקוד ברובי לחלק השני:
def part2
lines = File.read(@filename).lines
operators_line = lines.pop
column_sizes = operators_line.scan(/[+*]\s*/).map {|i| i.size - 1}
data = lines.map(&:chomp).map do |line|
column_sizes.map {|s| r = line.slice!(0, s); line.slice!(0, 1); r }
end
operators = operators_line.strip.split(/\s+/).map(&:to_sym)
columns = (0...operators.size).map {|col| data.map {|d| d[col] } }
values = columns.map do |column|
(0...column[0].size).map {|i| column.map {|c| c[i] }.join('').to_i }
end
@results = operators.each_with_index.map {|o, i| values[i].reduce(o) }
pp @results.sum
end
סך הכל אני מודה שבחלק השני הסתבכתי קצת עם האינדקסים וכנראה אפשר לראות את זה כשקוראים את הקוד. למרות זאת אחרי כמה בעיטות הקוד עבד ומצליח לטפל בכל מקרי הקצה שמצאתי ולהגיע לתשובה הנכונה.