Skip to content

Commit

Permalink
Merge pull request #72 from FrankKair/fred/more-elixir
Browse files Browse the repository at this point in the history
Elixir 017 019 029 030 034 048 055 089 097
  • Loading branch information
FrankKair authored May 29, 2018
2 parents fc2d718 + 292c150 commit ea765e8
Show file tree
Hide file tree
Showing 16 changed files with 1,431 additions and 2 deletions.
71 changes: 71 additions & 0 deletions src/017/p017.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env elixir
defmodule Problem017 do

defp unit2string([x]) do
case x do
1 -> "one"
2 -> "two"
3 -> "three"
4 -> "four"
5 -> "five"
6 -> "six"
7 -> "seven"
8 -> "eight"
9 -> "nine"
_ -> ""
end
end

defp tens2string([1, units]) do
case units do
0 -> "ten"
1 -> "eleven"
2 -> "twelve"
3 -> "thirteen"
4 -> "fourteen"
5 -> "fifteen"
6 -> "sixteen"
7 -> "seventeen"
8 -> "eighteen"
9 -> "nineteen"
end
end
defp tens2string([tens|units]) do
case tens do
2 -> "twenty" <> unit2string(units)
3 -> "thirty" <> unit2string(units)
4 -> "forty" <> unit2string(units)
5 -> "fifty" <> unit2string(units)
6 -> "sixty" <> unit2string(units)
7 -> "seventy" <> unit2string(units)
8 -> "eighty" <> unit2string(units)
9 -> "ninety" <> unit2string(units)
0 -> unit2string(units)
_ -> ""
end
end

defp int2string([first|rest]) do
case Enum.count([first|rest]) do
1 -> unit2string([first])
2 -> tens2string([first|rest])
3 ->
case rest do
[0,0] -> unit2string([first]) <> "hundred"
_ -> unit2string([first]) <> "hundredand" <> tens2string(rest)
end
_ -> ""
end
end
defp int2string(x), do: int2string(Integer.digits(x))

def solve do
1..999
|> Stream.map(&int2string/1)
|> Enum.reduce(&Kernel.<>/2)
|> Kernel.<>("onethousand")
|> String.length()
end
end

IO.puts Problem017.solve
33 changes: 33 additions & 0 deletions src/019/p019.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env elixir
defmodule Problem019 do
def is_leap_year(year) when rem(year, 400) == 0, do: true
def is_leap_year(year) when rem(year, 100) == 0, do: false
def is_leap_year(year) when rem(year, 4) == 0, do: true
def is_leap_year(_), do: false

def get_month_days(year) do
if is_leap_year(year) do
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
else
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
end
end

def calculate_month_first_days([[], [_|month_tail]]), do: month_tail
def calculate_month_first_days([[delta_head|delta_tail], [month_head|month_tail]]) do
calculate_month_first_days([delta_tail, [rem(delta_head+month_head, 7) | [month_head|month_tail]]])
end

def solve do
# [1901, 2] means that 1901-01-01 was a tuesday
Stream.unfold([1901, 2], fn [year, weekday] -> {[year, weekday],
[year+1, rem(weekday+Enum.sum(get_month_days(year)), 7)]} end)
|> Stream.take_while(fn [year, _] -> year <= 2000 end)
|> Stream.map(fn [year, weekday] -> [get_month_days(year), [weekday]] end)
|> Stream.map(&calculate_month_first_days/1)
|> Stream.map(&(Enum.count(&1, fn(x) -> x == 0 end)))
|> Enum.sum()
end
end

IO.puts Problem019.solve
14 changes: 14 additions & 0 deletions src/029/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
https://projecteuler.net/problem=029

Consider all integer combinations of a<sup>b</sup> for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:

- 2<sup>2</sup> = 4, 2<sup>3</sup> = 8, 2<sup>4</sup> = 16, 2<sup>5</sup> = 32
- 3<sup>2</sup> = 9, 3<sup>3</sup> = 27, 3<sup>4</sup> = 81, 3<sup>5</sup> = 243
- 4<sup>2</sup> = 16, 4<sup>3</sup> = 64, 4<sup>4</sup> = 256, 4<sup>5</sup> = 1024
- 5<sup>2</sup> = 25, 5<sup>3</sup> = 125, 5<sup>4</sup> = 625, 5<sup>5</sup> = 3125

If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by a<sup>b</sup> for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?
16 changes: 16 additions & 0 deletions src/029/p029.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env elixir
defmodule Problem029 do
defp generate_powers() do
for a <- 2..100,
b <- 2..100,
do: trunc(:math.pow(a, b))
end

def solve do
generate_powers()
|> Enum.uniq()
|> Enum.count()
end
end

IO.puts Problem029.solve
13 changes: 13 additions & 0 deletions src/030/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
https://projecteuler.net/problem=030

Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits:

- 1634 = 1<sup>4</sup> + 6<sup>4</sup> + 3<sup>4</sup> + 4<sup>4</sup>
- 8208 = 8<sup>4</sup> + 2<sup>4</sup> + 0<sup>4</sup> + 8<sup>4</sup>
- 9474 = 9<sup>4</sup> + 4<sup>4</sup> + 7<sup>4</sup> + 4<sup>4</sup>

As 1 = 1<sup>4</sup> is not a sum it is not included.

