Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Day 8

livebook/day-08.livemd

Day 8

Setup

be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc fgae cfgab fg bagce
Mix.install(
  [
    {:kino, "~> 0.4.1"}
  ],
  consolidate_protocols: false
)

input = Kino.Input.textarea("Please paste your input:")
defmodule Clean do
  def split_and_sort(string_list) do
    string_list
    |> String.split(" ", trim: true)
    |> Enum.map(fn string ->
      string
      |> String.to_charlist()
      |> Enum.sort()
    end)
  end
end

lines =
  input
  |> Kino.Input.read()
  |> String.split(["\n", "|"], trim: true)
  |> Enum.chunk_every(2)
  |> Enum.map(fn [signal, output] ->
    {Clean.split_and_sort(signal), Clean.split_and_sort(output)}
  end)

Part 1

lines
|> Enum.map(fn {_signal, output} ->
  Enum.map(output, &Enum.count/1)
  |> Enum.count(fn length -> length in [2, 3, 4, 7] end)
end)
|> Enum.sum()

Part 2 🙈

be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb |
fdgacbe cefdb cefbgd gcbe
  {['be', 'abcdefg', 'bcdefg', 'acdefg', 'bceg', 'cdefg', 'abdefg', 'bcdef', 'abcdf', 'bde'],
   ['abcdefg'8, 'bcdef'3, 'bcdefg'9, 'bceg']4}

 be
 edb
 abcdefg
 cgeb
 cdefg
 abcdf
 bcdef
 abdefg
 bcdefg
 acdefg

known   dcfgeb
unknown a

          1234567
Length  | Signal | Integer | Pattern
2           b  e   1          3  6   <>
3         d b  e   7 -----  1 3  6   <>
4          gbc e   4         234 6   <>
7         dgbcaef  8 -----  1234567  <> 
5         d bca f  2        1 345 7
5         d bc ef  3 -----  1 34 67
5         dgbc ef  5        12 4 67
6         dgb aef  0 -----  123 567
6         dgbcaef  6        12 4567
6         dgbc ef  9 -----  1234 67  
- pos 4 (search [4,7,5]   occurs in all of them)
- pos 1 (search [2,3,4,7] occurs in 3 and 7 only)
- pos 7 (search [7,5,6]   occurs in all of them)
- pos 6 (search [2,3,4,6] occurs everywhere AND in TWO [5])
- pos 3 (search [3]       only one unknown remaining)
- pos 5 (search [7,6] occurs everywhere and just in ONE [5])
- pos 2 (last unknown)

[‘abefg’, ‘ac’, ‘abcefg’, ‘abcdefg’, ‘acdefg’, ‘bcdfg’, ‘abce’, ‘abdefg’, ‘abcfg’, ‘acf’]

ac acf abce abcdefg

abefg bcdfg abcfg

abcefg acdefg abdefg

acdefg

      1_34567

Length | Signal | Integer | Pattern 2 c a 1 3 6 <> 3 f c a 7 —– 1 3 6 <> 4 dcb ag 4 234 6 <> 7 fdcbeag 8 —– 1234567 <> 5 f cbe g 2 1 345 7 5 f cb ag 3 —– 1 34 67 5 fd b ag 5 12 4 67 6 fdc eag 0 —– 123 567 6 fd beag 6 12 4567 6 fdcb ag 9 —– 1234 67

  {['abcdefg', 'bcdef', 'acdfg', 'abcdf', 'abd', 'abcdef', 'bcdefg', 'abef', 'abcdeg', 'ab'],
   ['bcdef'5, 'abcdf'3, 'bcdef'5, 'abcdf'3]}

ab
abd  
abef
abcdefg

bcdef
acdfg
abcdf

abcdef
bcdefg
abcdeg


dfceba
g
          1  4  7
Length  | Signal | Integer | Pattern
2           a  b    1          3  6   <>
3         d a  b    7 -----  1 3  6   <>
4          eaf b    4         234 6   <>
7         deafgbc   8 -----  1234567  <> 
5         d afg c   2        1 345 7
5         d af bc   3 -----  1 34 67
5         de f bc   5        12 4 67
6         dea gbc   0 -----  123 567
6         de fgbc   6        12 4567
6         deaf bc   9 -----  1234 67  


Actual
  0:(6)   1:(2)   2:(5)   3:(5)   4:(4)
 1111    ....    1111    1111    ....
2    3  .    3  .    3  .    3  2    3
2    3  .    3  .    3  .    3  2    3
 ....    ....    4444    4444    4444
5    6  .    6  5    .  .    6  .    6
5    6  .    6  5    .  .    6  .    6
 7777    ....    7777    7777    ....

  5:(5)   6:(6)   7:(3)   8:(7)   9:(6)
 1111    1111    1111    1111    1111
