Rust-Lang으로 알고리즘 문제 풀기 (K번째 소수)

'러스트 박살내기(?)' 시리즈Rust-Lang으로 알고리즘 문제 풀기 (K번째 소수)

baealex

소비적인 일보단 생산적인 일을 좋아합니다.

Sign in to view email

저번에는 기초적인 문제로 기초적인 문법을 다뤘으니 이번엔 파이썬으로 작성한 코드중에 뭔가를 러스트로 변환해 보고자 하였다. 2가지 정도를 변환해 볼 것인데 이번에는 백준에서 무려 25점을 받았던 (...)


"개발자 능력 실화?"


K번째 소수라는 문제의 파이썬 코드를 러스트로 변환해 볼 것이다. 이 코드를 변환하는 이유는 필자의 궁금증을 해결하기 위함이다. 파이썬이기 때문에 25점을 받은건지, 아니면 내가 똥멍청인지. 일단 이 코드는 파이썬의 내부 함수가 아닌 기초적인 로직들이 들어있으므로 "기초 다지기 - 2" 정도의 포스트가 될 것이다.


K 번째 소수 — 파이썬

import math

def prime_of_number(K):
    if K == 0:
        return None
    prime_lists = list()
    counter = 0
    x = 2
    while True:
        is_prime = True
        for y in prime_lists:
            if y > math.sqrt(x):
                break
            if x % y == 0:
                is_prime = False
                break
        if is_prime:
            prime_lists.append(x)
            counter += 1
            if counter >= K:
                return prime_lists[counter - 1]
        x += 1

if __name__=='__main__':
    print(prime_of_number(int(input())))

위 코드를 고대로 러스트로 변경해 볼 것이다. 처음엔 코드가 술술 작성되서 "오? 역시 난 천재였나?" 싶었으나 온갖 오류가 발생하여 고치느라 진땀을 흘렸다. 발생했던 오류들과 해결하는 방법을 아래에 작성하였다.


cannot infer type for type parameter `T`
  • 벡터에 타입이 존재하지 않는다는 에러로 이전 포스트에서 '상근날드'라는 문제를 풀이할 때는 벡터의 형태를 지정하지 않아서 이번에도 똑같이 했더니 발생한 오류다. 벡터를 선언할 때 let mut m_vec: Vec<T> = Vec::new()로 하면 해결된다.


no method named `sqrt` found for type `i32` in the current scope
  • 구글에 검색하였더니 var.sqrt()로 제곱근을 구하길래 똑같이 따라했더니 발생한 오류였는데 i32에는 sqrt()라는 함수가 존재하지 않는다. 따라서 실수로 형태를 변환하고 제곱근을 구하였다. 그리고 실수와 정수를 비교할 수 없다는 오류도 있었는데... 러스트가 정적 타입의 언어라는 걸 자꾸 망각하는 듯 하다. 비교되는 값도 실수형으로 변환하고 값을 비교해 주었다. 형변환은 무조건 parsematch를 써야하는 줄 알았는데 var as Type으로 변환이 가능했다. 나중에 더 알아봐야 할 듯.


value moved here, in previous iteration of loop
  • 벡터를 반복문의 iterator로 넣었더니 발생한 오류였다. for문에 들어가는 벡터의 이름앞에 &를 표시하는 것으로 오류를 해결하였다.


cannot cast `&i32` as `f32`
  • for문의 iterator로 들어온 y라는 변수가 &i32라서 f32로 형변환이 안된다는 오류로 여러 게시글을 찾아보다가 C언어와 마찬가지로 *&를 교차하는 방식으로 사용하길래 이걸 힌트로 해결할 수 있었다. 다만 러스트에서 *&가 무엇을 의미하는지 잘 모르겠다. 메모리에 접근하려면 unsafe라는 키워드를 사용한다는 것으로 알고 있어서 메모리 관련된 건 아니라 생각했는데... 찾아봐야 할 것 같다.


K 번째 소수 — 러스트

use std::io;

fn input_int() -> i32 {
    let mut temp_str = String::new();
    io::stdin().read_line(&mut temp_str)
        .expect("Falied to read line");
    let result = match temp_str.trim().parse::<i32>() {
        Ok(i) => i,
        Err(_e) => {
            -1
        }
    };
    return result;
}

fn prime_of_number(_k: i32) -> i32 {
    if _k == 0 {
        return 0;
    }
    let mut prime_lists: Vec<i32> = Vec::new();
    let mut counter: i32 = 0;
    let mut x: i32 = 2;
    loop {
        let mut is_prime = true;
        for y in &prime_lists {
            let f_x = x as f32;
            let f_y = *y as f32;
            if f_y > f_x.sqrt() {
                break;
            }
            if x % y == 0 {
                is_prime = false;
                break;
            }
        }
        if is_prime {
            prime_lists.push(x);
            counter += 1;
            if counter >= _k {
                return prime_lists[prime_lists.len() - 1];
            }
        }
        x += 1;
    }
}

fn main() {
    println!("{}", prime_of_number(input_int()));
}

결과값 비교해보려고 파이썬과 러스트를 교차해서 실행했는데 파이썬에 값을 넣고 엔터를 치고 이후 러스트에 값 넣고 엔터를 쳤더니 러스트에서 결과가 먼저 나오는 걸 보고 굉장히 신기했다. 이대로라면 50점은 넘게 나오지 않을까!

예상외로 100점이 나와버렸다. 나는 똥멍청이가 아니었다!


'러스트 박살내기(?)' 시리즈
러스트... 부셔버리겠어! 🔥🔥🔥 는... 내가 박살나는 중... 😥😫
작성된 댓글이 없습니다!
로그인된 사용자만 댓글을 작성할 수 있습니다.