LoginSignup
4
5

More than 5 years have passed since last update.

第28回 オフラインリアルタイムどう書くの問題「十字の壁がそそり立つ世界の中を君は螺旋状に歩く」をRustで解く

Last updated at Posted at 2015-03-04

第28回 オフラインリアルタイムどう書くの問題「十字の壁がそそり立つ世界の中を君は螺旋状に歩く」を、Rust(2015-02-22 nightly)で解きました。

u32だったのをu64にして、末尾再帰をloopに置き換えただけで、追加問題も難なく実行できました。

感想

  • このレベル(並列なし、Owned Pointerなし、traitなし)だと、Rustは単に「すばらしいC言語」。何もデメリットがない。C言語経験者だったら、単に楽しく便利なだけ。
    • Boxとか駆使してライフタイムがごにょり始めると、コンパイルエラーを乗り越えるための苦痛が予想される…
  • Rustは関数型プログラミングと相性が悪いと思う。&mutとかとどう折り合いつけるの? 逆に&mutを避けたいなら、Rust使う意味あんの?

コード

#![allow(unused_variables)]
#![allow(dead_code)]

static DIREC_STR:[&'static str;4] = ["E", "S", "W", "N"];
static TURN_RIGHT:i32 = 1;
static TURN_LEFT:i32 = -1;
static FORWARD:i32 = 0;

#[derive(Debug)]
struct Segment {
    steps: u64,
    next_direc: i32
}

impl Segment {
    fn new(steps: u64, next_direc: i32) -> Segment {
        Segment { next_direc:next_direc, steps:steps }
    }
}

#[derive(Debug)]
struct You {
    pos: u64,
    direc: u32
}

fn trace_segment_and_turn(day_of_answer:u64, segment: &Segment, you: &mut You)
{
    if day_of_answer < you.pos + (*segment).steps  {
        you.pos = day_of_answer;
        return;
    }
    you.pos += (*segment).steps;
    you.direc = ((you.direc as i32+(*segment).next_direc + 4) % 4) as u32;
}

fn create_segments(n:u64, e:u64, s:u64, w:u64, wall_thickness: u64) -> Vec<Segment>
{
    let mut segments = vec![
        Segment::new(e,              TURN_RIGHT),
        Segment::new(wall_thickness, TURN_RIGHT),
        Segment::new(e,              TURN_LEFT),
        Segment::new(s,              TURN_RIGHT),
        Segment::new(wall_thickness, TURN_RIGHT),
        Segment::new(s,              TURN_LEFT),
        Segment::new(w,              TURN_RIGHT),
        Segment::new(wall_thickness, TURN_RIGHT),
        Segment::new(w,              TURN_LEFT),
        Segment::new(n,              TURN_RIGHT)];
    if n > 1 {
        segments.push(Segment::new(wall_thickness, TURN_RIGHT));
        segments.push(Segment::new(n-1,   TURN_LEFT));
    } else {
        segments.push(Segment::new(wall_thickness, FORWARD));
    }
    segments
}

fn trace_path(day_of_answer:u64, you: &mut You,
              n:u64, e:u64, s:u64, w:u64, mut wall_thickness: u64) {
    loop {
        for segment in create_segments(n, e, s, w, wall_thickness).iter() {
            trace_segment_and_turn(day_of_answer, segment, you);
            if you.pos >= day_of_answer { return; }
        }
        you.pos += 1;
        wall_thickness += 2;
    }
}

fn solve(e:u64, s:u64, w:u64, n:u64, day_of_answer:u64) -> &'static str {
    let mut you = You {pos:0, direc:0};
    trace_path(day_of_answer, &mut you, e, s, w, n, 2);
    return DIREC_STR[you.direc as usize]
}

fn test(e:u64, s:u64, w:u64, n:u64, day_of_answer:u64, expected:&str) {
    assert_eq!(solve(e, s, w, n, day_of_answer), expected);
}

