שלושה פתרונות ראשונים ל Advent Of Code 2025
עוד שנה נגמרת וכמו בכל דצמבר אריק ווסטל מפרסם שוב סט חידות תכנות חדש באתר Advent Of Code. הפעם מספר החידות ירד ל 12, בעיקר כי הוא קצת התעייף אבל אני חייב להודות שכמו עם העוגות של שמו, גם פה ההקטנה היא לטובה. כבר כמה שנים שלא הצלחתי למצוא זמן לסיים את כל הסט ואולי הפעם עם 12 חידות אוכל למצוא את המוטיבציה והזמן להתמיד.
בינתיים אני לא בקצב ואני מסיים את השבוע הראשון עם 3 חידות פתורות מתוך 5 שפורסמו. תכף החידות והפתרונות שלי אבל קודם הבהרה - אני מפרסם את הפתרונות האלה לא בתור פתרונות בית ספר שצריך ללמוד מהם (את זה אפשר לקבל מ ChatGPT שאלוף בחידות מהסוג הזה) אלא כדי לתת גם לכם מוטיבציה לנסות ולפתור. זה אולי לא מושלם, לא מספיק מהיר וקצת מסורבל אבל גם זה חלק מהקסם של לפתור לבד ולהתבלבל באינדקסים. בואו נראה את הקוד.
1. יום 1 - הכספת
התרגיל כאן:
https://adventofcode.com/2025/day/1
מאיזושהי סיבה כשהתחלתי את המשחק חשבתי שפייתון היא השפה המושלמת אז פתרתי בה. אל דאגה מהר מאוד חזרתי לרובי. יום ראשון חלק 1:
def move_dial(old_value, line):
count = int(line[1:])
if line.startswith("L"):
return (old_value - count) % 100
elif line.startswith("R"):
return (old_value + count) % 100
else:
raise Exception(f"Line {line}")
dial = 50
zero_count = 0
with open('input.txt', encoding='utf-8') as f:
for line in f:
dial = move_dial(dial, line)
if dial == 0:
zero_count += 1
print(f"{zero_count=}")
חלק 2 - ארוך מדי וטעויות טפשיות בחשבון אבל בסוף זה עבד:
def dial_diff(line):
count = int(line[1:])
if line.startswith("L"):
return -count
elif line.startswith("R"):
return count
else:
raise Exception(f"Line {line}")
dial = 50
zero_count = 0
with open('input.txt', encoding='utf-8') as f:
for line in f:
count = dial_diff(line)
full_rounds = abs(count) // 100
if count > 0:
# move right
next_dial = (dial + count) % 100
if (next_dial < dial and next_dial != 0):
full_rounds += 1
elif count < 0:
next_dial = (dial + count) % 100
if (next_dial > dial and next_dial != 0 and dial != 0):
full_rounds += 1
dial = next_dial
zero_count += full_rounds
if dial == 0:
zero_count += 1
print(zero_count)
2. יום 2 - חנות מתנות
התרגיל כאן
https://adventofcode.com/2025/day/2
חלק ראשון חזרתי לרובי וכבר נשמתי לרווחה. את החלק הראשון עוד פתרתי בלי ביטויים רגולאריים אבל בחלק השני קיצרתי את החישובים ונתתי למנוע הביטויים הרגולאריים לעבוד בשבילי:
class Aoc2025Day2
def initialize(input_file_name)
@ranges = parse(input_file_name)
end
def parse(input_file_name)
File
.read(input_file_name)
.split(',')
.map {|r| r.split('-') }
.map {|a, b| a.to_i..b.to_i }
end
def part1
@ranges.flat_map {|r| r.filter {|id| valid?(id) } }.sum
end
def part2
@ranges.flat_map {|r| r.filter {|id| id.to_s.match(/^(\w+)\1+$/) } }.sum
end
def valid?(id)
ids = id.to_s
ids[0...ids.length / 2] == ids[ids.length / 2...]
end
end
if __FILE__ == $PROGRAM_NAME
a = Aoc2025Day2.new("input.txt")
puts a.part1
puts a.part2
end
3. יום 3 - לובי
התרגיל כאן
https://adventofcode.com/2025/day/3
הייתי שמח לכתוב פתרון יותר יעיל שסורק את המערך רק פעם אחת אבל index ו max כבר בנויים ברובי ואצל מתכנתים העצלות לפעמים מנצחת. לפחות הצלחתי לחתוך את המחרוזת בלי להתבלבל יותר מדי באינדקסים. זה הקוד:
class Day3
attr_accessor :banks
def parse(input_file_name)
@banks = File
.read(input_file_name)
.lines
.map {|l| l.strip.split('') }
.map {|bank| bank.map(&:to_i) }
end
def part1
values = banks.map {|b| iterate_bank(b, 2) }
puts values.sum
end
def part2
values = banks.map {|b| iterate_bank(b, 12) }
puts values.sum
end
def iterate_bank(bank, num_batteries)
value = 0
next_digit_index = 0
num_batteries.times do |i|
options = bank[next_digit_index..-(num_batteries - i)]
next_digit = options.max
next_digit_index += options.index(next_digit) + 1
value += next_digit * (10 ** (num_batteries - 1 - i))
end
value
end
end
if $PROGRAM_NAME == __FILE__
d = Day3.new
d.parse("input.txt")
d.part1
d.part2
end