2    .  2    .  .    3  2    3  2    3
2    .  2    .  .    3  2    3  2    3
 4444    4444    ....    4444    4444
.    6  5    6  .    6  5    6  .    6
.    6  5    6  .    6  5    6  .    6
 7777    7777    ....    7777    7777


Template
  0:      1:      2:      3:      4:
 1111    ....    1111    1111    ....
2    3  .    3  .    3  .    3  2    3
2    3  .    3  .    3  .    3  2    3
 ....    ....    4444    4444    4444
5    6  .    6  5    .  .    6  .    6
5    6  .    6  5    .  .    6  .    6
 7777    ....    7777    7777    ....

  5:      6:      7:      8:      9:
 1111    1111    1111    1111    1111
2    .  2    .  .    3  2    3  2    3
2    .  2    .  .    3  2    3  2    3
 4444    4444    ....    4444    4444
.    6  5    6  .    6  5    6  .    6
.    6  5    6  .    6  5    6  .    6
 7777    7777    ....    7777    7777
# - pos 4 (search [4,7,5]   occurs in all of them)
# - pos 1 (search [2,3,4,7] occurs in 3 and 7 only)
# - pos 7 (search [7,5,6]   occurs in all of them)
# - pos 6 (search [2,3,4,6] occurs everywhere AND in TWO [5])
# - pos 3 (search [3]       only one unknown remaining)
# - pos 5 (search [7,6] occurs everywhere and just in ONE [5])
# - pos 2 (last unknown)

