#10-1 작은 프로젝트들

Pt J·2020년 8월 21일
0

[完] Rust Programming

목록 보기
13/41
post-thumbnail

이 시리즈는 Rust 공식문서를 통해 공부한 흔적임을 밝힙니다.

이번 포스팅은 약간 번외편이다.

🦀 Ferris | "피터피터피터어ㅓㅓㅓㅓ!"

Here are some exercises you should now be equipped to solve:

  • Given a list of integers, use a vector and return the mean (the average value), median (when sorted, the value in the middle position), and mode (the value that occurs most often; a hash map will be helpful here) of the list.
  • Convert strings to pig latin. The first consonant of each word is moved to the end of the word and “ay” is added, so “first” becomes “irst-fay.” Words that start with a vowel have “hay” added to the end instead (“apple” becomes “apple-hay”). Keep in mind the details about UTF-8 encoding!
  • Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company. For example, “Add Sally to Engineering” or “Add Amir to Sales.” Then let the user retrieve a list of all people in a department or all people in the company by department, sorted alphabetically.

🐧 Peter | "뭐야, 이 장황한 건... 그러니까 지금 나보고 이걸 구현해보라는 거지?"

그렇게 피터와 페리스는 이번에 Rust 공식문서에서 소개해준 작은 프로젝트를 진행하고 가기로 했다.

평균값, 중간값, 최빈값 구하기

🦀 Ferris | "먼저 임의의 정수 벡터에 대해서 평균값, 중간값, 최빈값을 구하는 문제야."

🐧 Peter | "벡터 참조를 인자로 받아 정수값을 반환하는 함수를 각각 구현하면 되려나?"

🦀 Ferris | "맞아, 그걸 구현하면 내가 정수 벡터를 준비할게!"

🐧 Peter | "... 어...그래...... 고맙다...ㅋ"

peter@hp-laptop:~/rust-practice/chapter08$ mkdir practice
peter@hp-laptop:~/rust-practice/chapter08$ cd practice/
peter@hp-laptop:~/rust-practice/chapter08/practice$ cargo new integer_vector
     Created binary (application) `integer_vector` package
peter@hp-laptop:~/rust-practice/chapter08/practice$ cd integer_vector/
peter@hp-laptop:~/rust-practice/chapter08/practice/integer_vector$ vi src/main.rs

src/main.rs

use std::collections::HashMap;

fn main() {
    let integers = vec![20, 17, 114, 24, 14, 170, 141, 67, 20, 4, 78, 404, 19, 67, 221, 67, 20];

    println!("mean: {}", match mean(&integers) {
        Some(result) => result.to_string(),
        None => "No Data".to_string(),
    });

    println!("median: {}", match median(&integers) {
        Some(result) => result.to_string(),
        None => "No Data".to_string(),
    });

    let m = mode(&integers);
    println!("mode:{}", {
        if m.len() == 0 {
            " No Data".to_string()
        } else {
            let mut temp = String::new();
            for i in m {
                temp = format!("{} {}", temp, i.to_string());
            }
            temp
        }
    });

}

fn mean(ints: &Vec<i32>) -> Option<f64> {
    if ints.len() == 0 {
        return None;
    }

    let mut result = 0;

    for i in ints {
        result += i;
    }

    Some(result as f64 / ints.len() as f64)
}

fn median(ints: &Vec<i32>) -> Option<i32> {
    if ints.len() == 0 {
        return None;
    }

    let mut sorted = ints.clone();
    sorted.sort();

    Some(sorted[ints.len()/2])
}

fn mode(ints: &Vec<i32>) -> Vec<i32> {
    if ints.len() == 0 {
        return vec![];
    }

    let mut result: Vec<i32> = Vec::new();
    let mut frequencies = HashMap::new();
    let mut max = 0;

    for i in ints {
        let count = frequencies.entry(i).or_insert(0);
        *count += 1;
    }

    for (_int, frequency) in &frequencies {
        if *frequency > max {
            max = *frequency;
        }
    }

    for (int, frequency) in &frequencies {
        if *frequency == max {
            result.push(**int);
        }
    }
  
    result
}
peter@hp-laptop:~/rust-practice/chapter08/practice/integer_vector$ cargo run
   Compiling integer_vector v0.1.0 (/home/peter/rust-practice/chapter08/practice/integer_vector)
    Finished dev [unoptimized + debuginfo] target(s) in 0.47s
     Running `target/debug/integer_vector`
