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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><a href="https://github.com/egze/aoc/blob/master/lib/aoc/y2020/d4.ex" rel="noopener nofollow ugc">GitHub</a></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Aoc.Y2020.D4 do
  use Aoc.Boilerplate,
    transform: fn raw -&gt;
      raw
      |&gt; String.split("\n\n", trim: true)
      |&gt; Enum.map(fn line -&gt;
        line
        |&gt; String.split()
        |&gt; Enum.map(fn field -&gt;
          [key, value] = String.split(field, ":")
          {key, value}
        end)
        |&gt; Enum.into(%{})
      end)
    end

  @required_fields ~w(byr iyr eyr hgt hcl ecl pid)

  def part1(input \\ processed()) do
    input
    |&gt; Enum.filter(&amp;simple_valid_passport?/1)
    |&gt; Enum.count()
  end

  def part2(input \\ processed()) do
    input
    |&gt; Enum.filter(&amp;(Enum.sort(@required_fields) == Enum.sort(Map.keys(&amp;1) -- ["cid"])))
    |&gt; Enum.filter(&amp;strict_valid_passport?/1)
    |&gt; Enum.count()
  end

  defp simple_valid_passport?(passport) do
    @required_fields
    |&gt; Enum.all?(&amp;Map.has_key?(passport, &amp;1))
  end

  @doc """
  validates passport

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "1980", "ecl" =&gt; "grn", "eyr" =&gt; "2030", "hcl" =&gt; "#623a2f", "hgt" =&gt; "74in", "iyr" =&gt; "2012", "pid" =&gt; "087499704"})
      true

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "1989", "cid" =&gt; "129", "ecl" =&gt; "blu", "eyr" =&gt; "2029", "hcl" =&gt; "#a97842", "hgt" =&gt; "165cm", "iyr" =&gt; "2014", "pid" =&gt; "896056539"})
      true

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "2001", "cid" =&gt; "88", "ecl" =&gt; "hzl", "eyr" =&gt; "2022", "hcl" =&gt; "#888785", "hgt" =&gt; "164cm", "iyr" =&gt; "2015", "pid" =&gt; "545766238"})
      true

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "1944", "ecl" =&gt; "blu", "eyr" =&gt; "2021", "hcl" =&gt; "#b6652a", "hgt" =&gt; "158cm", "iyr" =&gt; "2010", "pid" =&gt; "093154719"})
      true

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "1926", "cid" =&gt; "100", "ecl" =&gt; "amb", "eyr" =&gt; "1972", "hcl" =&gt; "#18171d", "hgt" =&gt; "170", "iyr" =&gt; "2018", "pid" =&gt; "186cm"})
      false

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "1946", "ecl" =&gt; "grn", "eyr" =&gt; "1967", "hcl" =&gt; "#602927", "hgt" =&gt; "170cm", "iyr" =&gt; "2019", "pid" =&gt; "012533040"})
      false

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "1992", "cid" =&gt; "277", "ecl" =&gt; "brn", "eyr" =&gt; "2020", "hcl" =&gt; "dab227", "hgt" =&gt; "182cm", "iyr" =&gt; "2012", "pid" =&gt; "021572410"})
      false

      iex&gt; Aoc.Y2020.D4.strict_valid_passport?(%{"byr" =&gt; "2007", "ecl" =&gt; "zzz", "eyr" =&gt; "2038", "hcl" =&gt; "74454a", "hgt" =&gt; "59cm", "iyr" =&gt; "2023", "pid" =&gt; "3556412378"})
      false
  """
  def strict_valid_passport?(passport) do
    passport
    |&gt; Enum.all?(&amp;valid_field?/1)
  end

  defp valid_field?({"byr", byr}) do
    case Integer.parse(byr) do
      {byr_int, ""} -&gt; byr_int in 1920..2002
      _ -&gt; false
    end
  end

  defp valid_field?({"iyr", iyr}) do
    case Integer.parse(iyr) do
      {iyr_int, ""} -&gt; iyr_int in 2010..2020
      _ -&gt; false
    end
  end

  defp valid_field?({"eyr", eyr}) do
    case Integer.parse(eyr) do
      {eyr_int, ""} -&gt; eyr_int in 2020..2030
      _ -&gt; false
    end
  end

  defp valid_field?({"hgt", hgt}) do
    case Integer.parse(hgt) do
      {hgt_int, "cm"} -&gt; hgt_int in 150..193
      {hgt_int, "in"} -&gt; hgt_int in 59..76
      _ -&gt; false
    end
  end

  defp valid_field?({"hcl", hcl}) do
    String.match?(hcl, ~r/^#[0-9a-f]{6}$/)
  end

  defp valid_field?({"ecl", ecl}) do
    ecl in ~w(amb blu brn gry grn hzl oth)
  end

  defp valid_field?({"pid", pid}) do
    String.match?(pid, ~r/^\d{9}$/)
  end

  defp valid_field?({"cid", _cid}), do: true
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="196397" data-batch-url="/posts/batch_likers">
                        0
                      </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-2020-day-4/35971/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-196397" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="196397"
                     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 #21"></div>
  </section>
</div>
    <div class="postbit" id="196427" data-post-id="196427">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="JEG2" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/JEG2/120/936_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  JEG2
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Designing Elixir Systems with OTP</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Chunking and regular expression?  Fun stuff!</p>
<p><a href="https://github.com/JEG2/advent_of_code_2020/blob/main/day_04/passports.exs" class="onebox" target="_blank" rel="noopener nofollow ugc">https://github.com/JEG2/advent_of_code_2020/blob/main/day_04/passports.exs</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="196427" 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-2020-day-4/35971/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-196427" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="196427"
                     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 #22"></div>
  </section>
</div>
    <div class="postbit" id="196433" data-post-id="196433">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>part 2 -  <strong>O(n)</strong></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Advent.Day4b do

  def start(file \\ "/tmp/input.txt"), do:
    File.stream!(file)
    |&gt; Stream.chunk_by(fn o -&gt; byte_size(o) == 1 end)
    |&gt; Stream.filter(&amp;(&amp;1 !== ["\n"]))
    |&gt; Stream.scan(0, fn o, _acc -&gt; verify_passports(o) == 7 &amp;&amp; 1 || 0 end)
    |&gt; Enum.sum()

  defp verify_passports(o) do
    Stream.scan(o, 0, fn item, _acc -&gt;
      item
      |&gt; :binary.split([&lt;&lt;32&gt;&gt;, &lt;&lt;10&gt;&gt;], [:global, :trim])
      |&gt; Enum.reduce(0, fn x, acc -&gt; acc + verify_passport_item(x) end)
     end)
    |&gt; Enum.sum()
  end

  def verify_passport_item(&lt;&lt;"byr:", data::binary&gt;&gt;), do: in_range(String.to_integer(data), 1920,2002)
  def verify_passport_item(&lt;&lt;"iyr:", data::binary&gt;&gt;), do: in_range(String.to_integer(data), 2010,2020)
  def verify_passport_item(&lt;&lt;"eyr:", data::binary&gt;&gt;), do: in_range(String.to_integer(data), 2020,2030)
  def verify_passport_item(&lt;&lt;"hgt:", data::24, "cm"&gt;&gt;), do: &lt;&lt;data::24&gt;&gt; |&gt; String.to_integer |&gt; in_range(150,193)
  def verify_passport_item(&lt;&lt;"hgt:", data::16, "in"&gt;&gt;), do: &lt;&lt;data::16&gt;&gt; |&gt; String.to_integer |&gt; in_range(59,76)
  def verify_passport_item(&lt;&lt;"hcl:#", data::48&gt;&gt;), do: &lt;&lt;data::48&gt;&gt; =~ ~r(^[a-z, 0-9]*$) &amp;&amp; 1 || 0
  def verify_passport_item(&lt;&lt;"ecl:", data::binary&gt;&gt;) when data in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"], do: 1
  def verify_passport_item(&lt;&lt;"pid:", data::72&gt;&gt;), do: &lt;&lt;data::72&gt;&gt; =~ ~r(^[0-9]*$) &amp;&amp; 1 || 0
  def verify_passport_item(_), do: 0

  defp in_range(v, min, max) when v &gt;= min and v &lt;= max, do: 1
  defp in_range(_v, _min, _max), do: 0

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="196433" data-batch-url="/posts/batch_likers">
                        0
                      </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-2020-day-4/35971/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-196433" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="196433"
                     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 #23"></div>
  </section>
</div>
    <div class="postbit" id="196445" data-post-id="196445">
  <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>I hate my solution but here it is. The first time through part 1 I only cared about matching field names of the correct length. Decided that was too brittle so added a regex that matched the actual field names.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Day4 do
  import NimbleParsec

  @input File.read!("lib/input.txt") |&gt; String.split("\n\n")

  defmodule ParsingHelper do
    byr =
      string("byr")
      |&gt; ignore(string(":"))
      |&gt; choice([
        string("1") |&gt; string("9") |&gt; ascii_char([?2..?9]) |&gt; integer(1),
        string("2") |&gt; string("0") |&gt; string("0") |&gt; ascii_char([?0..?2])
      ])

    # matches 5 entries

    iyr =
      string("iyr")
      |&gt; ignore(string(":"))
      |&gt; string("20")
      |&gt; choice([
        string("1") |&gt; ascii_char([?0..?9]),
        string("2") |&gt; string("0")
      ])

    # matches 4 entries

    eyr =
      string("eyr")
      |&gt; ignore(string(":"))
      |&gt; string("20")
      |&gt; choice([
        string("2") |&gt; ascii_char([?0..?9]),
        string("3") |&gt; string("0")
      ])

    # matches 4 entries

    hgt =
      string("hgt")
      |&gt; ignore(string(":"))
      |&gt; choice([integer(3) |&gt; string("cm"), integer(2) |&gt; string("in")])

    # matches 3 entries

    hcl =
      string("hcl")
      |&gt; ignore(string(":"))
      |&gt; string("#")
      |&gt; ascii_string([?0..?9, ?a..?f], 6)

    # matches 3 entries

    ecl =
      string("ecl")
      |&gt; ignore(string(":"))
      |&gt; choice([
        string("amb"),
        string("blu"),
        string("brn"),
        string("gry"),
        string("grn"),
        string("hzl"),
        string("oth")
      ])

    # matches 2 entries

    pid = string("pid") |&gt; ignore(string(":")) |&gt; integer(9)
    # matches 2 entries

    cid = string("cid") |&gt; ignore(string(":")) |&gt; choice([integer(3), integer(2)])
    # matches 2 entries

    fields =
      repeat(
        choice([
          byr,
          iyr,
          eyr,
          hgt,
          hcl,
          ecl,
          pid,
          cid
        ])
        |&gt; ignore(choice([string(" "), ascii_char([10..10]), empty()]))
      )

    defparsec(:fields, fields)
  end

  defp valid_fields?(fields, regex_match) do
    case length(fields) do
      8 -&gt; true
      7 -&gt; not Enum.member?(fields, regex_match)
      _ -&gt; false
    end
  end

  def valid_number_of_fields() do
    @input
    |&gt; Enum.map(&amp;Regex.scan(~r/[a-z]{3}:/, &amp;1))
    |&gt; Enum.filter(&amp;valid_fields?(&amp;1, ["cid:"]))
    |&gt; Enum.count()
  end

  def valid_number_of_fields_and_expected_names() do
    @input
    |&gt; Enum.map(&amp;Regex.scan(~r/(byr|iyr|eyr|hgt|hcl|ecl|pid|cid)(?=:)/, &amp;1))
    |&gt; Enum.filter(&amp;valid_fields?(&amp;1, ["cid", "cid"]))
    |&gt; Enum.count()
  end

  def valid_fields_and_values() do
    @input
    |&gt; Enum.map(&amp;Day4.ParsingHelper.fields(&amp;1))
    |&gt; Enum.filter(fn {a, _, _, _, _, _} -&gt; a == :ok end)
    |&gt; Enum.filter(fn {_, b, _, _, _, _} -&gt;
      length(b) == 25 or (length(b) == 23 and not Enum.member?(b, "cid"))
    end)
    |&gt; Enum.count()
  end
end

IO.inspect(Day4.valid_number_of_fields())
IO.inspect(Day4.valid_number_of_fields_and_expected_names())
IO.inspect(Day4.valid_fields_and_values())

</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="196445" data-batch-url="/posts/batch_likers">
                        0
                      </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-2020-day-4/35971/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-196445" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="196445"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="197981" data-post-id="197981">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Very slowly catching up!</p>
<p><a href="https://gitlab.com/NobbZ/aoc_ex/-/blob/c668312f441ceccf5c6efa6fa14d7a96ab20fe51/lib/y2020/d04.ex" class="onebox" target="_blank" rel="noopener nofollow">https://gitlab.com/NobbZ/aoc_ex/-/blob/c668312f441ceccf5c6efa6fa14d7a96ab20fe51/lib/y2020/d04.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="197981" 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-2020-day-4/35971/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-197981" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197981"
                     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>