defmodule Part2 do
  def unique_chars_in_signals(signals) do
    x =
      Enum.reduce(signals, [], fn chars, uniq_chars -> '#{chars}#{uniq_chars}' |> Enum.uniq() end)

    # IO.puts(Enum.to_list(x))
    x
  end

  def pos4({_, _, _unknown_chars = [], _}) do
    raise "UHO.. pos4 did not find anything"
  end

  def pos4({signals, {p1, p2, p3, p4, p5, p6, p7}, [char | unknown_chars], remaining_chars}) do
    if Part2.char_present_in_all_lists(char, signals[5] ++ signals[4] ++ signals[7]) do
      remaining_chars =
        remaining_chars
        |> List.delete_at(Enum.find_index(remaining_chars, &amp;(char == &amp;1)))

      {signals, {p1, p2, p3, char, p5, p6, p7}, remaining_chars, remaining_chars}
    else
      Part2.pos4({signals, {p1, p2, p3, p4, p5, p6, p7}, unknown_chars, remaining_chars})
    end
  end

  def pos1({_, _, _unknown_chars = [], _}) do
    raise "UHO.. pos1 did not find anything"
  end

  def pos1({signals, {p1, p2, p3, p4, p5, p6, p7}, [char | unknown_chars], remaining_chars}) do
    if Part2.char_present_in_all_lists(char, signals[3] ++ signals[7]) and
         Part2.char_not_present(char, signals[2] ++ signals[4]) do
      remaining_chars =
        remaining_chars
        |> List.delete_at(Enum.find_index(remaining_chars, &amp;(char == &amp;1)))

      {signals, {char, p2, p3, p4, p5, p6, p7}, remaining_chars, remaining_chars}
    else
      Part2.pos1({signals, {p1, p2, p3, p4, p5, p6, p7}, unknown_chars, remaining_chars})
    end
  end

  def pos7({_, _, _unknown_chars = [], _}) do
    raise "UHO.. pos7 did not find anything"
  end

  def pos7({signals, {p1, p2, p3, p4, p5, p6, p7}, [char | unknown_chars], remaining_chars}) do
    if Part2.char_present_in_all_lists(char, signals[5] ++ signals[6] ++ signals[7]) do
      remaining_chars =
        remaining_chars
        |> List.delete_at(Enum.find_index(remaining_chars, &amp;(char == &amp;1)))

      {signals, {p1, p2, p3, p4, p5, p6, char}, remaining_chars, remaining_chars}
    else
      Part2.pos7({signals, {p1, p2, p3, p4, p5, p6, p7}, unknown_chars, remaining_chars})
    end
  end

  def pos2({_, _, _unknown_chars = [], _}) do
    raise "UHO.. pos2 did not find anything"
  end

  def pos2({signals, {p1, p2, p3, p4, p5, p6, p7}, [char | unknown_chars], remaining_chars}) do
    if Part2.char_present_in_all_lists(char, signals[4] ++ signals[7]) and
         Part2.char_present_in_one_list_only(char, signals[5]) do
      remaining_chars =
        remaining_chars
        |> List.delete_at(Enum.find_index(remaining_chars, &amp;(char == &amp;1)))

      {signals, {p1, char, p3, p4, p5, p6, p7}, remaining_chars, remaining_chars}
    else
      Part2.pos2({signals, {p1, p2, p3, p4, p5, p6, p7}, unknown_chars, remaining_chars})
    end
  end

  def pos6({_, _, _unknown_chars = [], _}) do
    raise "UHO.. pos6 did not find anything"
  end

  def pos6({signals, {p1, p2, p3, p4, p5, p6, p7}, [char | unknown_chars], remaining_chars}) do
    # IO.puts(
    #   "pos6 #{inspect(signals[2] ++ signals[3] ++ signals[4] ++ signals[5] ++ signals[6] ++ signals[7])} #{List.to_string([char])} #{unknown_chars}"
    # )
    if Part2.char_present_in_all_lists(
         char,
         signals[2] ++ signals[3] ++ signals[4] ++ signals[6]
       ) and
         Part2.char_present_in_two_lists(char, signals[5]) do
      remaining_chars =
        remaining_chars
        |> List.delete_at(Enum.find_index(remaining_chars, &amp;(char == &amp;1)))

      {signals, {p1, p2, p3, p4, p5, char, p7}, remaining_chars, remaining_chars}
    else
      Part2.pos6({signals, {p1, p2, p3, p4, p5, p6, p7}, unknown_chars, remaining_chars})
    end
  end

  def pos3({_, _, _unknown_chars = [], _}) do
    raise "UHO.. pos3 did not find anything"
  end

  def pos3({signals, {p1, p2, p3, p4, p5, p6, p7}, [char | unknown_chars], remaining_chars}) do
    if char in List.first(signals[3]) do
      remaining_chars =
        remaining_chars
        |> List.delete_at(Enum.find_index(remaining_chars, &amp;(char == &amp;1)))

      {signals, {p1, p2, char, p4, p5, p6, p7}, remaining_chars, remaining_chars}
    else
      Part2.pos3({signals, {p1, p2, p3, p4, p5, p6, p7}, unknown_chars, remaining_chars})
    end
  end

  def pos5({_, _, _unknown_chars = [], _}) do
    raise "UHO.. pos5 did not find anything"
  end

  def pos5({signals, {p1, p2, p3, p4, p5, p6, p7}, [char | unknown_chars], remaining_chars}) do
    if Part2.char_present_in_all_lists(
         char,
         signals[7] ++ signals[6]
       ) and
         Part2.char_present_in_one_list_only(char, signals[5]) do
      remaining_chars =
        remaining_chars
        |> List.delete_at(Enum.find_index(remaining_chars, &amp;(char == &amp;1)))

      {signals, {p1, p2, p3, p4, char, p6, p7}, remaining_chars, remaining_chars}
    else
      Part2.pos5({signals, {p1, p2, p3, p4, p5, p6, p7}, unknown_chars, remaining_chars})
    end
  end

  def char_present_in_one_list_only(char, lists) do
    Enum.count(lists, fn list -> char in list end) == 1
  end

  def char_present_in_two_lists(char, lists) do
    Enum.count(lists, fn list -> char in list end) == 2
  end

  def char_present_in_all_lists_except_one(char, lists) do
    IO.puts("char_present_in_all_lists_except_one")
    IO.puts(List.to_string([char]))
    IO.puts(inspect(lists))
    Enum.count(lists, fn list -> [char] in list end) == 2
  end

  def char_present_in_all_lists(char, lists) do
    Enum.all?(lists, &amp;(char in &amp;1))
  end

  def char_not_present(char, lists) do
    Enum.all?(lists, &amp;(char not in &amp;1))
  end

  def wire_connections({p1, p2, p3, p4, p5, p6, p7}) do
    IO.puts({p1, p2, p3, p4, p5, p6, p7} |> Tuple.to_list())

    %{
      Enum.sort([p1, p2, p3, p5, p6, p7]) => 0,
      Enum.sort([p3, p6]) => 1,
      Enum.sort([p1, p3, p4, p5, p7]) => 2,
      Enum.sort([p1, p3, p4, p6, p7]) => 3,
      Enum.sort([p2, p3, p4, p6]) => 4,
      Enum.sort([p1, p2, p4, p6, p7]) => 5,
      Enum.sort([p1, p2, p4, p5, p6, p7]) => 6,
      Enum.sort([p1, p3, p6]) => 7,
      Enum.sort([p1, p2, p3, p4, p5, p6, p7]) => 8,
      Enum.sort([p1, p2, p3, p4, p6, p7]) => 9
    }
  end

  def get_config_from_signals(signals, config, unknown_chars) do
    signals
    |> Enum.group_by(&amp;Enum.count/1)
    |> (fn signals -> Part2.pos4({signals, config, unknown_chars, unknown_chars}) end).()
    |> Part2.pos1()
    |> Part2.pos7()
    |> Part2.pos6()
    |> Part2.pos3()
    |> Part2.pos5()
    |> (fn {signals, {p1, _, p3, p4, p5, p6, p7}, unknown_chars, _remaining_chars} ->
          IO.puts(inspect(signals))
          {p1, unknown_chars |> List.first(), p3, p4, p5, p6, p7}
        end).()
    |> Part2.wire_connections()
  end
