#!/usr/bin/env ruby

def input
  @input ||= STDIN.read.split("\n\n")
end

def initial_stacks
  @initial_stacks ||= (
    input.first.
          split("\n").
          map(&:chars).
          transpose.
          select { |stack| stack.any? { |e| /\d+/.match(e) } }.
          map { |stack| *contents, number = stack; contents.delete(" "); [number.to_i, contents] }.
          to_h
  )
end

def instructions
  @instructions ||= input.last.split("\n").map { |line| line.scan(/\d+/).map(&:to_i) }
end

def follow_instruction(stacks, count, source, destination)
  count.times do
    stacks[destination].unshift(stacks[source].shift)
  end
end

def rearrange_crates
  initial_stacks.clone.map { |k, v| [k, v.clone] }.to_h.tap do |stacks|
    instructions.each { |instruction| follow_instruction(stacks, *instruction) }
  end
end

def heads_of_stacks(stacks)
  stacks.values.map(&:first).join
end

# part 1
puts heads_of_stacks(rearrange_crates)

# redefine stacking algorithm
def follow_instruction(stacks, count, source, destination)
  stacks[destination].unshift(*stacks[source].shift(count))
end

# part 2
puts heads_of_stacks(rearrange_crates)