Skip to content

Latest commit

 

History

History
859 lines (679 loc) · 28.6 KB

readme.org

File metadata and controls

859 lines (679 loc) · 28.6 KB

Project Euler solutions

In this file I will solve problems from Project Euler using Elixir lang.

Solutions:

1234567
891011121314
15161718192021

Reusable modules

Number Theory Module

defmodule NumberTheory do
  def gcd(a, 0), do: a
  def gcd(0, a), do: a
  def gcd(a, b), do: gcd(min(a, b), rem(max(a, b), min(a, b)))

  def lcm(a, b), do: div(a * b, gcd(a, b))

  def naturals, do: Stream.iterate(1, fn n -> n + 1 end)

  def max_prime_divisor(n), do: n |> :math.sqrt() |> ceil

  def possible_factors(n), do: 2..max_prime_divisor(n)

  def divides?(a, b), do: rem(b, a) == 0

  def divisors(n) do
    1..n |> Enum.filter(&divides?(&1, n))
  end

  def !(n), do: 1..n |> Enum.product()
end

Prime module

defmodule Prime do
  def prime?(2), do: true

  def prime?(n),
    do:
      n
      |> NumberTheory.possible_factors()
      |> Enum.filter(&NumberTheory.divides?(&1, n))
      |> (&(&1 == [])).()

  def primes do
    Stream.concat(2..2, Stream.iterate(3, fn n -> n + 2 end)) |> Stream.filter(&prime?/1)
  end

  def nth_prime(n) do
    primes() |> Stream.drop(n - 1) |> Enum.take(1) |> hd
  end

  def take(n), do: primes() |> Enum.take(n)

  def take_while(func), do: primes() |> Stream.take_while(func) |> Enum.to_list()

  def possible_prime_factors(n) do
    max_val = NumberTheory.max_prime_divisor(n)
    primes() |> Stream.take_while(fn el -> el <= max_val end) |> Enum.to_list()
  end
end

Set Module

defmodule Set do
  def cartesian_prod(set_a, set_b) do
    Stream.flat_map(set_a, fn x -> Stream.map(set_b, fn y -> {x, y} end) end)
  end
end

Helper functions

fst = fn {a, _} -> a end
snd = fn {_, a} -> a end

split_integer = fn n ->
  n |> Integer.to_string() |> String.split("", trim: true) |> Enum.map(&String.to_integer/1)
end

Problem 1

Find the sum of all the multiples of 3 or 5 below 1000.

multiple_of_3_or_5 = fn n -> rem(n, 5) * rem(n, 3) == 0 end
1..999 |> Enum.filter(multiple_of_3_or_5) |> Enum.sum()
233168

Problem 2

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

require Integer

defmodule Ex2 do
  @limit 4_000_000

  defp fib(list) do
    curr = list |> Enum.take(2) |> Enum.sum()

    if curr < @limit do
      fib([curr | list])
    else
      list
    end
  end

  defp even?(x), do: rem(x, 2) == 0

  def fib_even_sum() do
    [1, 1] |> fib |> Enum.filter(&even?/1) |> Enum.sum()
  end
end

Ex2.fib_even_sum()
4613732

Problem 3

What is the largest prime factor of the number 600851475143?

largest_prime_factor = fn n ->
  n
  |> Prime.possible_prime_factors()
  |> Enum.filter(&Prime.divides?(&1, n))
  |> List.last()
end

largest_prime_factor.(600_851_475_143)
6857

Problem 4

Find the largest palindrome made from the product of two 3-digit numbers.

palindrome? = fn n ->
  str = Integer.to_string(n)
  str == String.reverse(str)
end

numbers = 999..100

Stream.zip_with(numbers, numbers, &(&1 * &2)) |> Stream.filter(palindrome?) |> Enum.take(1) |> hd
698896

Problem 5

What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?

1..20 |> Enum.reduce(1, &NumberTheory.lcm/2)
232792560

