본문 바로가기

Julia

오일러 프로젝트 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 더보기
오일러 프로젝트 19 (Julia) 이번 문제는 20세기에서 매 월의 1일이 일요일인 날의 수를 구하는 문제이다. 하루씩 날짜를 더해가면서 계산하는 방법도 있으나, 다른 블로그에서 소개한 적도 많으므로 간단히 Dates 모듈을 사용해서 푸는 방법을 알아보겠다. Dates 모듈은 날짜와 관련한 자료형과 함수를 제공한다. 기본적으로 Date를 사용해서 날짜 데이터를 만들 수 있다. Date에는 "yyyy-mm-dd" 형식으로 된 문자열을 넘겨줄 수도 있고 년, 월, 일을 정수로 각각 넘겨주는 것도 가능하다. Dates.dayofweek() 함수는 주어진 날짜의 요일을 찾는다. 월요일=1, 화요일=2... 이런 식으로 매칭되어 있으므로 일요일은 7이다. 사실 줄리아의 요일 구성이 ISO 표준에 잘 들어맞는데, 요일 관련해서는 언어마다 규격이 다.. 더보기