<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="310632" data-post-id="310632">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="midouest" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/midouest/120/25170_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  midouest
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Love all the pattern matching solutions in this thread! I did not do that <img src="https://forum.elixirforum.com/images/emoji/apple/stuck_out_tongue.png?v=15" title=":stuck_out_tongue:" class="emoji" alt=":stuck_out_tongue:" loading="lazy" width="20" height="20"> I tried writing out all the different joker cases for each type of hand and ended up hard-coding them since there weren’t that many.</p>
<p><a href="https://github.com/midouest/advent-of-code-2023/blob/main/notebooks/day07.livemd" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/midouest/advent-of-code-2023/blob/main/notebooks/day07.livemd</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="310632" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2023-day-7/60224/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-310632" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="310632"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="310653" data-post-id="310653">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="trnasistor" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  trnasistor
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>My beginner’s solution, Day 7 part 1</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day07 do

  def part1(input) do
    parse(input)
    |&gt; Enum.sort_by(&amp;(&amp;1.hand), &amp;compare/2)
    |&gt; Enum.map(&amp;(&amp;1.bid))
    |&gt; Enum.with_index(1)
    |&gt; Enum.map(fn {bid, rank} -&gt; bid * rank end)
    |&gt; Enum.sum
  end

  def compare(hand1, hand2) do
    l1 = [hand_type(hand1) | hand1]
    l2 = [hand_type(hand2) | hand2]
    l1 &lt;= l2
  end

  def hand_type(hand) do
    hand
    |&gt; Enum.frequencies 
    |&gt; Map.values 
    |&gt; Enum.sort(:desc)
    |&gt; case do
        [5] -&gt; 6 # Five of a kind
        [4, 1] -&gt; 5 # Four of a kind
        [3, 2] -&gt; 4 # Full house
        [3, 1, 1] -&gt; 3 # Three of a kind
        [2, 2, 1] -&gt; 2 # Two pair
        [2, 1, 1, 1] -&gt; 1 # One Pair
        [1, 1, 1, 1, 1] -&gt; 0 # High card
       end
  end

  def parse(raw_list) do
    for raw_line &lt;- String.split(raw_list, "\n") do
      [raw_hand, raw_bid] = String.split(raw_line)
      bid = String.to_integer(raw_bid)
      hand = raw_hand
        |&gt; String.graphemes
        |&gt; Enum.map(fn raw_card -&gt; 
              case raw_card do
                "A" -&gt; 14
                "K" -&gt; 13
                "Q" -&gt; 12
                "J" -&gt; 11
                "T" -&gt; 10
                 x  -&gt; String.to_integer(x)
              end     
           end)
        
      %{hand: hand, bid: bid}
    end
  end
  
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="310653" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2023-day-7/60224/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-310653" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="310653"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="310698" data-post-id="310698">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="APB9785" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/APB9785/120/24101_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  APB9785
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of ECSx</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>My strategy for part 2 was to count the jokers in each hand, remove them from the hand, then count up the other cards.  The most frequent card would then get its quantity increased by the joker count:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">joker_count = Enum.count(hand, fn card -&gt; part_2? and card == "J" end)

freqs =
  hand
  |&gt; Enum.reject(fn card -&gt; part_2? and card == "J" end)
  |&gt; Enum.frequencies()
  |&gt; Enum.sort_by(fn {_k, v} -&gt; v end, :desc)
  |&gt; List.update_at(0, fn {card, count} -&gt; {card, count + joker_count} end)
