יום 8 - Memory Maneuver

קישור לחידה המקורית:
https://adventofcode.com/2018/day/8

פיתרון בשפת רובי:

$part1 = 0

class Metadata
  attr_reader :value

  def initialize(input)
    md = input.match(/^(\d+)/)
    @value = md[1].to_i
    $part1 += value
    input.slice!(0..md.end(0))
  end
end

class Node
  attr_accessor :header, :children

  def initialize(input)
    md = input.match(/^(\d+) (\d+)\s*/)
    input.slice!(0, md.end(0))
    self.header = []
    self.children = []
    _, @children_size, @header_size = *md.to_a.map(&:to_i)

    @children_size.times do
      @children << Node.new(input)      
    end

    @header_size.times do
      @header << Metadata.new(input)
    end
  end

  def value
    return header.map(&:value).sum if children.length == 0

    res = 0
    header.each do |entry|
      ref = entry.value - 1
      next if ref < 0
      next if ref >= children.length
      res += children[ref].value
    end

    res
  end
end

root = Node.new(ARGF.first)
puts root.value
# puts $part1

שימו לב לתבנית של ה Parser בבנאי של Node - כל אוביקט לוקח את מה שהוא צריך מה input ואז מוחק את מה שלקח. בצורה כזאת הילדים יכולים ״לתקשר״ אחד עם השני בעת הבניה שלהם, כל ילד ״מודיע״ דרך העבודה על המידע המשותף כמה מידע הוא לקח.

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