Project Euler의 Smallest multiple을 Elixir로 풀기
14304 단어 ProjectEulerElixir알고리즘수학재귀
Smallest multiple
위의 기사에서는 「 Project Euler 자신의 경우, 특히 "Smallest multiple"라는 문제가 인상에 남았습니다.
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
1에서 10까지의 자연수의 최소 공배수는 2520이 된다고 합니다만, 1에서 20이라고 어떨까? 라는 문제입니다.
사고방식
우선은 문제를 풀기 위한 생각입니다만, 자신은 이하의 Yahoo!지혜봉투의 해답이 참고가 되었습니다.
1~10까지의 자연수의 최소 공배수가 2520이 되는 것 같습니다만, 어떻게... - Yahoo!지혜봉투
베스트 앤서의 해답은 이미 2520이라는 숫자를 알고 있었을 때, 왜 1에서 10까지의 자연수의 최소 공배수가 되는지를 설명하고 있는 것처럼 보였지만, 다른 해답은 다른 접근법을 취하고 있었습니다 . 특히 실제로 문제를 해결할 때는 해답의 후반부에
1과 2의 최소 공배수는 2,
2와 3의 최소 공배수는 6,
6과 4의 최소 공배수는 12,
12와 5의 최소 공배수는 60,
60과 6의 최소 공배수는 60,
60과 7의 최소 공배수는 420,
420과 8의 최소 공배수는 840,
840과 9의 최소 공배수는 2520
이 아이디어를 사용하여 재귀로 프로그램을 작성하기로 결정했습니다.
최소 공배수와 최대 공약수
프로그램을 작성할 때 먼저 두 개의 자연수의 최소 공배수를 구해야 합니다.
2개의 자연수 a, b의 최대 공약수를 GCD로 하면 최소 공배수 LCM은 다음의 공식으로 구해집니다. 1
LCM = \frac{a \times b}{GCD}
이 때문에, 우선은 최소 공배수를 구할 필요가 있습니다. 최소 공배수는 유클리드 호제법으로 구할 수 있습니다. 대체로 이하와 같이 쓸 수 있을까 생각합니다. 2
defmodule Problem5 do
def gcd(a, b) do
if rem(a, b) == 0 do
b
else
gcd(b, rem(a, b))
end
end
end
Elixir에 연산자
%
가 없으므로 rem
를 사용합니다.위의 프로그램을 사용하여 예를 들어 824와 128의 최대 공약수를 구하려면 다음과 같이 합니다.
IO.puts Problem5.gcd(824, 128) # 8
다음에, 방금 전의 생각을 이용해 최소 공배수를 구해 갑니다. 자신은 이렇게 썼습니다.
defmodule Problem5 do
def gcd(a, b) do
if rem(a, b) == 0 do
b
else
gcd(b, rem(a, b))
end
end
def solve(n, lcm, max) do
if n == max do
lcm
else
lcm_next = div(n * lcm, gcd(n, lcm))
solve(n+1, lcm_next, max)
end
end
end
인수 n에 주어진 자연수가 max에 도달할 때까지 반복합니다. Elixir에서는 나눗셈으로 정수 값을 반환하려면
div
를 사용합니다.iex(1)> 6 / 2
3.0
iex(2)> div(6, 2)
3
이것을 사용하여 문제에 대한 대답을 구할 때,
IO.puts Problem5.solve(2, 1, 10) # 2520
IO.puts Problem5.solve(2, 1, 20) # 232792560
와 같이 됩니다.
감상
자신은 평소 재귀를 사용하는 것이 거의 없었기 때문에, while등을 사용할 수 없고, 재귀로 쓰도록 요구되는 Elixir는 신선했습니다. 앞으로는 이러한 생각도 슬러슬러 할 수 있게 되어 가고 싶습니다.
추가
함수
gcd
이나 solve
입니다만, 패턴 매치를 사용해 이하와 같이 쓰는 편이 좋을지도 모르겠네요 3 처음 쓸 때보다 상당히 깔끔했습니다.defmodule Problem5 do
def gcd(x, 0), do: x
def gcd(x, y), do: gcd(y, rem(x, y))
def solve(max, lcm, max), do: lcm
def solve(n, lcm, max) do
lcm_next = div(n * lcm, gcd(n, lcm))
solve(n+1, lcm_next, max)
end
end
더 추가
코멘트에서 지적을 받았습니다만, 지금의대로라고
Problem5.solve(2, 1, 11)
의 계산 결과가 다릅니다군요···. 코멘트에서는 수정판도 가르쳐 주시고 있습니다만, 일단 기사 본문에도 수정판을 써 둡니다.defmodule Problem5 do
def gcd(x, 0), do: x
def gcd(x, y), do: gcd(y, rem(x, y))
def solve(max), do: solve(2, 1, max)
def solve(max, lcm, max), do: div(max * lcm, gcd(max, lcm))
def solve(n, lcm, max) do
lcm_next = div(n * lcm, gcd(n, lcm))
solve(n+1, lcm_next, max)
end
end
수수함에
solve/1
도 추가하고 있습니다. 이렇게하면,IO.puts Problem5.solve(10) # 2520
IO.puts Problem5.solve(11) # 27720
IO.puts Problem5.solve(20) # 232792560
등으로 쓸 수 있습니다. 이것도 코멘트에서 가르쳐 주신 것입니다. mhgp 씨, 고마워요!
C 언어 입문 - 입력한 두 자연수의 최소 공배수 구하기 - Webkaru ↩
참고: 재귀 버전 유클리드 호제법 ¦ ↩
참고: The Pragmatic Bookshelf | Programming Elixir ¦ ↩
Reference
이 문제에 관하여(Project Euler의 Smallest multiple을 Elixir로 풀기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/y-temp4/items/865b17837a4fb9eaf86f텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)