본문 바로가기

전체 글

오일러 프로젝트 27 (Julia) 어떤 2차식이 있을 때, 이 이차식에 정수값을 대입했을 때 그 결과가 소수가 된다면, 소수의 개수가 가장 많은 2차식을 구하는 문제이다. 2차식의 그래프는 포물선이며, 포물선은 좌우 대칭이다. 포물선의 식을 (n - v)^2 + w 의 모양으로 정리했을 때, n = v 를 중심으로 소수가 분포하도록 하고 n = 0 ~ v 까지 최대한 소수가 되는 것이 유리하다. 따라서 n^2 an + b 에서 a는 음수 b는 -2a보다 큰 양수가 되는 제약 조건을 걸면 오래 걸리지 않는다. a, b가 주어질 때,0부터 몇 개의 소수가 나오는지를 체크한다. using Primes function test(a, b) f(x) = x^2 + a*x + b c, i = 0, 0 while true isprime(f(i)) ||.. 더보기
오일러 프로젝트 26 (Julia) 1000 이하의 자연수에서 그 역수가 순환소수가 될 때, 순환마디가 가장 긴 값을 찾는 문제이다. 분수를 소수로 표현하려면 실제로 나눗셈을 계산해야 한다. 매 자리에서 몫과 나머지가 나오는데, 나머지에 10을 곱하고 그 아랫자리를 더하면 다음 번 나누는 수(피제수)가 된다. 피제수가 같다면 몫과 나머지가 같을 것이므로, 같은 몫이 나올 때 까지의 구간의 길이를 구하면 된다. function process(n) d = 1 m = [] while true q, r = divrem(d, n) d in m && break push!(m, d) d == 0 && return 0 d = r * 10 end return length(m) end function main() 3:2:1000 .|> (x -> (proc.. 더보기
오일러 프로젝트 25 (Julia) 1, 1, 2, 3, ... 으로 시작하는 피보나치 수열에서 1000자리가 처음으로 되는 것은 몇 번째 항인지를 구하는 문제이다. 어떤 정수가 몇 자리가 되는지를 보려면 log10() 값의 정수값 - 1 이 되는 것을 활용한다. 피보나치 수열은 채널을 사용한 제너레이터를 사용하면 쉽게 구할 수 있다. # 제너레이터 function main() fib = Channel() do ch a, b = big(1), big(1) while true put!(ch, a) a, b = b, a + b end end for (i, f) in enumerate(Channel(fib)) log10(f) > 999 && (println(i); break) end end main() @async를 사용하면 훨씬 더 빨리 결과.. 더보기
오일러 프로젝트 24 (Julia) 0,1,2,3,4,5,6,7,8,9로 만들 수 있는 1백만 번째의 사전식 순열을 구하는 문제이다. n개의 요소에 대해 만들 수 있는 순열의 가지수는 n! 가지이다. 10개의 숫자로 순열을 만들 때, 첫자리를 0으로 정했다면 9! 가지의 순열을 생성할 수 있다. 따라서 999,999를 9!로 나눈 몫이 첫 번째 숫자가 될 것이다. 그 나머지에 대해서도 동일하게 8!로 나눠서 두 번째 숫자를 정할 수 있다. 이 과정을 반복하여 나머지가 더 이상 남지 않을 때까지 반복하면 1백만번째 순열을 구할 수 있다. 이 때 백만이 아니라 999,999를 한계값으로 사용하는 것은 0123456789가 0번째에 해당하기 때문이다. 이를 일반화하여 집합에서 n번째 순열을 구하는 방법을 다음과 같이 구할 수 있다. functi.. 더보기
오일러 프로젝트 23 (Julia) 어떤 N이 두 초과수의 합으로 표현가능할지를 살펴보는 문제. 유한한 크기의 초과수의 집합이 있다면, 해당 집합의 임의의 원소 e 에 대허서 N - e 가 초과수 집합의 원소인지를 검사해본다. 만약 이 조건을 만족하는 e 가 하나라도 있다면 N은 초과수 2개의 합으로 나타낼 수 있는 수이다. 문제에서 주어진 한계값은 28123이므로 28123 보다 작은 모든 초과수의 집합을 만들고, 24(두 초과수의 합으로 나타낼 수 있는 가장 작은 수)부터 28123까지를 검사해서 초과수의 합으로 나타낼 수 없는 수의 합과 1...23의 합을 더하면 된다. 초과수인지를 검사하는 함수는 이전 문제들에서 사용했던 방식을 그대로 사용하면 되겠다. function isovernum(n::Int)::Bool s = 1 l = I.. 더보기
오일러 프로젝트 22 (Julia) 파일을 다운로드 받아 읽으면 "ABC","DEF",... 와 같은 식으로 이름이 저장되어 있다. 이들을 콤마를 기준으로 자르고 양쪽의 따옴표를 제거한다. 줄리아에서 낱개의 문자는 Char 타입이고, 이는 문자 코드값(정수)처럼 덧셈 뺄셈이 가능하다. 따라서 단어 점수를 매길 때에는 각 글자(Char)에서 'A'를 빼고 1을 더하면 된다. 단어를 각 문자의 배열로 변환하기 위해서는 collect()를 사용해야 한다. URL로부터 파일을 다운로드 받을 때에는 download() 함수를 사용하는데, 이 함수는 임시 파일을 생성한다. 만약 파일 이름을 지정하고 싶다면 두 번째 인자로 파일이름을 주면 된다. 참고로 파일을 계속 다운로드 받지 않기 위해서 파일 이름으로 파일의 존재 여부를 확인할 때에.. 더보기
오일러 프로젝트 21 (Julia) 10,000 이하의 모든 친화수를 찾는다. 친화수란 자기 자신을 제외한 약수의 합이 서로 같은 수이다. 참고로 완전수는 자기 자신을 제외한 약수의 합이 자신과 같은 수로, 완전수 자신은 친화수에서 제외되어야 한다. 먼저 자신을 제외한 약수의 합을 구하는 함수를 작성해보자. 대상이 되는 값은 10,000 이하의 값이므로 제곱근 이하의 범위에서 약수를 찾아서 더하면 되겠다. function divsum(n::Int)::Int s = 1 l = Int(floor(sqrt(n) + 0.5)) k = 2 while k 더보기
오일러 프로젝트 20 (Julia) 100!의 각 자리 숫자의 합을 구하는 문제이다. 100!은 엄청 큰 수이기 때문에 BigInt를 사용해야 한다. 그외에는 필요한 모든 과정이 내장함수로 제공되고 있으므로 이번 문제도 한줄에 풀 수 있다. 파이프를 사용해서 함수를 연결한 과정을 살펴보면 어떤식으로 진행되는지 깔끔하게 로직이 드러나보인다. 100 |> big |> factorial |> digits |> sum |> println 더보기