Advent of Code 2016, Day 5: How About a Nice Game of Chess?

#ruby #advent of code 2016

Part A

On Day 5 we have unintentional introduction to bitcoin mining, because we need to generate hashes with a number of leading zeros.

Nothing difficult here. We start with some input string and an integer 0. We concatenate both values and generate MD5 hash. We increase our integer by 1 and repeat the process until we get a hash with 5 leading zeros. Here is the code:

require "digest"

input = File.read("5.txt").strip

index = 0
password = ""

while true
  digest = Digest::MD5.hexdigest("#{input}#{index}")

  if digest.start_with?("00000")
    password += digest[5]
    puts "Current password: #{password}"
  end

  if password.size == 8
    break
  end

  index += 1
end

puts "Final password: #{password}"

When we get a hash with 5 leading zeros we need to take the sixth character and this will be part of our password. We need 8 characters in total to get our password.

Part B

Second part is similar, but this time seventh character will be part of our password and sixth character will indicate the position of that character in the password. Password is still 8 characters long, so if we get a hash that sixth character is not in 0-7 range we should skip it. Here is the solution:

require "digest"

input = File.read("5.txt").strip

index = 0
password = Array.new(8, nil)

while true
  digest = Digest::MD5.hexdigest("#{input}#{index}")

  if digest.start_with?("00000")
    position = digest[5] =~ /[0-7]/ ? digest[5].to_i : nil

    if position && !password[position]
      password[position] = digest[6]
      puts "Current password: #{password.join}, digest = #{digest}, index = #{index}"
    end
  end

  if password.none? { |item| item.nil? }
    break
  end

  index += 1
end

puts "Final password: #{password.join}"