mean: 86.29411764705883
median: 67
mode: 67 20
peter@hp-laptop:~/rust-practice/chapter08/practice/integer_vector$ 

🦀 Ferris | "비어 있는 벡터까지 고려했잖아?"

🐧 Peter | "너라면 분명 그런 벡터를 줄지도 모른다고 생각해버렸어. 최빈값은 여러 개가 있을 수 있다는 것도."

🦀 Ferris | "개선의 여지가 없다고 확신해?"

🐧 Peter | "그럴라가ㅋ 하지만 일단 현재의 내 실력으론... 여기까지."

피그 라틴

🦀 Ferris | "자, 다음은 피그 라틴이야. 여러 가지 바리에이션이 존재하지만 언급된 조건만 고려하도록 하자."

🐧 Peter | "우선 첫 글자가 모음인지 자음인지 구분하고, 이에 따라 변형을 가해야겠군?"

🦀 Ferris | "그렇지! Rust의 문자열은 인덱스를 사용할 수 없으며 UTF-8 형식으로 인코딩되어 저장된다는 걸 기억하라고."

peter@hp-laptop:~/rust-practice/chapter08/practice/integer_vector$ cd ..peter@hp-laptop:~/rust-practice/chapter08/practice$ cargo new pig_latin
     Created binary (application) `pig_latin` package
peter@hp-laptop:~/rust-practice/chapter08/practice$ cd pig_latin/
peter@hp-laptop:~/rust-practice/chapter08/practice/pig_latin$ vi src/main.rs

src/main.rs

use unicode_segmentation::UnicodeSegmentation;

fn main() {
    println!("first: {}", pig_latin(String::from("first")));
    println!("apple: {}", pig_latin(String::from("apple")));
}

fn pig_latin(origin: String) -> String {
    if origin.len() == 0 {
        return origin;
    }

    let origin = UnicodeSegmentation::graphemes(&origin[..], true)
        .collect::<Vec<&str>>();

    let mut temp = "";
    let mut result = String::new();

    for (i, ch) in origin.iter().enumerate() {
        if i == 0 {
            temp = ch;
        } else {
            result = result + ch;
        }
    }

    if temp == "a" || temp == "e" || temp == "i" || temp == "o" || temp == "u" {
        result = format!("{}{}-hay", temp, result);
    } else {
        result = format!("{}-{}ay", result, temp);
    }

    result
}
peter@hp-laptop:~/rust-practice/chapter08/practice/pig_latin$ cargo run
   Compiling pig_latin v0.1.0 (/home/peter/rust-practice/chapter08/practice/pig_latin)
    Finished dev [unoptimized + debuginfo] target(s) in 0.25s
     Running `target/debug/pig_latin`
first: irst-fay
apple: apple-hay
peter@hp-laptop:~/rust-practice/chapter08/practice/pig_latin$ 

🦀 Ferris | "외부 크레이트를 의존성 목록에 추가했구나?"

🐧 Peter | "그렇지ㅋ Cargo.tomlunicode-segmentation = "1.6.0"를 추가함으로써 문자열을 문자 단위로 쉽게 분할할 수 있겠더라고."

유사 데이터베이스

🐧 Peter | "다음은... 회사의 부서에 사원을 추가하는 작업?"

🦀 Ferris | "그리고 부서별 사원 리스트, 회사 전체 사원 리스트를 사전순으로 출력할 수 있어야 하지."

🐧 Peter | "일단 Add {employee} to {department} 구조로 입력된다는 걸 가지고 사원과 부서를 뽑아내야겠군... 잘못된 Query가 없다고 기대할게."

peter@hp-laptop:~/rust-practice/chapter08/practice/pig_latin$ cd ..
peter@hp-laptop:~/rust-practice/chapter08/practice$ cargo new company
     Created binary (application) `company` package
