From a4e6849f99878825061e43bcbc24ccde0ccfbe50 Mon Sep 17 00:00:00 2001 From: Caleb Webber Date: Fri, 28 Feb 2025 01:47:31 -0500 Subject: [PATCH] add solution for problem 19 --- problems/19/solution.livemd | 68 +++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 problems/19/solution.livemd diff --git a/problems/19/solution.livemd b/problems/19/solution.livemd new file mode 100644 index 0000000..bc5fd5b --- /dev/null +++ b/problems/19/solution.livemd @@ -0,0 +1,68 @@ +# Project Euler Problem 19 + +```elixir +defmodule CountingSundays do + defguard is_leap_year(y) when rem(y, 4) == 0 and (rem(y, 100) != 0 or rem(y, 400) == 0) + + @days %{ + 0 => :sun, + 1 => :mon, + 2 => :tue, + 3 => :wed, + 4 => :thur, + 5 => :fri, + 6 => :sat, + } + + @months %{ + 0 => :jan, + 1 => :feb, + 2 => :mar, + 3 => :apr, + 4 => :may, + 5 => :jun, + 6 => :jul, + 7 => :aug, + 8 => :sep, + 9 => :oct, + 10 => :nov, + 11 => :dec + } + + def days_in_month(year, month) do + case month do + m when m in [:apr, :jun, :nov, :sep] -> 30 + :feb when is_leap_year(year) -> 29 + :feb -> 28 + _ -> 31 + end + end + + def add_days(d, days), do: rem(d + days, 7) + + defp count_sundays_between(year, month, fin_year, fin_month, _, acc) + when fin_month < month and fin_year == year or year > fin_year do + acc + end + + defp count_sundays_between(year, month, fin_year, fin_month, d, acc) do + next = add_days(d, days_in_month(year, @months[month])) + + acc = if @days[next] == :sun, do: acc + 1, else: acc + {year, month} = case month do + 11 -> { year + 1, 0} + n -> { year, n + 1} + end + + count_sundays_between(year, month, fin_year, fin_month, next, acc) + end + + def count_sundays() do + count_sundays_between(1900, 0, 2000, 11, 1, 0) - count_sundays_between(1900, 0, 1900, 11, 1, 0) + end +end +``` + +```elixir +CountingSundays.count_sundays() +```