68 lines
1.4 KiB
Markdown
68 lines
1.4 KiB
Markdown
# 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()
|
|
```
|