본문 바로가기

Julia

프로젝트 오일러 1번 (Julia)

프로젝트 오일러 1번 문제 풀이

10보다 작은 자연수 중에서 3또는 5의 배수는 3, 5, 6, 9이고, 이것을 모두 더하면 23입니다. 1000보다 작은 자연수 중에서 3또는 5의 배수를 모두 더하면 얼마일까요?

루프를 돌면서 3또는 5의 배수인지를 검사하고 그 때마다 결과값에 해당 값을 더하는 방식으로 계산할 수 있는 간단한 문제이다. 다만, 줄리아에서도 파이썬과 같이 리스트 축약을 사용할 수 있으므로 보다 간단하게 작성할 수 있다. 파이썬과 마찬가지로 [ ... ] 으로 둘러싼 축약 표현식은 배열로 생성되는데, 괄호속에 작성하는 경우에는 제너레이터 표현식으로 평가된다. 본 문제에서는 배열이나 제너레이터이나 아무런 차이가 없으므로 괄호속에 작성하면 되겠다. 또한 단순 정수 범위에 대해서는 for x in ... 표현 외에 for x=start:end의 표현을 써도 좋다.

3의 배수의 판정은 3으로 나눈 나머지가 0이되는지를 보면된다. 나머지를 구하기 위한 연산자는 % 을 사용하며, 논리 합(OR)은 || 연산자를 쓴다.

출력을 위해서는 println() 함수를 사용하는데, 중첩된 괄호를 피하기 위해서 |> 파이프 연산자를 사용하여 작성할 수 있다. 풀이는 다음과 같다.

@time sum(x for x=1:999 if x % 3 == 0 || x % 5 == 0) |> println

집합을 이용한 풀이

전통적인 루프외에도 집합을 사용하여 접근하는 방법도 소개한다. 1000미만의 모든 3의 배수는 3, 6, 9, .. 와 같이 3부터 3씩 커지는 모든 수이며, 5의 배수는 마찬가지로 5부터 시작하여 5씩 커지는 수이다. 이는 줄리아에서 Range를 사용해서 쉽게 표현할 수 있다.

Range는 파이썬 슬라이스와 비슷한데, 중간에 커지는 step 값이 가운데 적힌다는 차이가 있으며, 항상 end 값이 포함된다. 예를 들어 1부터 1000까지의 모든 정수는 1:1000으로 표현한다. 3부터 1000까지의 모든 정수는 3:3:1000으로 표현할 수 있다. 이 범위값을 Set()에 넘겨주면 해당 정수들로 된 집합을 생성할 수 있다.

문제는 1000이하의 3의 배수의 집합과 5의 배수의 집합의 합집합을 구하고 그 합집합의 모든 원소를 합하는 것이다. 합집합을 구하는 함수는 union()인데, 간단히 연산자로도 구할 수 있다. (이 연산자는 \cup이라 입력하고 탭 키를 누르면 변환된다.) 이 방식은 루프를 돌지도 않고 매 정수를 나눗셈하여 배수여부를 체크할 필요도 없으므로 훨씬 더 (10배이상) 빠르게 계산된다.

@time (Set(3:3:999) ∪ Set(5:5:999)) |> sum |> println