end

# [{signals, output} | _] = lines

# Part2.unique_chars_in_signals([
#   'be',
#   'abcdefg',
#   'bcdefg',
#   'acdefg',
#   'bceg',
#   'cdefg',
#   'abdefg',
#   'bcdef',
#   'abcdf',
#   'bde'
# ])

# config =
#   Part2.get_config_from_signals(
#     signals,
#     {1, 2, 3, 4, 5, 6, 7, 8, 9},
#     Part2.unique_chars_in_signals(signals)
#   )
[lines | _] = lines

configs =
  [lines]
  |> Enum.map(fn {signals, outputs} ->
    config =
      Part2.get_config_from_signals(
        signals,
        {1, 2, 3, 4, 5, 6, 7},
        Part2.unique_chars_in_signals(signals)
      )

    IO.puts("Config #{inspect(config)}")

    Enum.map(outputs, fn output ->
      IO.puts(inspect(output))
      Map.get(config, output)
    end)
  end)

{[‘be’, ‘abcdefg’, ‘bcdefg’, ‘acdefg’, ‘bceg’, ‘cdefg’, ‘abdefg’, ‘bcdef’, ‘abcdf’, ‘bde’], [‘abcdefg’, ‘bcdef’, ‘bcdefg’, ‘bceg’]},

{d, a, b, c, g, e, f’ [p1, p2, p3,}

Template 0: 1: 2: 3: 4: 1111 …. 1111 1111 …. 2 3 . 3 . 3 . 3 2 3 2 3 . 3 . 3 . 3 2 3 …. …. 4444 4444 4444 5 6 . 6 5 . . 6 . 6 5 6 . 6 5 . . 6 . 6 7777 …. 7777 7777 ….

5: 6: 7: 8: 9: 1111 1111 1111 1111 1111 2 . 2 . . 3 2 3 2 3 2 . 2 . . 3 2 3 2 3 4444 4444 …. 4444 4444 . 6 5 6 . 6 5 6 . 6 . 6 5 6 . 6 5 6 . 6 7777 7777 …. 7777 7777

Part 2 José

parsed =
  input
  |> Kino.Input.read()
  |> String.split([" |\n", " | ", "\n"], trim: true)
  |> Enum.chunk_every(2)
  |> Enum.map(fn [input, output] ->
    {input |> String.split() |> Enum.group_by(&amp;byte_size/1, &amp;String.to_charlist/1),
     output |> String.split() |> Enum.map(&amp;String.to_charlist/1)}
  end)
supersets = fn numbers, pivot ->
  Enum.filter(numbers, &amp;match?([], pivot -- &amp;1))
end

almost_supersets = fn numbers, pivot ->
  Enum.filter(numbers, &amp;match?([_], pivot -- &amp;1))
end

parsed
|> Enum.map(fn {input, output} ->
  %{
    2 => [one],
    3 => [seven],
    4 => [four],
    5 => two_three_five,
    6 => zero_six_nine,
    7 => [eight]
  } = input

  [nine] = supersets.(zero_six_nine, four)
  [six] = almost_supersets.(zero_six_nine, seven)
  [zero] = zero_six_nine -- [six, nine]

  [three] = supersets.(two_three_five, seven)
  [five] = almost_supersets.(two_three_five, six)
  [two] = two_three_five -- [three, five]

  numbers = %{
    Enum.sort(zero) => 0,
    Enum.sort(one) => 1,
    Enum.sort(two) => 2,
    Enum.sort(three) => 3,
    Enum.sort(four) => 4,
    Enum.sort(five) => 5,
    Enum.sort(six) => 6,
    Enum.sort(seven) => 7,
    Enum.sort(eight) => 8,
    Enum.sort(nine) => 9
  }

  [d1, d2, d3, d4] = output

  Integer.undigits([
    numbers[Enum.sort(d1)],
    numbers[Enum.sort(d2)],
    numbers[Enum.sort(d3)],
    numbers[Enum.sort(d4)]
  ])
end)
|> Enum.sum()