Problem 6

Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

square_of_the_sum = fn n -> div(n * (n + 1), 2) ** 2 end

sum_of_the_squares = fn n -> div(n * (n + 1) * (2 * n + 1), 6) end

square_of_the_sum.(100) - sum_of_the_squares.(100)
25164150

Problem 7

What is the 10 001st prime number?

Prime.nth_prime 10_001
104743

Problem 8

Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?

number = 7_316_717_653_133_062_491_922_511_967_442_657_474_235_534_919_493_496_983_520_312_774_506_326_239_578_318_016_984_801_869_478_851_843_858_615_607_891_129_494_954_595_017_379_583_319_528_532_088_055_111_254_069_874_715_852_386_305_071_569_329_096_329_522_744_304_355_766_896_648_950_445_244_523_161_731_856_403_098_711_121_722_383_113_622_298_934_233_803_081_353_362_766_142_828_064_444_866_452_387_493_035_890_729_629_049_156_044_077_239_071_381_051_585_930_796_086_670_172_427_121_883_998_797_908_792_274_921_901_699_720_888_093_776_657_273_330_010_533_678_812_202_354_218_097_512_545_405_947_522_435_258_490_771_167_055_601_360_483_958_644_670_632_441_572_215_539_753_697_817_977_846_174_064_955_149_290_862_569_321_978_468_622_482_839_722_413_756_570_560_574_902_614_079_729_686_524_145_351_004_748_216_637_048_440_319_989_000_889_524_345_065_854_122_758_866_688_116_427_171_479_924_442_928_230_863_465_674_813_919_123_162_824_586_178_664_583_591_245_665_294_765_456_828_489_128_831_426_076_900_422_421_902_267_105_562_632_111_110_937_054_421_750_694_165_896_040_807_198_403_850_962_455_444_362_981_230_987_879_927_244_284_909_188_845_801_561_660_979_191_338_754_992_005_240_636_899_125_607_176_060_588_611_646_710_940_507_754_100_225_698_315_520_005_593_572_972_571_636_269_561_882_670_428_252_483_600_823_257_530_420_752_963_450

number_list = number |> split_integer.()

el_mul = fn idx ->
  Enum.drop(number_list, idx) |> Enum.take(13) |> (&{&1, Enum.product(&1)}).()
end

0..999 |> Enum.map(el_mul) |> Enum.max(fn a, b -> snd.(a) > snd.(b) end)
{[5, 5, 7, 6, 6, 8, 9, 6, 6, 4, 8, 9, 5], 23514624000}

Problem 9

There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product abc.

Solution:

For $m,n$, a pitagorean triplet can be defined as:

$a = m^2 - n^2$

$b = 2mn$

$c = m^2 + n^2$

Therefore $a+b+c = 2m^2 + 2mn = 1000 \therefore m^2 +mn = 500$

We want $abc = (m^2 - n^2)(2mn)(m^2+n^2) = 2 m^5 n - 2 m n^5 = 2mn(m^4 - n^4)$

nums = 1..500

get_abc = fn {m, n} -> {m * m - n * n, 2 * m * n, m * m + n * n} end

check_abc = fn {a, b, c} -> a > 0 and b > 0 and c > 0 end

check_mn = fn {a, b} ->
  a ** 2 + a * b === 500 and {a, b} |> get_abc.() |> check_abc.()
end

calc_abc = fn {a, b, c} -> {{a, b, c}, a * b * c} end

Set.cartesian_prod(nums, nums)
|> Stream.filter(check_mn)
|> Stream.map(get_abc)
|> Stream.map(calc_abc)
|> Enum.take(1)
|> hd
{{375, 200, 425}, 31875000}

Problem 10

Find the sum of all the primes below two million.

Prime.take_while(&(&1 < 2_000_000)) |> Enum.sum()  
142913828922

Problem 11

In the 20×20 grid below