The sum of these numbers is 1634 + 8208 + 9474 = 19316.

Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.
18 changes: 18 additions & 0 deletions src/030/p030.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env elixir
defmodule Problem030 do
defp digits_fifth_power(x) do
x
|> Integer.digits()
|> Enum.map(&(trunc(:math.pow(&1, 5))))
|> Enum.sum()
end

def solve do
Stream.iterate(2, &(&1+1))
|> Enum.take_while(&(&1 < 200_000))
|> Stream.filter(&(&1 == digits_fifth_power(&1)))
|> Enum.sum()
end
end

IO.puts Problem030.solve
7 changes: 7 additions & 0 deletions src/034/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
https://projecteuler.net/problem=034

145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145.

Find the sum of all numbers which are equal to the sum of the factorial of their digits.

Note: as 1! = 1 and 2! = 2 are not sums they are not included.
22 changes: 22 additions & 0 deletions src/034/p034.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env elixir
defmodule Problem034 do
defp factorial(1), do: 1
defp factorial(x) when is_integer(x) and x > 0, do: x*factorial(x-1)

defp is_factorial_sum?(number) do
number ==
number
|> Integer.digits()
|> Enum.map(&(factorial(&1)))
|> Enum.sum()
end

def solve do
3..40_585 # magic number!
|> Stream.filter(&(is_factorial_sum?(&1)))
|> Enum.to_list()
|> Enum.sum()
end
end

IO.puts Problem034.solve
5 changes: 3 additions & 2 deletions src/048/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
https://projecteuler.net/problem=048

The series, 1^1 + 2^2 + 3^3 + ... + 10^10 = 10405071317.
Find the last ten digits of the series, 1^1 + 2^2 + 3^3 + ... + 1000^1000.
The series, 1<sup>1</sup> + 2<sup>2</sup> + 3<sup>3</sup> + ... + 10<sup>10</sup> = 10405071317.

Find the last ten digits of the series, 1<sup>1</sup> + 2<sup>2</sup> + 3<sup>3</sup> + ... + 1000<sup>1000</sup>.
29 changes: 29 additions & 0 deletions src/048/p048.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env elixir
defmodule Problem048 do

defp pow_mod10000000000(_, 0), do: 1
defp pow_mod10000000000(x, n) when rem(n, 2) != 0 do
x * pow_mod10000000000(x, n - 1)
|> Integer.digits()
|> Enum.take(-10)
|> Integer.undigits()
end
defp pow_mod10000000000(x, n) do
result = pow_mod10000000000(x, div(n, 2))
result * result
|> Integer.digits()
|> Enum.take(-10)
|> Integer.undigits()
end

def solve do
1..1000
|> Stream.map(&(pow_mod10000000000(&1, &1)))
|> Enum.sum()
|> Integer.digits()
|> Enum.take(-10)
|> Integer.undigits()
end
end

IO.puts Problem048.solve
19 changes: 19 additions & 0 deletions src/055/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
https://projecteuler.net/problem=055

If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.

Not all numbers produce palindromes so quickly. For example,

349 + 943 = 1292,
1292 + 2921 = 4213
4213 + 3124 = 7337

That is, 349 took three iterations to arrive at a palindrome.

Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).

Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994.

How many Lychrel numbers are there below ten-thousand?

NOTE: Wording was modified slightly on 24 April 2007 to emphasise the theoretical nature of Lychrel numbers.
28 changes: 28 additions & 0 deletions src/055/p055.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env elixir
defmodule Problem055 do
defp reverse_number(x) do
x
|> Integer.to_string()
|> String.reverse()
|> String.to_integer()
end

defp reverse_sum(x), do: x + reverse_number(x)

defp is_palindrome(x), do: x == reverse_number(x)

defp is_Lychrel_number(x) do
Stream.unfold(reverse_sum(x), fn n -> {n, reverse_sum(n)} end)
|> Stream.take(50)
|> Enum.any?(&is_palindrome/1)
|> Kernel.not
end

def solve do
1..10_000
|> Stream.filter(&is_Lychrel_number/1)
|> Enum.count()
end
end

IO.puts Problem055.solve
20 changes: 20 additions & 0 deletions src/089/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
https://projecteuler.net/problem=089

For a number written in Roman numerals to be considered valid there are basic rules which must be followed. Even though the rules allow some numbers to be expressed in more than one way there is always a "best" way of writing a particular number.

For example, it would appear that there are at least six ways of writing the number sixteen:

IIIIIIIIIIIIIIII
VIIIIIIIIIII
VVIIIIII
XIIIIII
VVVI
XVI

However, according to the rules only `XIIIIII` and `XVI` are valid, and the last example is considered to be the most efficient, as it uses the least number of numerals.

The 11K text file, [roman.txt](https://projecteuler.net/project/resources/p089_roman.txt) (right click and 'Save Link/Target As...'), contains one thousand numbers written in valid, but not necessarily minimal, Roman numerals; see [About... Roman Numerals](https://projecteuler.net/about=roman_numerals) for the definitive rules for this problem.

Find the number of characters saved by writing each of these in their minimal form.

Note: You can assume that all the Roman numerals in the file contain no more than four consecutive identical units.
Loading

0 comments on commit ea765e8

Please sign in to comment.