peter@hp-laptop:~/rust-practice/chapter08/practice$ cd company/
peter@hp-laptop:~/rust-practice/chapter08/practice/company$ vi src/main.rs

src/main.rs

use std::io;
use std::collections::HashMap;

fn main() {
    let mut company: HashMap<String, Vec<String>> = HashMap::new();

    println!("**************************************************************************");
    println!("* Type \"Add {{employee}} to {{department}}\" to insert                        *");
    println!("* Type \"{{department}}\" to retrieve a list of all people in the department *");
    println!("* Type \"Company\" to retrieve a list of all people in the company         *");
    println!("* Type \"Exit\" to exit this program                                       *");
    println!("**************************************************************************");

    loop {
        let mut query = String::new();
        let mut flag = false;

        println!("Type the query:");
        match io::stdin().read_line(&mut query) {
            Ok(_) => {
                if &query == "Exit\n" {
                    break;
                } else if &query == "Company\n" {
                    view_company(&company);
                    continue;
                } else {
                    for (dept, _) in &company {
                        if &query == dept {
                            view_department(&company, &query);
                            flag = true;
                            break;
                        }
                    }
                    if flag == false {
                        add_employee(&mut company, &query);
                    }
                    continue;
                }
            },
            Err(_) => {
                println!("Cannot read the line. Try again.");
                continue;
            }
        }
    }

    println!("Terminated...");
}

fn add_employee(company: &mut HashMap<String, Vec<String>>, query: &String) {
    let mut space = 0;
    let mut temp = 0;

    let mut employee = "";

    for (i, &item) in query.as_bytes().iter().enumerate() {
        if item == b' ' {
            space += 1;
            if space % 2 == 1 {
                temp = i+1;
            } else if space == 2 {
                employee = &query[temp..i+1];
            }
        }
    }
    let department = &query[temp..];

    if space == 0 {
        println!("Try again...");
        return;
    }
    insert_employee(company, employee, department);
}

fn insert_employee(company: &mut HashMap<String, Vec<String>>, employee: &str, department: &str) {
    let key = String::from(department);
    let value = String::from(employee);

    let data = company.entry(key)
        .or_insert({
            let temp = Vec::new();
            temp
        });

    data.push(value);
    data.sort();
}

fn view_department(company: &HashMap<String, Vec<String>>, department: &String) {
    let employees = company.get(department);

    match employees {
        Some(list) => { 
            for item in list {
                println!("{}", item);
            }
    },
        None => (),
    }

}

fn view_company(company: &HashMap<String, Vec<String>>) {
    let mut total: Vec<String> = Vec::new();

    for (_dept, list) in company {
        let mut temp = list.clone();
        total.append(&mut temp);
    }
    total.sort();

    for item in total {
        println!("{}", item);
    }
}
peter@hp-laptop:~/rust-practice/chapter08/practice/company$ cargo run
   Compiling company v0.1.0 (/home/peter/rust-practice/chapter08/practice/company)
    Finished dev [unoptimized + debuginfo] target(s) in 0.52s
     Running `target/debug/company`
**************************************************************************
* Type "Add {employee} to {department}" to insert                        *
* Type "{department}" to retrieve a list of all people in the department *
* Type "Company" to retrieve a list of all people in the company         *
* Type "Exit" to exit this program                                       *
**************************************************************************
Type the query:
Add Amir to Sales
Type the query:
Add Sally to Engineering
Type the query:
Company
Amir 
Sally 
Type the query:
Sales
Amir 
Type the query:
Engineering
Sally 
Type the query:
DepartmentThatNotExists
Try again...
Type the query:
Exit
Terminated...
peter@hp-laptop:~/rust-practice/chapter08/practice/company$ 

🐧 Peter | "사용 방법은 다 적어놨으니 따로 설명하지 않을게."

🦀 Ferris | "좋아, 그럼 이 쯤 하고 다음 장으로 넘어가자."

profile
Peter J Online Space - since July 2020

0개의 댓글