number_grid = [
  [08, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91, 08],
  [49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 04, 56, 62, 00],
  [81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 03, 49, 13, 36, 65],
  [52, 70, 95, 23, 04, 60, 11, 42, 69, 24, 68, 56, 01, 32, 56, 71, 37, 02, 36, 91],
  [22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80],
  [24, 47, 32, 60, 99, 03, 45, 02, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50],
  [32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70],
  [67, 26, 20, 68, 02, 62, 12, 20, 95, 63, 94, 39, 63, 08, 40, 91, 66, 49, 94, 21],
  [24, 55, 58, 05, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72],
  [21, 36, 23, 09, 75, 00, 76, 44, 20, 45, 35, 14, 00, 61, 33, 97, 34, 31, 33, 95],
  [78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 03, 80, 04, 62, 16, 14, 09, 53, 56, 92],
  [16, 39, 05, 42, 96, 35, 31, 47, 55, 58, 88, 24, 00, 17, 54, 24, 36, 29, 85, 57],
  [86, 56, 00, 48, 35, 71, 89, 07, 05, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58],
  [19, 80, 81, 68, 05, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 04, 89, 55, 40],
  [04, 52, 08, 83, 97, 35, 99, 16, 07, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66],
  [88, 36, 68, 87, 57, 62, 20, 72, 03, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69],
  [04, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 08, 46, 29, 32, 40, 62, 76, 36],
  [20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 04, 36, 16],
  [20, 73, 35, 29, 78, 31, 90, 01, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 05, 54],
  [01, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 01, 89, 19, 67, 48]
]

What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?

at = fn {x, y} ->
  if x < 0 or y < 0 do
    0
  else
    number_grid |> Enum.at(x, []) |> Enum.at(y, 0)
  end
end

north = fn {x, y} -> 0..3 |> Enum.map(&{x - &1, y}) end
south = fn {x, y} -> 0..3 |> Enum.map(&{x + &1, y}) end
east = fn {x, y} -> 0..3 |> Enum.map(&{x, y - &1}) end
west = fn {x, y} -> 0..3 |> Enum.map(&{x, y + &1}) end
northwest = fn {x, y} -> 0..3 |> Enum.map(&{x - &1, y + &1}) end
northeast = fn {x, y} -> 0..3 |> Enum.map(&{x - &1, y - &1}) end
southwest = fn {x, y} -> 0..3 |> Enum.map(&{x + &1, y + &1}) end
southeast = fn {x, y} -> 0..3 |> Enum.map(&{x + &1, y - &1}) end

directions = fn idx ->
  [north, south, east, west, northeast, northwest, southeast, southwest]
  |> Enum.map(fn f -> f.(idx) end)
end

multiply = fn idxs -> idxs |> Enum.map(at) |> Enum.product() end

max_at_idx = fn idx -> idx |> directions.() |> Enum.map(multiply) |> Enum.max() end

idxs = 0..19

Set.cartesian_prod(idxs, idxs)
|> Enum.to_list()
|> Enum.map(max_at_idx)
|> Enum.max()
70600674

Problem 12

What is the value of the first triangle number to have over five hundred divisors?

triangle_number = fn idx -> div(idx * (idx + 1), 2) end
count_divisors = fn n -> n |> NumberTheory.divisors() |> length end
check_divisors = fn n -> count_divisors.(n) > 100 end

NumberTheory.naturals()
|> Stream.map(triangle_number)
|> Stream.filter(check_divisors)
|> Enum.take(1)
|> hd
73920

Problem 13

Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.

