본문 바로가기

전체 글

오일러 프로젝트 19 (Julia) 이번 문제는 20세기에서 매 월의 1일이 일요일인 날의 수를 구하는 문제이다. 하루씩 날짜를 더해가면서 계산하는 방법도 있으나, 다른 블로그에서 소개한 적도 많으므로 간단히 Dates 모듈을 사용해서 푸는 방법을 알아보겠다. Dates 모듈은 날짜와 관련한 자료형과 함수를 제공한다. 기본적으로 Date를 사용해서 날짜 데이터를 만들 수 있다. Date에는 "yyyy-mm-dd" 형식으로 된 문자열을 넘겨줄 수도 있고 년, 월, 일을 정수로 각각 넘겨주는 것도 가능하다. Dates.dayofweek() 함수는 주어진 날짜의 요일을 찾는다. 월요일=1, 화요일=2... 이런 식으로 매칭되어 있으므로 일요일은 7이다. 사실 줄리아의 요일 구성이 ISO 표준에 잘 들어맞는데, 요일 관련해서는 언어마다 규격이 다.. 더보기
오일러 프로젝트 18 (Julia) 숫자로 쌓아올린 삼각형에서 내려가면서 인접한 숫자와 더한 값이 최대가 되는 경우를 구하는 문제. 위에서부터 각각의 가능한 경로를 계산하는 식으로 구하면 모든 가능한 경로를 더해야 한다. 각 위치에서 더할 값은 2가지 경우가 있기 때문에 n 줄이 있는 경우에 2^n 만큼의 가능한 경우가 있다. 물론, 이 문제는 줄의 수가 적은 편이라 모든 가능한 경우를 다 더해도 상관없다. lines = [[1], [2, 3], [4, 5, 6]] 과 같은 값이 있을 때 2에서 더할 수 있는 다음 값은 다음 번 라인의 같은 위치에 있는 값 4와, 그 오른쪽에 있는 값 5이다. 이런 식으로 더해나가서 더 큰 값을 취하도록하는 계산은 재귀를 통해서 구현할 수 있다. s = """ 75 95 64 17 47 82 18 35 8.. 더보기
오일러 프로젝트 17 (Julia) 숫자를 영어로 읽기 영어에서 숫자는 110까지가 아닌 119까지가 별개의 이름으로 정해져 있다. 20~99까지는 10의 자리를 표현하는 단어와 1의 자리를 표현하는 단어를 결합하여 표시한다. (twenty one, forty five...) 100의 경우 1의 자리에 대한 단어 + hundred 로 쓰이며, 100 이하의 자리에 값이 있는 경우에는 and를 쓴다. 참고로 hundred는 항상 단수형으로만 쓰인다. 따라서 각 경우는 다음과 같다. 1000인 경우에는 "one thousand"이다. 100으로 나눈 몫 + "hundred", 100으로 나눈 몫이 없으면 생략 100으로 나눈 몫이 0보다 크고 나머지가 있는 경우 "and" 추가 100으로 나눈 나머지가 20 이상인 경우, 10으로 나눈 몫과 .. 더보기
오일러 프로젝트 16 (Julia) 2의 1000제곱의 각 자리 수를 더한 값을 구하는 문제이다. 파이프 연산을 사용해서 각 함수에 순서대로 전달하면 되는 정직한 문제. @time big(2)^1000 |> digits |> sum |> println 더보기
오일러 프로젝트 15번 (Julia) 가로 3, 세로 2인 격자를 지나는 경로에서 모든 가로방향 선분을 h, 세로 방향 선분을 v라하면, 가능한 모든 경로는 h 3개와 v 2개로 이루어진 순열이된다. 예를 들어 hhhvv, hvhvh 등으로 표기할 수 있는 것이다. h끼리, v끼리는 순서가 없으므로 이 때 경로의 개수는 5!/(3! * 2!) 이 된다. 가로 20, 세로 20인 경우에는 40!/20!/20! 을 계산하면 된다. 정수를 큰 수로 변환하는 big()과 팩토리얼을 구하는 factorial()을 합성하고, 나눗셈으로 리듀스하면 된다. 참고로 큰수를 정수형식으로 표시하기 위해서는 Integer()로 정수로 다시 변환해주는 과정이 필요하다. @time let f = factorial ∘ big reduce(/, [40, 20, 20] .. 더보기
오일러 프로젝트 14번 (Julia) 우박수를 찾는 문제이다. 주어진 정수 n에 대해서 1까지 이르는 단계를 세는 함수를 만들고 1백만 이하에 대해서 모두 시행하여 가장 큰 값이 나오는 값을 찾으면 된다. (우박수열길이, 값)의 튜플을 생성하고 가장 큰 값을 찾으면 간단하다. 다른 언어에서는 속도를 높이기 위해서 메모이제이션 등의 기법을 동원했는데, 줄리아는 그런 거 필요 없고 그냥 돌려도 빠르게 계산된다. function h(n) c = 1 while n > 1 n, c = iseven(n) ? n ÷ 2 : 3n + 1, c + 1 end return c end @time [(h(x), x) for x=1:100_0000] |> maximum |> last |> println 더보기
오일러 프로젝트 13번 (Julia) 큰수들의 덧셈은 BigInt 타입을 통해서 수행할 수 있다. 워낙 간단한 코드이기 때문에 문제의 숫자들을 텍스트 파일로 저장했다 가정하고 파일을 읽어서 처리하는 식으로 작성했다. 파일을 문자열로 읽어들여서 공백(개행문자)기준으로 쪼개고, 쪼갠 조각을 각각 BigInt 타입으로 변환한다. 이를 모두 합한 값을 문자열에 내삽하고 앞에서부터 10자를 출력하면 끝. @time let xs = read("s013.txt", String) |> split .|> x -> parse(BigInt, x) "$(sum(xs))"[1:10] |> println end 더보기
오일러 프로젝트 12번 (Julia) 500개 이상의 약수를 갖는 삼각수 삼각수는 1부터 n까지의 합으로 구성되는 수이다. 1부터 n까지의 합은 간단한 공식 (n * (n + 1) / 2)으로 구할 수 있으므로 각 삼각수를 구하고, 그 삼각수의 약수의 개수가 500개 이상인지를 판단하면 된다. 어떤 정수 n이 p로 나눠진다면 그 몫인 q 역시 n의 약수가 된다. 따라서 n은 그 제곱근범위 이내에서 나눠보고 약수가 있다면 2씩 더해보면 된다. function numdivs(n) l = Int(floor(sqrt(n) + 0.5)) # n이 완전제곱수이면 약수의 개수는 홀수가 된다. s = l^2 == n ? 1 : 2 i = 2 while i < l n % i == 0 && (s += 2) i += 1 end return s end let n.. 더보기