# rust-eratos An implementation of 'Sieve of Eratosthenes' for rust language practice. ## Usage ``` cargo install rust-eratos rust-eratos 11 ``` - - - # Rust 언어에 적응하기 ## 이 문서의 목표 - Rust 언어에 대한 기본적인 이해를 마친 초심자에게 - 언어를 직접 사용하며 몸에 익히고 적응하는데 도움을 주고자 - 가볍게 따라할 수 있는 작은 목표들을 단계적으로 제공한다. ## 사전 지식 - Rust 언어의 기본 문법을 대략적으로 알고 있거나 쉽게 찾아볼 수 있어야 한다. - 혹시나 처음이라면 취향에 맞는 것으로 준비한다. - 짧지만 맛보기는 가능한 마소 런 튜토리얼 [Rust First Steps](https://docs.microsoft.com/ko-kr/learn/paths/rust-first-steps/) - 길지만 훌륭한 공식 커뮤니티 튜토리얼 [The Rust Programming Language](https://doc.rust-lang.org/book/) - 온라인 강의 [Exercism: Rust Track](https://exercism.org/tracks/rust) - 유툽 강의 [YouTube: mithradates](https://www.youtube.com/user/mithradates/videos) - 소수(prime number)를 판별하는 간단한 알고리즘 지식이 필요하다. - 미리 학습할 필요는 없고, 따라하면서 필요한 내용을 찾아본다. [소수 (수론)](https://ko.wikipedia.org/wiki/%EC%86%8C%EC%88%98_(%EC%88%98%EB%A1%A0)) ## 지금 단계에서 집중해야 할 것 - 기본 문법을 완전히 습득하는 것 - primitive types, variable, if, match, for, println!, fn, ... - 기본 자료구조들에 익숙해지는 것 - array, slice, String, Vec, HashMap, tuple, ... - 언어 공통적 요소를 사용해보는 것 - struct, enum, trait, iterator, ... - 언어 특수한 요소를 경험하고 이해하는 것 - ownership, borrow, reference, macros, ... - 언어 생태계를 경험하는 것 - cargo, crates, ... - 이번 따라하기에서 위의 것들을 전부 사용해보는 것은 아님 ## 지금은 집중하지 않을 것 - 알고리즘의 개선 - 특정 프레임워크의 사용 방법 - 언어와 생태계의 고급 기능들 - generic, polymorphism, thread, future, async, cargo workspace, ... ## 따라하기 - 제시된 함수의 내용을 구현한다. - 만약 알고리즘을 잘 이해하지 못하겠고 생각하기도 귀찮다면, 문서 하단의 예시 코드를 적절하게 포팅하는 방식으로 따라한다. - 제공된 인터페이스들은 입력 받은 수 n을 포함하지 않는 결과를 리턴하도록 의도하였으나, 포함시켜도 무관하다. 다만 일관된 동작으로 작성한다. ### *n* 이 소수인지 판별하기 ```rust fn is_prime_number(n: u32) -> bool ``` - 혹시 if, for 명령들로만 구현했다면 match, range, iter, any 등을 이용한 표현으로 구현해본다. ### *n* 미만의 소수의 수를 구하기 ```rust fn get_prime_number_count_below(n: u32) -> usize ``` - 혹시 if, for 명령들로만 구현했다면 match, range, iter, filter, count 등을 이용한 표현으로 구현해본다. - filter를 사용했다면 앞에서 사용했던 any의 것과 비교하여 타입의 차이와 그 이유를 알아본다. - hint: Iterator::next(&mut self) vs new iterator ### *n* 미만의 가장 큰 소수를 구하기 ```rust fn get_largest_prime_number_below(n: u32) -> u32 ``` - 혹시 if, for 명령들로만 구현했다면 match, range, iter, find, Option<T> 등을 이용한 표현으로 구현해본다. - find를 사용했다면 앞에서 사용했던 any, filter들과 비교하여 타입의 차이와 그 이유를 알아본다. ### *n* 미만의 소수들을 구하기 ```rust fn get_prime_numbers_below(n: u32) -> Vec ``` - 에라토스테네스의 체 알고리즘을 구현한다. - 기본 자료구조 중 Vec을 사용하여 구현해본다. - 혹시 if, for 명령들로만 구현했다면 range, into_iter, filter, collect 등을 이용한 표현으로 구현해본다. ### *n*을 커맨드 라인 입력을 정수로 변환하기 ```rust fn parse_args(args: &[String]) -> Result ``` - 커맨드 라인으로 입력받은 문자열을 정수로 변환한다. - 정수 변환 결과와 오류를 Result<T, E> 를 이용하여 적절하게 반환하고 처리해본다. ### 작성한 기능들로 stdout에 출력하기 ``` # output example > rust-eratos 13 13 is a prime number. There are 5 prime numbers less than 13, and the largest number is 11. Prime numbers less than 13. [2, 3, 5, 7, 11] ``` ### 더 해보기 - 유닛 테스트 작성하기 - 구현된 기능들을 라이브러리로 만들기 - 계산된 결과를 캐싱하여 성능 개선하기 - 코드의 실행 속도를 프로파일하고 개선하기 - {2, 3, 5} 휠 인수분해 알고리즘 적용하기 - Wheel factorization [Link](https://en.wikipedia.org/wiki/Wheel_factorization), [more](https://primes.utm.edu/glossary/page.php?sort=WheelFactorization) ## 예시 코드 ```python # python import sys def is_prime_number(n): if n < 2: return False for i in range(2, int(n ** 0.5) + 1): # (n ** 0.5) == (math.sqrt(n)) if n % i == 0: return False return True def get_prime_number_count_below(n): if n < 3: return 0 count = 0 for i in range(2, n): if is_prime_number(i): count += 1 return count def get_largest_prime_number_below(n): for i in reversed(range(2, n)): if is_prime_number(i): return i return 0 def get_prime_numbers_below(n): # sieve = [0, 0] + [i for i in range(2, n)] sieve = [0, 0] for i in range(2, n): sieve.append(i) for i in range(2, int(len(sieve) ** 0.5) + 1): if sieve[i] <= 0: continue index = i * i while index < len(sieve): sieve[index] = 0 index += i primes = [] for i in range(2, len(sieve)): if sieve[i] > 0: primes.append(i) return primes # return [i for i in range(2, len(sieve)) if sieve[i] > 0] def main(n): print(f"{n} is a prime number.") print(f"There are {get_prime_number_count_below(n)} prime numbers less than {n}," f" and the largest number is {get_largest_prime_number_below(n)}") print(f"Prime numbers less than {n}") print(get_prime_numbers_below(n)) if __name__ == "__main__": main(int(sys.argv[1])) ```