fifty_digit_numbers = [
  37_107_287_533_902_102_798_797_998_220_837_590_246_510_135_740_250,
  46_376_937_677_490_009_712_648_124_896_970_078_050_417_018_260_538,
  74_324_986_199_524_741_059_474_233_309_513_058_123_726_617_309_629,
  91_942_213_363_574_161_572_522_430_563_301_811_072_406_154_908_250,
  23_067_588_207_539_346_171_171_980_310_421_047_513_778_063_246_676,
  89_261_670_696_623_633_820_136_378_418_383_684_178_734_361_726_757,
  28_112_879_812_849_979_408_065_481_931_592_621_691_275_889_832_738,
  44_274_228_917_432_520_321_923_589_422_876_796_487_670_272_189_318,
  47_451_445_736_001_306_439_091_167_216_856_844_588_711_603_153_276,
  70_386_486_105_843_025_439_939_619_828_917_593_665_686_757_934_951,
  62_176_457_141_856_560_629_502_157_223_196_586_755_079_324_193_331,
  64_906_352_462_741_904_929_101_432_445_813_822_663_347_944_758_178,
  92_575_867_718_337_217_661_963_751_590_579_239_728_245_598_838_407,
  58_203_565_325_359_399_008_402_633_568_948_830_189_458_628_227_828,
  80_181_199_384_826_282_014_278_194_139_940_567_587_151_170_094_390,
  35_398_664_372_827_112_653_829_987_240_784_473_053_190_104_293_586,
  86_515_506_006_295_864_861_532_075_273_371_959_191_420_517_255_829,
  71_693_888_707_715_466_499_115_593_487_603_532_921_714_970_056_938,
  54_370_070_576_826_684_624_621_495_650_076_471_787_294_438_377_604,
  53_282_654_108_756_828_443_191_190_634_694_037_855_217_779_295_145,
  36_123_272_525_000_296_071_075_082_563_815_656_710_885_258_350_721,
  45_876_576_172_410_976_447_339_110_607_218_265_236_877_223_636_045,
  17_423_706_905_851_860_660_448_207_621_209_813_287_860_733_969_412,
  81_142_660_418_086_830_619_328_460_811_191_061_556_940_512_689_692,
  51_934_325_451_728_388_641_918_047_049_293_215_058_642_563_049_483,
  62_467_221_648_435_076_201_727_918_039_944_693_004_732_956_340_691,
  15_732_444_386_908_125_794_514_089_057_706_229_429_197_107_928_209,
  55_037_687_525_678_773_091_862_540_744_969_844_508_330_393_682_126,
  18_336_384_825_330_154_686_196_124_348_767_681_297_534_375_946_515,
  80_386_287_592_878_490_201_521_685_554_828_717_201_219_257_766_954,
  78_182_833_757_993_103_614_740_356_856_449_095_527_097_864_797_581,
  16_726_320_100_436_897_842_553_539_920_931_837_441_497_806_860_984,
  48_403_098_129_077_791_799_088_218_795_327_364_475_675_590_848_030,
  87_086_987_551_392_711_854_517_078_544_161_852_424_320_693_150_332,
  59_959_406_895_756_536_782_107_074_926_966_537_676_326_235_447_210,
  69_793_950_679_652_694_742_597_709_739_166_693_763_042_633_987_085,
  41_052_684_708_299_085_211_399_427_365_734_116_182_760_315_001_271,
  65_378_607_361_501_080_857_009_149_939_512_557_028_198_746_004_375,
  35_829_035_317_434_717_326_932_123_578_154_982_629_742_552_737_307,
  94_953_759_765_105_305_946_966_067_683_156_574_377_167_401_875_275,
  88_902_802_571_733_229_619_176_668_713_819_931_811_048_770_190_271,
  25_267_680_276_078_003_013_678_680_992_525_463_401_061_632_866_526,
  36_270_218_540_497_705_585_629_946_580_636_237_993_140_746_255_962,
  24_074_486_908_231_174_977_792_365_466_257_246_923_322_810_917_141,
  91_430_288_197_103_288_597_806_669_760_892_938_638_285_025_333_403,
  34_413_065_578_016_127_815_921_815_005_561_868_836_468_420_090_470,
  23_053_081_172_816_430_487_623_791_969_842_487_255_036_638_784_583,
  11_487_696_932_154_902_810_424_020_138_335_124_462_181_441_773_470,
  63_783_299_490_636_259_666_498_587_618_221_225_225_512_486_764_533,
  67_720_186_971_698_544_312_419_572_409_913_959_008_952_310_058_822,
  95_548_255_300_263_520_781_532_296_796_249_481_641_953_868_218_774,
  76_085_327_132_285_723_110_424_803_456_124_867_697_064_507_995_236,
  37_774_242_535_411_291_684_276_865_538_926_205_024_910_326_572_967,
  23_701_913_275_725_675_285_653_248_258_265_463_092_207_058_596_522,
  29_798_860_272_258_331_913_126_375_147_341_994_889_534_765_745_501,
  18_495_701_454_879_288_984_856_827_726_077_713_721_403_798_879_715,
  38_298_203_783_031_473_527_721_580_348_144_513_491_373_226_651_381,
  34_829_543_829_199_918_180_278_916_522_431_027_392_251_122_869_539,
  40_957_953_066_405_232_632_538_044_100_059_654_939_159_879_593_635,
  29_746_152_185_502_371_307_642_255_121_183_693_803_580_388_584_903,
  41_698_116_222_072_977_186_158_236_678_424_689_157_993_532_961_922,
  62_467_957_194_401_269_043_877_107_275_048_102_390_895_523_597_457,
  23_189_706_772_547_915_061_505_504_953_922_979_530_901_129_967_519,
  86_188_088_225_875_314_529_584_099_251_203_829_009_407_770_775_672,
  11_306_739_708_304_724_483_816_533_873_502_340_845_647_058_077_308,
  82_959_174_767_140_363_198_008_187_129_011_875_491_310_547_126_581,
  97_623_331_044_818_386_269_515_456_334_926_366_572_897_563_400_500,
  42_846_280_183_517_070_527_831_839_425_882_145_521_227_251_250_327,
  55_121_603_546_981_200_581_762_165_212_827_652_751_691_296_897_789,
  32_238_195_734_329_339_946_437_501_907_836_945_765_883_352_399_886,
  75_506_164_965_184_775_180_738_168_837_861_091_527_357_929_701_337,
  62_177_842_752_192_623_401_942_399_639_168_044_983_993_173_312_731,
  32_924_185_707_147_349_566_916_674_687_634_660_915_035_914_677_504,
  99_518_671_430_235_219_628_894_890_102_423_325_116_913_619_626_622,
  73_267_460_800_591_547_471_830_798_392_868_535_206_946_944_540_724,
  76_841_822_524_674_417_161_514_036_427_982_273_348_055_556_214_818,
  97_142_617_910_342_598_647_204_516_893_989_422_179_826_088_076_852,
  87_783_646_182_799_346_313_767_754_307_809_363_333_018_982_642_090,
  10_848_802_521_674_670_883_215_120_185_883_543_223_812_876_952_786,
  71_329_612_474_782_464_538_636_993_009_049_310_363_619_763_878_039,
  62_184_073_572_399_794_223_406_235_393_808_339_651_327_408_011_116,
  66_627_891_981_488_087_797_941_876_876_144_230_030_984_490_851_411,
  60_661_826_293_682_836_764_744_779_239_180_335_110_989_069_790_714,
  85_786_944_089_552_990_653_640_447_425_576_083_659_976_645_795_096,
  66_024_396_409_905_389_607_120_198_219_976_047_599_490_197_230_297,
  64_913_982_680_032_973_156_037_120_041_377_903_785_566_085_089_252,
  16_730_939_319_872_750_275_468_906_903_707_539_413_042_652_315_011,
  94_809_377_245_048_795_150_954_100_921_645_863_754_710_598_436_791,
  78_639_167_021_187_492_431_995_700_641_917_969_777_599_028_300_699,
  15_368_713_711_936_614_952_811_305_876_380_278_410_754_449_733_078,
  40_789_923_115_535_562_561_142_322_423_255_033_685_442_488_917_353,
  44_889_911_501_440_648_020_369_068_063_960_672_322_193_204_149_535,
  41_503_128_880_339_536_053_299_340_368_006_977_710_650_566_631_954,
  81_234_880_673_210_146_739_058_568_557_934_581_403_627_822_703_280,
  82_616_570_773_948_327_592_232_845_941_706_525_094_512_325_230_608,
  22_918_802_058_777_319_719_839_450_180_888_072_429_661_980_811_197,
  77_158_542_502_016_545_090_413_245_809_786_882_778_948_721_859_617,
  72_107_838_435_069_186_155_435_662_884_062_257_473_692_284_509_516,
  20_849_603_980_134_001_723_930_671_666_823_555_245_252_804_609_722,
  53_503_534_226_472_524_250_874_054_075_591_789_781_264_330_331_690
]

