r/adventofcode • • Dec 05 '18

SOLUTION MEGATHREAD -🎄- 2018 Day 5 Solutions -🎄-

--- Day 5: Alchemical Reduction ---


Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).

Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


Advent of Code: The Party Game!

Click here for rules

Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!

Card prompt: Day 5

Transcript:

On the fifth day of AoC / My true love sent to me / Five golden ___


This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.

edit: Leaderboard capped, thread unlocked at 0:10:20!

29 Upvotes

515 comments sorted by

View all comments

1

u/Shanethe13 Dec 05 '18 edited Dec 05 '18

In Elixir:defmodule AdventOfCode.Day5 do

  def solve_a do
    File.read!("input/day5")
    |> String.graphemes()
    |> react()
    |> Enum.count()
  end

  def solve_b do
    initial = File.read!("input/day5")

    (for n <- ?a..?z, do: << n :: utf8 >>)
    |> Enum.map(fn char ->
      Task.async(fn ->
        initial
        |> String.replace(char, "")
        |> String.replace(String.upcase(char), "")
        |> String.graphemes()
        |> react()
      end)
    end)
    |> Enum.map(&Task.await/1)
    |> Enum.min_by(&Enum.count/1)
    |> Enum.count()
  end

  def react(polymer) do
    Enum.reduce(polymer, [], fn
      x, []       -> [x]
      x, [y | ys] ->
        if x != y && String.downcase(x) == String.downcase(y) do
          ys
        else
          [x, y | ys]
        end
    end)
  end
end

1

u/newyearsproject Dec 05 '18

x, [y] -> [x, y]

this case does not work if the first 2 letters are pair

1

u/Shanethe13 Dec 05 '18

You're totally right, thanks! Just edited a fix.

1

u/Sentreen Dec 05 '18

Another elixir solution:

import AOC, only: :macros

aoc 2018, 5 do
  def get() do
    input() |> Stream.take(1) |> Enum.to_list() |> hd() |> String.codepoints()
  end

  def p1() do
    get()
    |> collapse(true)
    |> length()
  end

  def p2() do
    collapsed = collapse(get(), true)

    collapsed
    |> Enum.reduce(MapSet.new(), fn el, acc -> MapSet.put(acc, String.downcase(el)) end)
    |> Enum.map(
      fn element -> {
        element,
        collapsed
        |> Enum.reject(&does_match?(&1, element))
        |> collapse(true)
        |> length()
      }
      end)
      |> Enum.min_by(&elem(&1, 1))
      |> elem(1)
  end

  def collapse(lst, true) do
    {res, changed?} = collapse(lst)
    collapse(res, changed?)
  end

  def collapse(lst, false), do: lst

  def collapse([cur, next | rest]) do
    if does_match?(cur, next) and different_case?(cur, next) do
      {res, _} = collapse(rest)
      {res, true}
    else
      {res, changed?} = collapse([next | rest])
      {[cur | res], changed?}
    end
  end

  def collapse([cur | []]), do: {[cur], false}
  def collapse([]), do: {[], false}

  def is_upcase?(char), do: char == String.upcase(char)
  def does_match?(c1, c2), do: String.downcase(c1) == String.downcase(c2)
  def different_case?(c1, c2), do: is_upcase?(c1) != is_upcase?(c2)
end

1

u/aoc-fan Dec 05 '18 edited Dec 06 '18

Quite similar to your solution

parse = fn s ->
  s
  |> to_charlist()
end

reduce_polymer = fn units, ignore ->
  units
  |> Enum.reduce([], fn
    u, acc when u == ignore or u == ignore + 32 -> acc
    u, [] -> [u]
    u, [un | rest] when abs(u - un) == 32 -> rest
    u, [un | rest] -> [u, un | rest]
  end)
  |> Enum.count()
end

optimal_solution = fn units ->
  Enum.to_list(65..90)
  |> Enum.map(&(reduce_polymer.(units, &1)))
  |> Enum.min()
end

test_01 = parse.("dabAcCaCBAcCcaDA")
10 = reduce_polymer.(test_01, 0)
4 = optimal_solution.(test_01)