require 'set' def hash_code(string) initial_string = [*0..255] suffix = [17, 31, 73, 47, 23] # shifts = File.open('puzzle_10.txt').read.split(',').map(&:to_i) + suffix # shifts = [1, 2, 3] + suffix # shifts = suffix shifts = string.split('').map(&:ord) shifts = shifts + suffix skip_size = 0 offset = 0 shifts = shifts * 64 for shift in shifts do initial_string.rotate! offset if shift > 0 then rotated_bit = initial_string[0..shift - 1] kept_bit = initial_string[shift..initial_string.length-1] initial_string = rotated_bit.reverse + kept_bit end initial_string.rotate! -offset offset += shift + skip_size skip_size += 1 end blocks = initial_string.each_slice(16).to_a hash = blocks.map do |block| block.inject(0) { |x, y| x^y }.to_s(16).rjust(2, '0') end return hash.join('') end input = "jxqlasbh" # input = "flqrgnkx" total = 0 map = [] 128.times do |time| hash_input = input + '-' + time.to_s computed_hash = hash_code(hash_input) binary = computed_hash.split('').map do |it| it.to_i 16 end.map do |it| (it.to_s 2).rjust(4, '0') end.join('') total += binary.count '1' map.push(binary.split('')) end puts total puts "#{map[0][0..3]}" puts "#{map[1][0..3]}" puts "#{map[2][0..3]}" puts "#{map[3][0..3]}" enabled = [] 128.times do |x| 128.times do |y| if map[x][y] != '1' then next end enabled.push [[x, y]] end end def is_neighbor(a, b) a_neighbors = [[a[0]+1,a[1]],[a[0]-1, a[1]], [a[0],a[1]+1], [a[0],a[1]-1]] return a_neighbors.include? b end final_groups = [] modified = true while modified do modified = false i = 0 while i < enabled.length do current = enabled[i] j = i + 1 while j < enabled.length do other = enabled[j] if (current.product other).any? { |a| is_neighbor(a[0], a[1]) } then current.concat other enabled.delete_at(j) modified = true else j += 1 end end i += 1 end end puts enabled.length