1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
require "set"

input = ARGF.read.split("\n").map {|x| x.split(/\s+\|\s+/).map {|x| x.split(/\s+/) } }
# output = input.map(&:last)
# p output.flatten.count {|x| [2, 4, 3, 7].include?(x.length) }

MAP = {
  %w[ a b c   e f g ] => 0,
  %w[     c     f   ] => 1,
  %w[ a   c d e   g ] => 2,
  %w[ a   c d   f g ] => 3,
  %w[   b c d   f   ] => 4,
  %w[ a b   d   f g ] => 5,
  %w[ a b   d e f g ] => 6,
  %w[ a   c     f   ] => 7,
  %w[ a b c d e f g ] => 8,
  %w[ a b c d   f g ] => 9,
#     8 6 8 7 4 9 7
}.transform_keys(&:to_set)

# # My original solution to part two
# def solve(signals, output)
#   all = signals + output
#   one = all.find {|x| x.length == 2 }
#   four = all.find {|x| x.length == 4 }
#   seven = all.find {|x| x.length == 3 }
#   eight = all.find {|x| x.length == 7 }

#   b = (?a..?g).find {|x| signals.count {|s| s.include?(x) } == 6 }
#   e = (?a..?g).find {|x| signals.count {|s| s.include?(x) } == 4 }
#   f = (?a..?g).find {|x| signals.count {|s| s.include?(x) } == 9 }

#   a = (seven.chars - one.chars)[0]
#   c = (one.chars - [f])[0]
#   d = (four.chars - [b, c, f])[0]
#   g = (eight.chars - [a, b, c, d, e, f])[0]

#   map = { a: a, b: b, c: c, d: d, e: e, f: f, g: g }.invert

#   output.map {|x| MAP.fetch(x.chars.map {|c| map.fetch(c).to_s }.to_set) }.join.to_i
# end

# Here it is with a solver, but much, much slower!
def solve(signals, output)
  data = "Patterns = [ #{signals.map { "{ #{_1.upcase.chars.join(" ,")} }" }.join(", ")} ]"
  solution = `minizinc --cmdline-data "#{data}" day_08.mzn`.scan(/[A-G]/)
  map = (?a..?g).zip(solution.map(&:downcase)).to_h
  output.map {|x| MAP.fetch(x.chars.map {|c| map.fetch(c).to_s }.to_set) }.join.to_i
end

p input.sum {|x| solve(*x) }