rust-eratos 0.1.1

An implementation of 'Sieve of Eratosthenes' for rust language practice.
Documentation
# 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<u32>
```

- 에라토스테네스의 체 알고리즘을 구현한다.
- 기본 자료구조 중 Vec을 사용하여 구현해본다.
- 혹시 if, for 명령들로만 구현했다면 range, into_iter, filter, collect 등을 이용한 표현으로 구현해본다.

### *n*을 커맨드 라인 입력을 정수로 변환하기
```rust
fn parse_args(args: &[String]) -> Result<u32, &'static str>
```

- 커맨드 라인으로 입력받은 문자열을 정수로 변환한다.
- 정수 변환 결과와 오류를 Result&lt;T, E&gt; 를 이용하여 적절하게 반환하고 처리해본다.

### 작성한 기능들로 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]))

```