fifty_digit_numbers |> Enum.sum() |> Integer.to_charlist() |> Enum.take(10)
'5537376230'

Problem 14

The following iterative sequence is defined for the set of positive integers:

$n → n/2$ (n is even)

$n → 3n + 1$ (n is odd)

Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1. Which starting number, under one million, produces the longest chain?

defmodule Ex14 do
  defp even?(n), do: rem(n, 2) == 0

  defp calc_next(curr) do
    if even?(curr) do
      div(curr, 2)
    else
      3 * curr + 1
    end
  end

  defp collatz_rec(lst) do
    curr = hd(lst)

    if curr == 1 do
      lst
    else
      [calc_next(curr) | lst] |> collatz_rec()
    end
  end

  def collatz(n), do: collatz_rec([n])

  def count_chain(n) do
    {length(collatz(n)), n}
  end

  def sdn({_, a}), do: a
end

1..1_000_000 |> Enum.map(&Ex14.count_chain/1) |> Enum.max() |> Ex14.sdn()
837799

Problem 15

Starting in the top left corner of a 20×20 grid, and only being able to move to the right and down, how many routes to the bottom right are there through a 20×20 grid?

div(NumberTheory.!(20) * NumberTheory.!(20), NumberTheory.!(2) * NumberTheory.!(2))
1479753045347481921354360422400000000

