2022/04/24
はじめに
地下鉄システムのうち,特定の駅間の平均所要時間を求める問題.
コード全文
main.rs
use std::collections::HashMap;
struct User {
start: String,
time: i32
}
struct Record {
sum: i32,
count: i32,
}
struct UndergroundSystem {
users: HashMap<i32, User>,
records: HashMap<String, Record>
}
impl UndergroundSystem {
fn new() -> Self {
Self {
users: HashMap::new(),
records: HashMap::new()
}
}
fn get_key(&self, start_station: String, end_station: String) -> String {
let mut key = start_station.clone();
key.push('-');
key.push_str(end_station.as_str());
key
}
fn check_in(&mut self, id: i32, station_name: String, t: i32) {
let user = User {start:station_name.clone(), time:t};
self.users.insert(id, user);
}
fn check_out(&mut self, id: i32, station_name: String, t: i32) {
let user = self.users.get(&id).unwrap();
let key = self.get_key(user.start.clone(), station_name);
let record = self.records.entry(key).or_insert(Record{sum:0,count:0});
(*record).sum += (t - user.time);
(*record).count += 1;
}
fn get_average_time(&self, start_station: String, end_station: String) -> f64 {
let key = self.get_key(start_station, end_station);
let record = self.records.get(&key).unwrap();
((*record).sum as f64) / ((*record).count as f64)
}
}
解説
準備
今回は,HashMap を利用して問題を解く.
use std::collections::HashMap;
struct User
ユーザ情報管理用の struct を定義しておく.
名前の通り,start
はcheckIn
した駅名を,time
はcheckIn
した時間を記録する.
struct User {
start: String,
time: i32
}
struct Record
特定の駅間の所要時間の情報を記録する struct を定義する.
sum
には所要時間の合計を,count
には利用回数を記録する.
struct Record {
sum: i32,
count: i32,
}
struct UndergroundSystem
システムは,(1)現在のユーザの情報,(2)2駅間の所要時間情報をもつ.
ここで,それらの情報はそれぞれ,User
, Record
で定義したものとする.
struct UndergroundSystem {
users: HashMap<i32, User>,
records: HashMap<String, Record>
}
impl UndergroundSystem
システム起動時は何も情報を持たないので,空の HashMap で初期化する.
impl UndergroundSystem {
fn new() -> Self {
Self {
users: HashMap::new(),
records: HashMap::new()
}
}
fn get_key
2駅間の情報を指し示すキーを取得する.
今回は,スタートとエンドの両駅の名前を単純に-
でつないだものとする.
fn get_key(&self, start_station: String, end_station: String) -> String {
let mut key = start_station.clone();
key.push('-');
key.push_str(end_station.as_str());
key
}
fn check_in
駅に入場する場合に呼ばれる関数.
users
に各種情報を保存する.
fn check_in(&mut self, id: i32, station_name: String, t: i32) {
let user = User {start:station_name.clone(), time:t};
self.users.insert(id, user);
}
fn check_out
駅から退場するための関数.
ユーザの入退場駅および入退場時刻から,records
を更新する.
fn check_out(&mut self, id: i32, station_name: String, t: i32) {
let user = self.users.get(&id).unwrap();
let key = self.get_key(user.start.clone(), station_name);
let record = self.records.entry(key).or_insert(Record{sum:0,count:0});
(*record).sum += (t - user.time);
(*record).count += 1;
}
fn get_average_time
2駅間の平均所要時間を返す関数.
records
に保存されている合計所要時刻とカウントから,平均を求める.
fn get_average_time(&self, start_station: String, end_station: String) -> f64 {
let key = self.get_key(start_station, end_station);
let record = self.records.get(&key).unwrap();
((*record).sum as f64) / ((*record).count as f64)
}
}
おわりに
だんだん Rust に慣れてきた気がする.特に,StackOverflow よりも公式 Docs のリファレンスから情報をとれるようになってきたという点が嬉しい.