#[test]
fn test_case() {
    /*0*/ test( 2, 3, 5, 4, 85, "S" );
    /*1*/ test( 1, 2, 3, 4, 1, "E" );
    /*2*/ test( 1, 2, 3, 4, 2, "S" );
    /*3*/ test( 1, 2, 3, 4, 3, "S" );
    /*4*/ test( 1, 2, 3, 4, 4, "W" );
    test( 2, 3, 5, 4,  85, "S");
    test( 1, 2, 3, 4,  1, "E");
    test( 1, 2, 3, 4,  2, "S");
    test( 1, 2, 3, 4,  3, "S");
    test( 1, 2, 3, 4,  4, "W");
    test( 1, 2, 3, 4,  27, "E");
    test( 1, 2, 3, 4,  63, "E");
    test( 1, 2, 3, 4,  40, "W");
    test( 1, 4, 3, 2,  40, "S");
    test( 3, 3, 3, 3,  30, "S");
    test( 3, 3, 3, 3,  31, "E");
    test( 3, 3, 3, 3,  32, "E");
    test( 3, 3, 3, 3,  70, "S");
    test( 3, 3, 3, 3,  71, "E");
    test( 3, 3, 3, 3,  72, "E");
    test( 1, 1, 1, 1,  7, "N");
    test( 1, 2, 1, 1,  7, "W");
    test( 1, 6, 1, 1,  7, "S");
    test( 1, 8, 1, 1,  7, "E");
    test( 1, 1, 1, 1,  30, "N");
    test( 1, 2, 1, 1,  30, "W");
    test( 1, 5, 1, 1,  30, "S");
    test( 1, 8, 1, 1,  30, "E");
    test( 9, 9, 9, 9,  99, "W");
    test( 5, 6, 3, 8,  3, "E");
    test( 5, 8, 1, 1,  11, "W");
    test( 2, 8, 1, 2,  18, "S");
    test( 3, 2, 3, 1,  20, "N");
    test( 3, 3, 8, 1,  28, "N");
    test( 2, 5, 1, 2,  32, "E");
    test( 2, 5, 1, 6,  33, "E");
    test( 1, 2, 5, 7,  34, "N");
    test( 3, 6, 5, 6,  36, "E");
    test( 6, 2, 8, 1,  39, "S");
    test( 3, 1, 2, 3,  41, "W");
    test( 1, 1, 3, 4,  45, "W");
    test( 1, 3, 1, 2,  46, "N");
    test( 4, 4, 4, 4,  49, "W");
    test( 3, 1, 4, 4,  55, "N");
    test( 6, 6, 2, 1,  56, "W");
    test( 3, 2, 1, 2,  59, "S");
    test( 2, 7, 7, 1,  60, "S");
    test( 3, 1, 1, 1,  63, "N");
    test( 4, 6, 4, 1,  78, "E");
    test( 7, 5, 3, 6,  79, "W");
    test( 7, 8, 3, 1,  81, "E");
    test( 3, 2, 5, 2,  82, "S");
    test( 1, 1, 3, 4,  84, "N");
    test( 7, 4, 1, 5,  88, "S");
    test( 3, 6, 5, 3,  89, "S");
    test( 1, 4, 2, 3,  92, "N");
    test( 1, 3, 4, 5,  93, "W");
    test( 2, 4, 8, 1,  94, "W");
    test( 3, 6, 1, 7,  99, "S");
}

fn main() {
    assert_eq!(solve(1234, 2345, 3456, 4567, 978593417), "E");
    assert_eq!(solve(1234, 2345, 3456, 4567, 978593418), "S");
    assert_eq!(solve(31415, 92653, 58979, 32384, 9812336139), "W");
    assert_eq!(solve(31415, 92653, 58979, 32384, 9812336140), "S");
    assert_eq!(solve(314159, 265358, 979323, 84626, 89099331642), "S");
    assert_eq!(solve(314159, 265358, 979323, 84626, 89099331643), "W");
}
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5