Problem 16

What is the sum of the digits of the number $21000$ ?

2**1000 |> split_integer.() |> Enum.sum()
1366

Problem 17

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

num_map = %{
  0 => "",
  1 => "one",
  2 => "two",
  3 => "three",
  4 => "four",
  5 => "five",
  6 => "six",
  7 => "seven",
  8 => "eight",
  9 => "nine",
  10 => "ten",
  11 => "eleven",
  12 => "twelve",
  13 => "thirteen",
  14 => "fourteen",
  15 => "fifteen",
  16 => "sixteen",
  17 => "seventeen",
  18 => "eighteen",
  19 => "nineteen",
  20 => "twenty",
  30 => "thirty",
  40 => "fourty",
  50 => "fifty",
  60 => "sixty",
  70 => "seventy",
  80 => "eighty",
  90 => "ninety"
}

first_two = fn n ->
  if n < 21 do
    num_map[n]
  else
    unity = rem(n, 10)
    decimal = n - unity
    String.trim("#{num_map[decimal]} #{num_map[unity]}")
  end
end

write_num = fn n ->
  dec = rem(n, 100)
  hundred_digit = n |> rem(1000) |> div(100)
  thousand_digit = div(n, 1000)

  hundred =
    if hundred_digit > 0 do
      "#{num_map[hundred_digit]} hundred and "
    else
      ""
    end

  thousand =
    if thousand_digit > 0 do
      "#{num_map[thousand_digit]} thousand "
    else
      ""
    end

  (thousand <> hundred <> first_two.(dec))
  |> String.replace(~r/and[[:blank:]]$/, "")
  |> String.trim()
end

count_number = fn n ->
  n
  |> write_num.()
  |> String.replace(~r/[[:blank:]]/, "")
  |> String.length()
end

