Ccmmutty logo
Commutty IT
3 min read

RustとAtCoderを勉強する(typical90_r)

https://cdn.magicode.io/media/notebox/blob_K11wDQe

はじめに

AtCoder の問題を Rust で解いていきます。AtCoder も Rust も初心者ですが、温かい目で成長を見守っていただけるとありがたいです。
今回は、競プロ典型90問018 - Statue of Chokudai(★3)を解きました。

提出コード

構造体を活用することを意識しました。トレイトも上手く使えないか考えてみたのですが、断念しました...。
rust
use num::pow;
use proconio::input;
use std::f64::consts::PI;

#[derive(Default)]
struct Position {
    x: f64,
    y: f64,
    z: f64,
}

struct FerrisWheel {
    t: f64,
    r: f64,
    position: Position,
}

struct Statue {
    position: Position,
}

impl Position {
    fn angle2(&self, other: &Position) -> f64 {
        (self.z - other.z)
            .atan2((pow(self.x - other.x, 2) + pow(self.y - other.y, 2)).sqrt())
            .to_degrees()
    }
}

impl FerrisWheel {
    fn new(t: f64, r: f64) -> FerrisWheel {
        FerrisWheel {
            t,
            r,
            position: Default::default(),
        }
    }

    fn rotate(&mut self, t: f64) {
        // self.t: 周期, t: 経過時間
        let theta = 2.0 * PI * (t / self.t);
        self.position.y = -self.r * theta.sin();
        self.position.z = self.r - self.r * theta.cos();
    }
}

impl Statue {
    fn new(x: f64, y: f64) -> Statue {
        Statue {
            position: Position { x, y, z: 0.0 },
        }
    }
}

fn main() {
    input! {
        t: f64,
        l: f64,
        x: f64,
        y: f64,
        q: isize,
        e: [f64; q],
    }
    let mut ferris_wheel = FerrisWheel::new(t, l / 2.0);
    let statue = Statue::new(x, y);

    for e in e {
        ferris_wheel.rotate(e);
        let angle = ferris_wheel.position.angle2(&statue.position);
        println!("{:}", angle);
    }
}

解説

三角関数を使います。観覧車に乗っている人の現在の位置は FerrisWheel.rotate() で求めています。また、人と像との俯角は Position.angle2() で求めています。

まとめ

本当は ferris_wheel.position.angle2(&statue.position)ferris_wheel.angle2(&statue) と書けるような実装にしたかったのですが、思いつきませんでした。構造体やトレイトの勉強をしてもっとスマートに書けるようになりたいです。

Discussion

コメントにはログインが必要です。