AtCoder Beginner Contest 255 C

https://atcoder.jp/contests/abc255/tasks/abc255_c

等差数列を構造体にすれば楽になりますが、負数が絡むと不安になりますね。

// ±1 Operation 1
#![allow(non_snake_case)]

use std::cmp::min;

fn read<T: std::str::FromStr>() -> T {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    line.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect()
}

fn read_input() -> (i64, i64, i64, i64) {
    let v = read_vec();
    (v[0], v[1], v[2], v[3])
}

struct Sequence {
    A: i64,
    D: i64,
    N: i64
}

impl Sequence {
    fn value(&self, i: i64) -> i64 {
        self.A + self.D * i
    }
    
    fn min(&self) -> i64 {
        self.value(if self.D >= 0 { 0 } else { self.N - 1 })
    }
    
    fn max(&self) -> i64 {
        self.value(if self.D >= 0 { self.N - 1 } else { 0 })
    }
    
    fn dist(&self, X: i64) -> i64 {
        if X <= self.min() {
            self.min() - X
        }
        else if X >= self.max() {
            X - self.max()
        }
        else {
            let i = (X - self.A) / self.D;  // 0 <= i < N - 1
            let v1 = self.value(i);
            let v2 = self.value(i + 1);
            // Dの符号でv1とv2の大小関係が変わる
            if self.D >= 0 {
                min(X - v1, v2 - X)
            }
            else {
                min(X - v2, v1 - X)
            }
        }
    }
}

fn f(v: (i64, i64, i64, i64)) -> i64 {
    let X = v.0;
    let A = v.1;
    let D = v.2;
    let N = v.3;
    let S = Sequence { A, D, N };
    S.dist(X)
}

fn main() {
    let v = read_input();
    println!("{}", f(v))
}