1..1000 |> Enum.map(count_number) |> Enum.sum()
21221

Problem 18

Find the maximum total from top to bottom of the triangle below:

tree = [
  [75],
  [95, 64],
  [17, 47, 82],
  [18, 35, 87, 10],
  [20, 04, 82, 47, 65],
  [19, 01, 23, 75, 03, 34],
  [88, 02, 77, 73, 07, 63, 67],
  [99, 65, 04, 28, 06, 16, 70, 92],
  [41, 41, 26, 56, 83, 40, 80, 70, 33],
  [41, 48, 72, 33, 47, 32, 37, 16, 94, 29],
  [53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14],
  [70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57],
  [91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48],
  [63, 66, 04, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
  [04, 62, 98, 27, 23, 09, 70, 98, 73, 93, 38, 53, 60, 04, 23]
]

defmodule T do
  def tree,
    do: [
      [75],
      [95, 64],
      [17, 47, 82],
      [18, 35, 87, 10],
      [20, 04, 82, 47, 65],
      [19, 01, 23, 75, 03, 34],
      [88, 02, 77, 73, 07, 63, 67],
      [99, 65, 04, 28, 06, 16, 70, 92],
      [41, 41, 26, 56, 83, 40, 80, 70, 33],
      [41, 48, 72, 33, 47, 32, 37, 16, 94, 29],
      [53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14],
      [70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57],
      [91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48],
      [63, 66, 04, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
      [04, 62, 98, 27, 23, 09, 70, 98, 73, 93, 38, 53, 60, 04, 23]
    ]

  defp at({h, i}) do
    if h < 0 or i < 0 do
      0
    else
      tree() |> Enum.at(h, []) |> Enum.at(i, 0)
    end
  end

  defp left({h, i}), do: {h + 1, i}
  defp right({h, i}), do: {h + 1, i + 1}

  defp sum_path_rec(coords, acc) do
    node = at(coords)
    l = left(coords)
    r = right(coords)

    if node === 0 do
      acc
    else
      max(sum_path_rec(l, acc + node), sum_path_rec(r, acc + node))
    end
  end

  def sum_path, do: sum_path_rec({0, 0}, 0)
end

T.sum_path()
1074

Problem 19

months = [
  jan: 31,
  feb: 28,
  feb_leap: 29,
  mar: 31,
  apr: 30,
  may: 31,
  jun: 30,
  jul: 31,
  aug: 31,
  sep: 30,
  oct: 31,
  nov: 31,
  dec: 31
]

leap_year? = fn year -> NumberTheory.gcd(80, year) > NumberTheory.gcd(50, year) end

days_in_year = fn year ->
  if leap_year?.(year) do
    366
  else
    365
  end
end

month_length = fn month -> months[month] end

months_length = fn year ->
  feb =
    if leap_year?.(year) do
      :feb_leap
    else
      :feb
    end

  [:jan, feb, :mar, :apr, :may, :jun, :jul, :aug, :sep, :oct, :nov, :dec]
  |> Enum.map(month_length)
end

sunday? = fn day -> rem(day, 7) === 6 end

years = 1901..2000

num_days = years |> Enum.map(days_in_year) |> Enum.sum()

days = 1..num_days

sundays = days |> Enum.filter(sunday?)

first_of_each_month =
  years
  |> Enum.map(months_length)
  |> List.flatten()
  |> Enum.reduce([1], fn val, [x | xs] -> [val + x | [x | xs]] end)


sundays_firsts = first_of_each_month |> Enum.filter(&Enum.member?(sundays, &1)) |> length
173

Problem 20

100 |> NumberTheory.!() |> split_integer.() |> Enum.sum()
648

Problem 21

d = fn n -> n |> NumberTheory.divisors() |> List.pop_at(-1) |> snd.() |> Enum.sum() end

amicable? = fn n -> n |> d.() |> d.() === n end

2..9999 |> Enum.filter(amicable?) |> length
14