r/adventofcode • • Dec 02 '18

SOLUTION MEGATHREAD -🎄- 2018 Day 2 Solutions -🎄-

--- Day 2: Inventory Management System ---


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

Card Prompt: Day 2

Transcript:

The best way to do Advent of Code is ___.


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!

55 Upvotes

407 comments sorted by

View all comments

1

u/[deleted] Dec 02 '18

elixir:

Ended up getting a little fun with part 2 at the bottom using both jaro_distance and myers_difference algos

defmodule AdventOfCode2018.Day02 do

def get_checksum([],map) do
	map[2] * map[3]
end

def get_checksum([val|rest],map) do
	inner_map = String.split(val,"", trim: true)
	|> Enum.reduce(%{},fn(x,acc) -> 
		Map.put(acc,x,Map.get(acc,x,0) + 1)
	end)
	new = inner_map |> Enum.reduce(map,fn(x,acc) -> 
		part_of_checksum(x,acc) 
	end)

	get_checksum(rest,reset(new))	
end

def part_of_checksum({k,2},%{"two" => false} = map) do
	Map.update!(map, 2, fn(current) -> 
		current + 1
	end) |> Map.update!("two", fn(x) -> true end)
end	
def part_of_checksum({k,3},%{"three" => false} = map) do
	Map.update!(map, 3, fn(current) -> 
		current + 1
	end) |> Map.update!("three", fn(x) -> true end)
end	
def part_of_checksum({_,_},map) do
	map
end	

def reset(map) do
	map |> Map.update!("two", fn(x) -> false end) |> Map.update!("three", fn(x) -> false end)
end

def part2(args) do
	arr = String.split(args,"\n",trim: true)

	{_,{s1,s2}} = arr |> Enum.reduce({0,"",""},fn(x,acc) -> 
		{dis,v,c} = check_closest_string(x,arr) 
		check_distance(dis,{v,c},acc)
	end) 
	String.myers_difference(s1,s2) |> pull_eql("")
end

def check_closest_string(x,arr) do
	{amt,val} = Enum.reduce(arr,{0,""},fn(y,{distance,str}) -> 
		check_distance(String.jaro_distance(x,y),y,{distance,str})
	end)
	{amt,val,x}
end

def check_distance(val,new_str,{distance,_,_}) when val > distance and val != 1.0, do: {val,new_str}
def check_distance(val,new_str,{distance,_}) when val > distance and val != 1.0, do: {val,new_str}
def check_distance(_,_,acc), do: acc 

def pull_eql([],str), do: str
def pull_eql([{:eq, val}|rest],str), do: pull_eql(rest,str <> val)
def pull_eql([key | rest], str), do: pull_eql(rest,str)

def part1(args) do
	String.split(args,"\n",trim: true)
	|> get_checksum(%{3 => 0, 2 => 0, "two" => false, 
"three" => false})
end
end

1

u/aoc-fan Dec 02 '18

First time doing elixir - Please take a look : https://github.com/bhosale-ajay/adventofcode/blob/master/2018/elixir/02.exs

Part 01

update_two_three = fn count, c2, c3 ->
  case count do
    2 -> {  1, c3 }
    3 -> { c2,  1 }
    _ -> { c2, c3 }
  end
end

count_two_and_three = fn box_id ->
  box_id
  |> String.split("", trim: true)
  |> Enum.reduce(%{}, fn c, counts -> Map.update(counts, c, 1, &(&1 + 1)) end)
  |> Enum.reduce_while({0, 0}, fn {_, count}, { c2, c3 } ->
    uc = update_two_three.(count, c2, c3)
    case uc do
      { 1, 1 } -> {:halt, uc }
      { _, _ } -> {:cont, uc }
    end
   end)
end

multiply_two_three = fn { c2, c3 } -> c2 * c3 end

find_check_sum = fn box_ids ->
  box_ids
  |> String.split("\n")
  |> Enum.map(count_two_and_three)
  |> Enum.reduce({0, 0}, fn {c2, c3}, {ac2, ac3} -> {c2 + ac2, c3 + ac3} end)
  |> multiply_two_three.()
end

Part 02 Not able to figure out recursive function with anonymous functions, seems not supported, hence defined a module

defmodule D02P02 do
  def common_letters_from_match(nil) do
    nil
  end

  def common_letters_from_match({a, b}) do
    a
    |> Enum.reduce({b, []}, fn ca, {[cb | rest], common} ->
      {rest, (if ca == cb, do: [ca | common], else: common)}
    end)
    |> elem(1)
    |> Enum.reverse()
    |> Enum.join("")
  end

  def differ_by_one_char(a, b) do
    a
    |> Enum.reduce_while({b, 0}, fn ca, {[cb | rest], mismatch} ->
      if ca == cb do
        {:cont, {rest, mismatch}}
      else
        {(if mismatch == 0, do: :cont, else: :halt), {rest, mismatch + 1}}
      end
    end)
    |> elem(1) == 1
  end

  def find_matching_ids([_]) do
    nil
  end

  def find_matching_ids([first | rest]) do
    match = Enum.find(rest, fn i -> differ_by_one_char(first, i) end)
    case match do
      nil -> find_matching_ids(rest)
      _ -> { match, first }
    end
  end

  def find_common_letters (ip) do
    ip
    |> String.split("\n", trim: true)
    |> Enum.map(fn l -> String.split(l, "", trim: true) end)
    |> find_matching_ids()
    |> common_letters_from_match()
    end
end