cave = Hash.new {|h,k| h[k] = [] }
ARGF.read.scan(/(\w+)-(\w+)/).each do
  cave[_1] << _2
  cave[_2] << _1
end

paths = [ %w[start] ]

loop do
  closed, open = paths.partition { _1.last == "end" }
  break if open.empty?

  paths = closed + open.flat_map {|path|
    cave.fetch(path.last)
      # .reject { _1 =~ /^[a-z]+$/ && path.include?(_1) }
      .reject { _1 == "start" }
      .reject {|cave|
        smalls = path.tally.select { _1 =~ /^[a-z]+$/ }
        smalls.fetch(cave, 0) > (smalls.any? { _2 > 1 } ? 0 : 1)
      }
      .map { path + [_1] }
  }
end

p paths.count