</code></pre>
<p>Full solution <a href="https://github.com/APB9785/AoC-2023-elixir/blob/master/lib/advent_2023/day_07.ex" rel="noopener nofollow ugc">here on Github</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="310698" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2023-day-7/60224/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-310698" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="310698"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="310812" data-post-id="310812">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="stevensonmt" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/stevensonmt/120/20503_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  stevensonmt
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Nothing special about my solution to this one. Felt like it was pretty straight-forward. I’m still running couple days behind and unlikely to catch up due to my day job this weekend. I wanted to do some clever binary pattern matching on parsing the input but it just didn’t seem to warrant the effort. Had the same approach to part 2 as <a class="mention" href="/u/apb9785" rel="nofollow">@APB9785</a></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day7 do
  @moduledoc """
  Day7 AoC Solutions
  """

  alias AocToolbox.Input

  def input(:test),
    do: """
    32T3K 765
    T55J5 684
    KK677 28
    KTJJT 220
    QQQJA 483
    """

  def input(:real), do: Input.load(__DIR__ &lt;&gt; "/input.txt")

  def solve(1, mode) do
    Day7.Part1.solve(input(mode))
  end

  def solve(2, mode) do
    Day7.Part2.solve(input(mode))
  end

  def high_card(), do: 1
  def one_pair(), do: 2
  def two_pair(), do: 3
  def three_of_a_kind(), do: 4
  def full_house(), do: 5
  def four_of_a_kind(), do: 6
  def yahtzee(), do: 7

  defmodule Part1 do
    @face_card_map %{"T" =&gt; ":", "J" =&gt; ";", "Q" =&gt; "&lt;", "K" =&gt; "=", "A" =&gt; "&gt;"}
    def solve(input) do
      input
      |&gt; parse()
      |&gt; rank_hands()
      |&gt; calc_winnings()
    end

    def parse(input, face_card_map \\ @face_card_map) do
      input
      |&gt; replace_face_cards(face_card_map)
      |&gt; String.trim()
      |&gt; String.split("\n")
      |&gt; Enum.map(&amp;String.split/1)
      |&gt; Enum.map(fn [hand, bid] -&gt; [hand, String.to_integer(bid)] end)
    end

    defp replace_face_cards(input, face_card_map) do
      input
      |&gt; String.graphemes()
      |&gt; Enum.map(fn g -&gt;
        case Map.fetch(face_card_map, g) do
          {:ok, c} -&gt; c
          _ -&gt; g
        end
      end)
      |&gt; Enum.join()
    end

    defp rank_hands(hands) when is_list(hands) do
      hands
      |&gt; Enum.map(&amp;hand_value/1)
      |&gt; Enum.sort()
    end

    defp hand_value([hand, bid]) when is_binary(hand) do
      hand
      |&gt; String.graphemes()
      |&gt; Enum.group_by(&amp;Function.identity/1)
      |&gt; apply_value(hand, bid)
    end

    defp apply_value(groups, hand, bid) when is_map(groups) do
      sets = map_size(groups)

      cond do
        sets == 1 -&gt; {{7, hand}, bid}
        sets == 2 -&gt; {{four_of_a_kind_or_full_house(groups), hand}, bid}
        sets == 3 -&gt; {{three_of_a_kind_or_two_pair(groups), hand}, bid}
        sets == 4 -&gt; {{2, hand}, bid}
        sets == 5 -&gt; {{1, hand}, bid}
      end
    end

    defp four_of_a_kind_or_full_house(groups) do
      groups
      |&gt; Map.values()
      |&gt; Enum.map(&amp;length/1)
      |&gt; Enum.max()
      |&gt; maybe_full_house()
    end

    defp maybe_full_house(4), do: 6
    defp maybe_full_house(3), do: 5

    defp three_of_a_kind_or_two_pair(groups) do
      groups
      |&gt; Map.values()
      |&gt; Enum.map(&amp;length/1)
      |&gt; Enum.max()
      |&gt; maybe_two_pair()
    end

    defp maybe_two_pair(3), do: 4
    defp maybe_two_pair(2), do: 3

    defp calc_winnings(ranked_hands) do
      ranked_hands
      |&gt; Enum.with_index(1)
      |&gt; Enum.reduce(0, fn {{_, bid}, ndx}, acc -&gt; acc + bid * ndx end)
    end
  end

  defmodule Part2 do
    @face_card_map %{"T" =&gt; ":", "J" =&gt; "0", "Q" =&gt; "&lt;", "K" =&gt; "=", "A" =&gt; "&gt;"}
    def solve(input) do
      input
      |&gt; parse()
      |&gt; rank_hands()
      |&gt; calc_winnings()
    end

    defp parse(input) do
      Part1.parse(input, @face_card_map)
    end

    defp rank_hands(hands) when is_list(hands) do
      hands
      |&gt; Enum.map(fn [hand, bid] -&gt; {{set_rank(hand), hand}, bid} end)
      |&gt; Enum.sort()
    end

    defp set_rank(hand) when is_binary(hand) do
      hand
      |&gt; String.graphemes()
      |&gt; Enum.group_by(&amp;Function.identity/1)
      |&gt; calc_rank()
    end

    defp calc_rank(groups) when is_map(groups) do
      sets = map_size(groups)
      jokers = Map.get(groups, "0", []) |&gt; length()

      cond do
        sets == 1 -&gt; Day7.yahtzee()
        sets == 2 and jokers &gt; 0 -&gt; Day7.yahtzee()
        sets == 2 -&gt; four_of_a_kind_or_full_house(groups)
        # two singles plus 3 jokers to make a 4 of a kind
        sets == 3 and jokers == 3 -&gt; Day7.four_of_a_kind()
        sets == 3 and jokers &gt; 0 -&gt; four_of_a_kind_or_full_house_bc_joker(groups, jokers)
        sets == 3 -&gt; three_of_a_kind_or_two_pair(groups)
        sets == 4 and jokers &gt; 0 -&gt; Day7.three_of_a_kind()
        sets == 4 -&gt; Day7.one_pair()
        sets == 5 and jokers == 1 -&gt; Day7.one_pair()
        sets == 5 -&gt; Day7.high_card()
        true -&gt; raise "cheater"
      end
    end

    defp four_of_a_kind_or_full_house(groups) do
      set_sizes = groups |&gt; Map.values() |&gt; Enum.map(&amp;length/1) |&gt; MapSet.new()

      if set_sizes == MapSet.new([3, 2]) do
        Day7.full_house()
      else
        Day7.four_of_a_kind()
      end
    end

    defp four_of_a_kind_or_full_house_bc_joker(groups, jokers) when map_size(groups) == 3 do
      set_sizes = groups |&gt; Map.drop(["0"]) |&gt; Map.values() |&gt; Enum.map(&amp;length/1) |&gt; MapSet.new()

      cond do
        MapSet.member?(set_sizes, 3) and jokers == 1 -&gt;
          # if you have 3 of a kind and one joker you get 4 of a kind
          Day7.four_of_a_kind()

        jokers == 1 -&gt;
          # 3 sets, 1 joker, means two pairs of non-jokers, use joker to make full house
          Day7.full_house()

        jokers == 2 -&gt;
          # pair of jokers, 3 sets, means one pair of non-jokers, use jokers to make 4 of a kind
          Day7.four_of_a_kind()
          # this covers all conditions because only called for groups == 3
      end
    end

    defp three_of_a_kind_or_two_pair(groups) do
      set_sizes = groups |&gt; Map.values() |&gt; Enum.map(&amp;length/1) |&gt; MapSet.new()

      if MapSet.member?(set_sizes, 3) do
        Day7.three_of_a_kind()
      else
        Day7.two_pair()
      end
    end

    defp calc_winnings(ranked_hands) do
      ranked_hands
      |&gt; Enum.with_index(1)
      |&gt; Enum.reduce(0, fn {{_, bid}, ndx}, acc -&gt; acc + bid * ndx end)
    end
  end
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="310812" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2023-day-7/60224/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-310812" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="310812"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="312736" data-post-id="312736">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tiago.avila09" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tiago.avila09/120/33072_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tiago.avila09
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>For this one, the part I most liked about my code was the way to identify the hand type, where I counted each letter of a hand, then I got the counts and sorted them and the final step was a pattern matching to identify the hand type.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def get_hand_type(hand) do
    hand
    |&gt; String.graphemes()
    |&gt; Enum.reduce(%{}, fn char, acc -&gt; Map.update(acc, char, 1, &amp;(&amp;1 + 1)) end)
    |&gt; Map.values()
    |&gt; Enum.sort()
    |&gt; Enum.join()
    |&gt; do_get_hand_type()
  end

  defp do_get_hand_type("5"), do: :five_of_a_kind
  defp do_get_hand_type("14"), do: :four_of_a_kind
  defp do_get_hand_type("23"), do: :full_house
  defp do_get_hand_type("113"), do: :three_of_a_kind
  defp do_get_hand_type("122"), do: :two_pairs
  defp do_get_hand_type("1112"), do: :one_pair
  defp do_get_hand_type("11111"), do: :high_card
</code></pre>
<p>Full solution:<br>
<a href="https://github.com/tiagoavila/advent_of_code_2023/blob/main/lib/day_seven.ex" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/tiagoavila/advent_of_code_2023/blob/main/lib/day_seven.ex</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="312736" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/advent-of-code-2023-day-7/60224/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-312736" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="312736"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>