# Rust-Lang으로 알고리즘 문제 풀기 (기초 다지기)

- Author: @baealex
- Published: 2020-03-07
- Updated: 2020-03-10
- Source: http://blex.me/@baealex/%EB%9F%AC%EC%8A%A4%ED%8A%B8%EB%A1%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%AC%B8%EC%A0%9C-%ED%92%80%EA%B8%B0-%EB%B0%B1%EC%A4%80-1330-5543-1
- Tags: 프로그래밍, 러스트

---

![](https://static.blex.me/images/content/2020/3/6/S7aQtmtbLZ44EofMfAg0.png)

> 2019-12-10에 작성한 러스트와 관련된 첫 글인데 이번이 두번째 쓰는 글이다. 2-3일은 무슨... 3달이 훌쩍 지나버렸다.

<br>

<video autoplay muted loop><source src="https://static.blex.me/images/content/2020/3/6/2KaTZCwYBtf5aw2Yi4qK.mp4" type="video/mp4" /></video>

<br>

맨날 '해야지 해야지' 하면서 '해야지'만 맨날 하는중이다. 정말 너란 녀석... 이제는 진짜 *해야지!* 진짜 진짜 스스로와의 약속을 하겠다. 죽이되든 밥이되는 무엇이건 러스트를 이용해서 해결할 것이다. 함수형과 러스트에 익숙해지기 위해서 2일에 하나씩 30일간 15개의 개시글을 꼭 올린다! 차후엔 러스트를 이용해서 실사용 가능한 서비스를 만들고 싶다. 기존것을 러스트로 바꿔보던지. 이유는 없다 그냥 재밌어 보이기 때문에 도전하는 것이다!

<br>

#### 두 수 비교하기

- https://www.acmicpc.net/problem/1330

첫째 줄에 다음 세 가지 중 하나를 출력한다.

- A가 B보다 큰 경우에는 '>'를 출력한다.
- A가 B보다 작은 경우에는 '<'를 출력한다.
- A와 B가 같은 경우에는 '=='를 출력한다.

입력과 비교, 출력을 수행하는 아주 기초적이면서 훌륭한 문제라고 생각한다.

```rust
use std::io;

fn main() {
    let mut input_number = String::new();

    io::stdin().read_line(&mut input_number)
        .expect("Falied to read line");
}
```

입력은 위와같이 받았던 걸로 기억하는데 스플릿은 어떻게 하는거지?

![](https://static.blex.me/images/content/2020/3/6/Y6ziy8i5P8CQdH9Oihi8.png)

![](https://static.blex.me/images/content/2020/3/6/Mn4ewguZRRVZpm3PgD4F.jpeg)

```rust
let split_input_number = input_number.split(' ');
for number in split_input_number {
    println!("{}", number);
}
```

문서가 어려워 보였던거지 사실은 일반적인 언어들과 비슷하게 위와같이 잘라낼 수 있다. 다만 참고한 스택오버플로에선 `mut`로 선언하였는데 컴파일시 `mut`로 선언한 것이 위험하다고 알려줬다. 하긴 스플릿된 변수를 굳이 `mut`로 선언할 필요는 없어보이긴 한다.

```rust
use std::io;

fn main() {
    let mut input_number = String::new();

    io::stdin().read_line(&mut input_number)
        .expect("Falied to read line");

    let split_input_number = input_number.split(' ');
    for number in split_input_number {
        println!("{}", number);
    }
}
```

```
45 21
45
21
```

이제 위와같이 두개의 숫자를 분할하였으니 비교를 진행하자.

<br><br><br><br><br>

잠깐...

<br><br><br><br><br>

<video autoplay muted loop><source src="https://static.blex.me/images/content/2020/3/7/fz8x9FwK7BpPY1gZ3Ysf.mp4" type="video/mp4" /></video>

`split_input_number`에 어떻게... 접근하는 거지...

```rust
use std::io;

fn main() {
    let mut input_number = String::new();

    io::stdin().read_line(&mut input_number)
        .expect("Falied to read line");

    let strings: Vec<&str> = input_number.split_whitespace().collect();
    println!("{:?}", strings);
}
```

```
45 21
["45", "21"]
```

스플릿한 결과가 `iterator`를 반환하므로 아까 위와같이 `for i in items`로 사용한 거였다. 이걸 배열로 받으려면 위와같이 `collect`를 사용해서 얻어야 한다고 설명한다. 이제 형변환을 해줘야 할 차례!

```rust
use std::io;

fn main() {
    let mut input_number = String::new();

    io::stdin().read_line(&mut input_number)
        .expect("Falied to read line");

    let numbers: Vec<&str> = input_number.split_whitespace().collect();

    let number_a = match numbers[0].parse::<i32>() {
        Ok(i) => i,
        Err(_e) => {
            -1
        }
    };
    let number_b = match numbers[1].parse::<i32>() {
        Ok(i) => i,
        Err(_e) => {
            -1
        }
    };
    println!("{}", number_a);
    println!("{}", number_b);
}
```

이제 비교만 해주면 끝이구나...

```rust
use std::io;
use std::cmp::Ordering;

fn main() {
    let mut input_number = String::new();

    io::stdin().read_line(&mut input_number)
        .expect("Falied to read line");

    let numbers: Vec<&str> = input_number.split_whitespace().collect();

    let number_a = match numbers[0].parse::<i32>() {
        Ok(i) => i,
        Err(_e) => {
            -1
        }
    };
    let number_b = match numbers[1].parse::<i32>() {
        Ok(i) => i,
        Err(_e) => {
            -1
        }
    };
    match number_a.cmp(&number_b) {
        Ordering::Less      => println!("<"),
        Ordering::Greater   => println!(">"),
        Ordering::Equal     => {
            println!("==");
        },
    }
}
```

![](https://static.blex.me/images/content/2020/3/7/H5BvVqfzksZJvkpfu4OJ.png)

<video autoplay muted loop><source src="https://static.blex.me/images/content/2020/3/7/E5Ag1GJN5aHD3VJy21DI.mp4" type="video/mp4" /></video>

난생처음 러스트로 문제를 풀어보았다. 문법 적응이 너무 안된다. 한문제를 더 풀어보자.

<br>

#### 상근날드

- https://www.acmicpc.net/problem/5543

가장 적응이 안되는 문법은 `cmp`와 `Ordering`이다. 러스트에는 `if`문이 없는건가?

- https://doc.rust-lang.org/rust-by-example/index.html

를 찾다가 위와같이 문법이 정리된 페이지를 발견했다. 싹 정리 되있어서 찾아보고 싶은건 금방 찾아볼 수 있겠다. 여하지간 `if/else`님께서도 아주 잘 계셨다. 왜 튜토리얼에선 `if/else`가 아닌 `cmp`와 `Ordering`을 먼저 알려준;

여하지간 상근날드라는 문제는 5개의 입력을 받는데 3개는 햄버거 가격이고 2개는 음료수 가격이다 각각 물건중 저렴한 물건을 구매하여 합산한 가격에 50원을 빼는 문제다. 배열과 반복문 조건문을 활용해야 하는 간단한 문제다.

```rust
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;
}
```

정수 입력 받는게 귀찮아서 위와같이 함수로 만들었다.

```rust
fn main() {
    let mut menus: [i32; 5] = Default::default();

    let mut optional = Some(0);
    while let Some(i) = optional {
        if i < menus.len() {
            optional = Some(i + 1);
            menus[i] = input_int()
        } else {
            optional = None;
        }
    }
    let bergers = &menus[0 .. 3];
    let drinks = &menus[3 .. 5];

    println!("{:?}", bergers);
    println!("{:?}", drinks);
}
```

진입점에선 위와같이 루프를 돌리며 메뉴 배열에 값을 채우고 버거와 음료를 나눠주었다. 이제 이걸 정렬해서 앞에것만 가져오려고 하였더만 정렬을 사용하려면 백터로 선언하는게 일반적인 것 같다.

```rust
let mut bergers = vec![&menus[3 .. 5]];
bergers[0].sort(); // Error

let mut bergers = Vec::new();
bergers.extend(&mut menus[0 .. 3].iter().cloned());
bergers.sort();
```

백터를 생성하면서 `munus`를 넣어주려 했더니 2차원 배열로 만들어지고 정렬하려고 시도하자 `mut` 변수가 아니라고 오류를 뿜어냈다. 그래서 위와같이 작성하였다.

```rust
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 main() {
    let mut menus: [i32; 5] = Default::default();

    let mut optional = Some(0);
    while let Some(i) = optional {
        if i < menus.len() {
            optional = Some(i + 1);
            menus[i] = input_int()
        } else {
            optional = None;
        }
    }

    let mut bergers = Vec::new();
    bergers.extend(&mut menus[0 .. 3].iter().cloned());
    bergers.sort();

    let mut drinks = Vec::new();
    drinks.extend(&mut menus[3 .. 5].iter().cloned());
    drinks.sort();

    println!("{:?}", bergers[0] + drinks[0] - 50);
}
```

![](https://static.blex.me/images/content/2020/3/7/38x2udWbe61Yq7Vj7sp2.png)

파이썬이면 5줄이면 짤 코드가 이렇게 길어지니 왠지 바보가 된 느낌이다. 이 또한 문법이 익숙해 지면서 차차 나아질 것이라 생각된다. 오늘은 러스트의 기본기(?)를 다졌으니 다음에는 파이썬으로 풀었던 코드를 러스트로 바꿔보는 시도를 해봐야겠다.
