Submission #64986148


Source Code Expand

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

use std::mem::MaybeUninit;

use itertools::Itertools;
use nalgebra::coordinates::IJKW;
use num_integer::Roots;
use ordered_float::OrderedFloat;
use proconio::{input, marker::Chars};

use rng::Rng;
use rng_log::RngLog;
use smallvec::{smallvec, SmallVec};
use time::{elapsed, Timer};
// use visualize::*;

static mut TIMER: MaybeUninit<Timer> = MaybeUninit::uninit();
static mut RNG: MaybeUninit<Rng> = MaybeUninit::uninit();
static mut RNG_LOG: MaybeUninit<RngLog> = MaybeUninit::uninit();

// const DIRS: [char; 4] = ['R', 'U', 'L', 'D'];
// const DIJ: [usize; 4] = [1, !0 - N + 1, !0, N];
// const DI: [usize; 4] = [0, !0, 0, 1];
// const DJ: [usize; 4] = [1, 0, !0, 0];

type P = (i64, i64);

fn orient(a: P, b: P, p: P) -> i64 {
    (b.0 - a.0) * (p.1 - a.1) - (b.1 - a.1) * (p.0 - a.0)
}

fn contains(p: P, a: P, b: P, c: P) -> bool {
    if orient(a, b, c) == 0 {
        if orient(a, b, p) != 0 || orient(a, c, p) != 0 {
            return false;
        }

        let xs_min = a.0.min(b.0).min(c.0);
        let xs_max = a.0.max(b.0).max(c.0);
        let ys_min = a.1.min(b.1).min(c.1);
        let ys_max = a.1.max(b.1).max(c.1);
        return xs_min <= p.0 && p.0 <= xs_max && ys_min <= p.1 && p.1 <= ys_max;
    }

    let c1 = orient(a, b, p);
    let c2 = orient(b, c, p);
    let c3 = orient(c, a, p);
    (c1 >= 0 && c2 >= 0 && c3 >= 0) || (c1 <= 0 && c2 <= 0 && c3 <= 0)
}

fn contains_sq(p: P, l0: P, r0: P, l1: P, r1: P) -> bool {
    contains(p, l0, r0, l1) || contains(p, l1, r0, r1)
}

fn dist(a: P, b: P) -> OrderedFloat<f64> {
    (((a.0 - b.0).pow(2) + (a.1 - b.1).pow(2)).sqrt() as f64).into()
}

#[derive(Debug, Clone)]
struct Square {
    p0: P,
    p1: P,
    p2: P,
    p3: P,
}

impl Square {
    fn new(p0: P, p1: P, p2: P, p3: P) -> Self {
        Self { p0, p1, p2, p3 }
    }

    fn contains(&self, gomi: P) -> bool {
        contains_sq(gomi, self.p0, self.p1, self.p2, self.p3)
    }
}

#[derive(Debug, Clone)]
struct Gomi {
    p: P,
    index: usize,
    picked: bool,
    cover_count: usize,
}

impl Gomi {
    fn new(index: usize, p: P) -> Self {
        Self {
            index,
            p,
            picked: false,
            cover_count: 0,
        }
    }
}

struct State {
    turn: usize,
    moeru: Vec<Gomi>,
    moenai: Vec<Gomi>,
    sigen: Vec<P>,

    pos_moeru_l: P,
    pos_moeru_r: P,

    pos_moenai_l: P,
    pos_moenai_r: P,

    moves_moeru_l: Vec<P>,
    moves_moeru_r: Vec<P>,

    moves_moenai_l: Vec<P>,
    moves_moenai_r: Vec<P>,
}

impl State {
    fn pick_extra_moeru_gomi(&self, l: P, r: P) -> Option<P> {
        let mut extra_moeru = None;

        let extra = self
            .moenai
            .iter()
            .filter(|gomi| !gomi.picked)
            .map(|gomi| gomi.p)
            .chain(self.sigen.iter().cloned());

        for p in extra {
            if contains_sq(p, self.pos_moenai_l, self.pos_moenai_r, l, r) {
                extra_moeru = Some(p);
                break;
            }
        }

        extra_moeru
    }

    fn move_moeru(&mut self, l: P, r: P) {
        self.moeru.iter_mut().for_each(|gomi| {
            if contains_sq(gomi.p, self.pos_moeru_l, self.pos_moeru_r, l, r) {
                gomi.picked = true;
            }
        });

        self.moves_moeru_l.push(l);
        self.moves_moeru_r.push(r);
        self.pos_moeru_l = l;
        self.pos_moeru_r = r;
    }

    fn stay_moeru(&mut self) {
        self.move_moeru(self.pos_moeru_l, self.pos_moeru_r);
    }

    fn move_moenai(&mut self, l: P, r: P) {
        self.moenai.iter_mut().for_each(|gomi| {
            if contains_sq(gomi.p, self.pos_moenai_l, self.pos_moenai_r, l, r) {
                gomi.picked = true;
            }
        });

        self.moves_moenai_l.push(l);
        self.moves_moenai_r.push(r);
        self.pos_moenai_l = l;
        self.pos_moenai_r = r;
    }

    fn stay_moenai(&mut self) {
        self.move_moenai(self.pos_moenai_l, self.pos_moenai_r);
    }

    fn need_moeru_move(&self) -> bool {
        self.turn >= self.moves_moeru_l.len()
    }

    fn print(&mut self) {
        let i = self.turn;
        println!(
            "{} {} {} {} {} {} {} {}",
            self.moves_moeru_l[i].0,
            self.moves_moeru_l[i].1,
            self.moves_moeru_r[i].0,
            self.moves_moeru_r[i].1,
            self.moves_moenai_l[i].0,
            self.moves_moenai_r[i].1,
            self.moves_moenai_l[i].0,
            self.moves_moenai_r[i].1,
        );
        self.turn += 1;
    }
}

fn gen_single_square(state: &mut State, rest_gomi: &mut Vec<Gomi>) -> Square {
    let i0 = rng::usize(rest_gomi.len());
    let i1 = rng::usize(rest_gomi.len());
    let i2 = rng::usize(rest_gomi.len());
    let i3 = rng::usize(rest_gomi.len());

    let sq = Square::new(
        rest_gomi[i0].p,
        rest_gomi[i1].p,
        rest_gomi[i2].p,
        rest_gomi[i3].p,
    );

    let mut k = 0;
    while k < rest_gomi.len() {
        let gomi = rest_gomi[k].p;
        if sq.contains(gomi) {
            rest_gomi.swap_remove(k);
        } else {
            k += 1;
        }
    }

    state.moeru.iter_mut().for_each(|gomi| {
        if sq.contains(gomi.p) {
            gomi.cover_count += 1;
        }
    });

    sq
}

fn cover_square_moeru(state: &mut State) -> Vec<Square> {
    let mut rest_gomi = state.moeru.clone();

    let mut squares = Vec::new();
    while !rest_gomi.is_empty() {
        let sq = gen_single_square(state, &mut rest_gomi);
        squares.push(sq);
    }

    squares
}

fn cover_square_moenai(state: &mut State) {
    // TODO
}

fn break_random_square_moeru(
    state: &mut State,
    squares: &mut Vec<Square>,
) -> (usize, usize, Square) {
    let i = rng::usize(squares.len());
    let remove_sq = squares.remove(i);
    let mut cnt = 0;

    state.moeru.iter_mut().for_each(|gomi| {
        if remove_sq.contains(gomi.p) {
            gomi.cover_count -= 1;
            if gomi.cover_count == 0 {
                cnt += 1;
            }
        }
    });

    (cnt, i, remove_sq)
}

fn recover_square_moeru(state: &mut State) -> Vec<Square> {
    let mut rest_gomi: Vec<_> = state
        .moeru
        .iter()
        .filter(|g| g.cover_count == 0)
        .cloned()
        .collect();

    let mut squares = Vec::new();
    while !rest_gomi.is_empty() {
        let sq = gen_single_square(state, &mut rest_gomi);
        squares.push(sq);
    }

    squares
}

fn undo_moeru(
    state: &mut State,
    squares: &mut Vec<Square>,
    (index, sq): (usize, Square),
    recovered: Vec<Square>,
) {
    state.moeru.iter_mut().for_each(|gomi| {
        if sq.contains(gomi.p) {
            gomi.cover_count += 1;
        }

        for r in &recovered {
            if r.contains(gomi.p) {
                gomi.cover_count -= 1;
            }
        }
    });

    squares.drain(index..index + recovered.len());
    squares.insert(index, sq);
}

fn eval(state: &mut State, moeru_sq: &Vec<Square>) -> f64 {
    let mut penalty = 0;

    let mut moeru_index = 0;

    let mut moeru_moves = Vec::new();
    for sq in moeru_sq {
        moeru_moves.push((sq.p0, sq.p1));
        moeru_moves.push((sq.p2, sq.p3));
    }

    let mut moeru_t: OrderedFloat<f64> = 0.0.into();
    while moeru_index + 1 < moeru_moves.len() {
        let (l0, r0) = moeru_moves[moeru_index];
        let (l1, r1) = moeru_moves[moeru_index + 1];

        for i in 0..state.sigen.len() {
            if contains_sq(state.sigen[i], l0, r0, l1, r1) {
                penalty += 1;
            }
        }

        moeru_t += dist(l0, l1) + dist(r0, r1);
        moeru_index += 1;
    }

    1000000.0 * (1.0 + (100000000.0 / moeru_t.0).log2()) - (penalty as f64) * 10000000.0
}

fn print(state: &mut State, moeru_sq: &Vec<Square>) {
    let mut penalty = 0;

    let mut moeru_index = 0;

    let mut moeru_moves = Vec::new();
    for sq in moeru_sq {
        moeru_moves.push((sq.p0, sq.p1));
        moeru_moves.push((sq.p2, sq.p3));
    }

    println!(
        "{} {} {} {} {} {} {} {}",
        moeru_moves[0].0 .0,
        moeru_moves[0].0 .1,
        moeru_moves[0].1 .0,
        moeru_moves[0].1 .1,
        0,
        0,
        0,
        0
    );

    let mut moeru_t: OrderedFloat<f64> = 0.0.into();
    while moeru_index + 1 < moeru_moves.len() {
        let (l0, r0) = moeru_moves[moeru_index];
        let (l1, r1) = moeru_moves[moeru_index + 1];

        for i in 0..state.sigen.len() {
            if contains_sq(state.sigen[i], l0, r0, l1, r1) {
                penalty += 1;
            }
        }

        moeru_t += dist(l0, l1) + dist(r0, r1);
        moeru_index += 1;

        println!(
            "{} {} {} {} {} {} {} {}",
            l1.0, l1.1, r1.0, r1.1, 0, 0, 0, 0
        );
    }
}

fn calc_perf_moeru(
    state: &State,
    cl: usize,
    cr: usize,
    i: usize,
    j: usize,
    k: usize,
    picked_bit: u128,
    moeru_bit: &Vec<u128>,
) -> f64 {
    // if dist(state.moeru[i].p, state.moeru[j].p).0 > 1e5 {
    //     return -1.0;
    // }

    let l = state.pos_moeru_l;
    let r = state.pos_moeru_r;

    let b1 = moeru_bit[cl * 10000 + cr * 100 + i] | moeru_bit[i * 10000 + cr * 100 + j];
    let cnt1 = ((b1 | moeru_bit[i * 10000 + j * 100 + k]) & !picked_bit).count_ones();
    let cnt2 = (b1 & !picked_bit).count_ones();

    let d = (dist(l, state.moeru[i].p) + dist(r, state.moeru[j].p))
        + dist(state.moeru[i].p, state.moeru[k].p);

    // if d.0 == 0.0 {
    //     ((cnt1 * 1 + cnt2) as f64 * 1e3) / 0.1
    // } else {
    ((cnt1 * 1 + cnt2) as f64 * 1e3) / (d.0 + 1.0).powf(3.0)
    // }
}

fn calc_perf_moeru2(
    state: &State,
    cl: usize,
    cr: usize,
    i: usize,
    j: usize,
    picked_bit: u128,
    moeru_bit: &Vec<u128>,
) -> f64 {
    // if dist(state.moeru[i].p, state.moeru[j].p).0 > 1e5 {
    //     return -1.0;
    // }

    let l = state.pos_moeru_l;
    let r = state.pos_moeru_r;

    let b1 = moeru_bit[cl * 10000 + cr * 100 + i] | moeru_bit[i * 10000 + cr * 100 + j];
    let cnt2 = (b1 & !picked_bit).count_ones();
    // for idx in 0..state.moeru.len() {
    //     if state.moeru[idx].picked {
    //         continue;
    //     }

    //     let p = state.moeru[idx].p;
    //     if contains(p, l, r, state.moeru[i].p) || contains(p, state.moeru[i].p, r, state.moeru[j].p)
    //     {
    //         cnt1 += 1;
    //     }
    //     if contains(p, l, r, state.moeru[i].p)
    //         || contains(p, state.moeru[i].p, r, state.moeru[j].p)
    //         || contains(p, state.moeru[i].p, state.moeru[j].p, state.moeru[k].p)
    //     {
    //         cnt2 += 1;
    //     }
    // }

    let d = dist(l, state.moeru[i].p) + dist(r, state.moeru[j].p);

    if d.0 == 0.0 {
        ((0 * 1 + cnt2) as f64 * 1e3) / 0.1
    } else {
        ((0 * 1 + cnt2) as f64 * 1e3) / d.0.powf(3.0)
    }
}

// fn calc_perf_moeru2(state: &State, i: usize, j: usize) -> f64 {
//     // if dist(state.moeru[i].p, state.moeru[j].p).0 > 1e5 {
//     //     return -1.0;
//     // }

//     let l = state.pos_moeru_l;
//     let r = state.pos_moeru_r;

//     let mut cnt1 = 0;
//     for idx in 0..state.moeru.len() {
//         if state.moeru[idx].picked {
//             continue;
//         }

//         let p = state.moeru[idx].p;
//         if contains(p, l, r, state.moeru[i].p) || contains(p, state.moeru[i].p, r, state.moeru[j].p)
//         {
//             cnt1 += 1;
//         }
//     }

//     let d = (dist(l, state.moeru[i].p) + dist(r, state.moeru[j].p));

//     if d.0 == 0.0 {
//         ((cnt1 * 100) as f64 * 1e10) / 0.1
//     } else {
//         ((cnt1 * 100) as f64 * 1e10) / d.0
//     }
// }

fn main() {
    unsafe {
        TIMER = MaybeUninit::new(Timer::new());
        RNG = MaybeUninit::new(Rng::new());
        RNG_LOG = MaybeUninit::new(RngLog::from_rng(RNG.assume_init_mut()));
    }

    input! {
        X: usize,
        Y: usize,
        Z: usize,
        moeru: [(i64, i64); X],
        moenai: [(i64, i64); Y],
        sigen: [(i64, i64); Z],
    };

    let moeru = moeru
        .into_iter()
        .enumerate()
        .map(|(i, p)| Gomi::new(i, p))
        .collect::<Vec<_>>();

    let moenai = moenai
        .into_iter()
        .enumerate()
        .map(|(i, p)| Gomi::new(i, p))
        .collect::<Vec<_>>();

    let mut state = State {
        turn: 0,
        moeru: moeru.clone(),
        moenai: moenai.clone(),
        sigen: sigen.clone(),

        pos_moeru_l: moeru[0].p,
        pos_moeru_r: moeru[0].p,

        pos_moenai_l: (0, 0),
        pos_moenai_r: (0, 0),

        moves_moeru_l: vec![moeru[0].p],
        moves_moeru_r: vec![moeru[0].p],

        moves_moenai_l: vec![(0, 0)],
        moves_moenai_r: vec![(0, 0)],
    };

    let mut sigen_bit = vec![0_u128; X * X * X];
    let mut moeru_bit = vec![0_u128; X * X * X];

    for i in 0..X {
        for j in 0..=i {
            for k in 0..=j {
                let pi = state.moeru[i].p;
                let pj = state.moeru[j].p;
                let pk = state.moeru[k].p;

                let mut v = 0;
                for a in 0..Z {
                    let p = sigen[a];

                    if contains(p, pi, pj, pk) {
                        v |= 1 << a;
                    }
                }
                sigen_bit[i * 10000 + j * 100 + k] = v;
                sigen_bit[i * 10000 + k * 100 + j] = v;
                sigen_bit[j * 10000 + i * 100 + k] = v;
                sigen_bit[j * 10000 + k * 100 + i] = v;
                sigen_bit[k * 10000 + i * 100 + j] = v;
                sigen_bit[k * 10000 + j * 100 + i] = v;

                let mut v = 0;
                for a in 0..X {
                    let p = state.moeru[a].p;

                    if contains(p, pi, pj, pk) {
                        v |= 1 << a;
                    }
                }
                moeru_bit[i * 10000 + j * 100 + k] = v;
                moeru_bit[i * 10000 + k * 100 + j] = v;
                moeru_bit[j * 10000 + i * 100 + k] = v;
                moeru_bit[j * 10000 + k * 100 + i] = v;
                moeru_bit[k * 10000 + i * 100 + j] = v;
                moeru_bit[k * 10000 + j * 100 + i] = v;
            }
        }
    }

    let mut best_perf = (-1e300, 0, 0, 0);
    for i in 0..X {
        for j in 0..X {
            if i == j {
                continue;
            }
            for k in 0..X {
                if sigen_bit[i * 10000 + j * 100 + k] != 0 {
                    continue;
                }

                let perf = calc_perf_moeru(&state, i, j, i, j, k, 0, &moeru_bit);
                if best_perf.0 <= perf {
                    best_perf = (perf, i, j, k);
                }
            }
        }
    }

    let mut cl = best_perf.1;
    let mut cr = best_perf.2;
    let mut rest_moeru = state.moeru.len();
    let mut picked_bit: u128 = 0;

    println!(
        "{} {} {} {} {} {} {} {}",
        state.moeru[cl].p.0,
        state.moeru[cl].p.1,
        state.moeru[cr].p.0,
        state.moeru[cr].p.1,
        0,
        0,
        0,
        0,
    );

    let mut turn = 0;
    while rest_moeru > 0 && elapsed() < 1900.0 {
        turn += 1;
        let mut best_perf = (-1e300, 0, 0, 0);
        // dbg!(state.moeru[0].picked);

        state.pos_moeru_l = state.moeru[cl].p;
        state.pos_moeru_r = state.moeru[cr].p;

        for i in 0..state.moeru.len() {
            for j in 0..state.moeru.len() {
                if i == cl && j == cr {
                    continue;
                }
                for k in 0..state.moeru.len() {
                    if sigen_bit[cl * 10000 + cr * 100 + i] != 0
                        || sigen_bit[i * 10000 + cr * 100 + j] != 0
                        || sigen_bit[i * 10000 + j * 100 + k] != 0
                    {
                        continue;
                    }

                    let perf = calc_perf_moeru(&state, cl, cr, i, j, k, picked_bit, &moeru_bit);

                    // if turn == 98 && i == 56 && j == 56 && k == 89 {
                    //     calc_perf_moeru_debug(&state, cl, cr, i, j, k, picked_bit, &moeru_bit);
                    //     dbg!(perf, i, j, k, state.moeru[k].picked);
                    // }

                    if best_perf.0 <= perf {
                        best_perf = (perf, i, j, k);
                    }
                }
            }
        }

        if best_perf.0 == 0.0 {
            best_perf.1 = cr;
            best_perf.2 = cr;
        }

        // dbg!(turn, best_perf, elapsed());

        let (_, l, r, _) = best_perf;
        for i in 0..state.moeru.len() {
            if state.moeru[i].picked {
                continue;
            }

            if (moeru_bit[cl * 10000 + cr * 100 + l] >> i & 1) != 0
                || (moeru_bit[l * 10000 + cr * 100 + r] >> i & 1) != 0
            {
                state.moeru[i].picked = true;
                rest_moeru -= 1;
                picked_bit |= 1 << i;
                // dbg!(i);
            }
        }
        cl = l;
        cr = r;

        println!(
            "{} {} {} {} {} {} {} {}",
            state.moeru[l].p.0,
            state.moeru[l].p.1,
            state.moeru[r].p.0,
            state.moeru[r].p.1,
            0,
            0,
            0,
            0,
        );
    }

    while rest_moeru > 0 {
        let mut best_perf = (-1e300, 0, 0, 0);
        // dbg!(state.moeru[0].picked);

        state.pos_moeru_l = state.moeru[cl].p;
        state.pos_moeru_r = state.moeru[cr].p;

        for i in 0..state.moeru.len() {
            for j in 0..state.moeru.len() {
                if i == cl && j == cr {
                    continue;
                }
                // i * 10000 + j * 100 + k
                if sigen_bit[cl * 10000 + cr * 100 + i] != 0
                    || sigen_bit[i * 10000 + cr * 100 + j] != 0
                {
                    continue;
                }

                let perf = calc_perf_moeru2(&state, cl, cr, i, j, picked_bit, &moeru_bit);

                if best_perf.0 <= perf {
                    best_perf = (perf, i, j, 0);
                }
            }
        }

        if best_perf.0 == 0.0 {
            best_perf.1 = cr;
            best_perf.2 = cr;
        }

        // dbg!(rest_moeru, elapsed());

        let (_, l, r, _) = best_perf;
        for i in 0..state.moeru.len() {
            if state.moeru[i].picked {
                continue;
            }

            if (moeru_bit[cl * 10000 + cr * 100 + l] >> i & 1) != 0
                || (moeru_bit[l * 10000 + cr * 100 + r] >> i & 1) != 0
            {
                state.moeru[i].picked = true;
                rest_moeru -= 1;
                picked_bit |= 1 << i;
                // dbg!(i);
            }
        }
        cl = l;
        cr = r;

        println!(
            "{} {} {} {} {} {} {} {}",
            state.moeru[l].p.0,
            state.moeru[l].p.1,
            state.moeru[r].p.0,
            state.moeru[r].p.1,
            0,
            0,
            0,
            0,
        );
    }

    // dbg!(rest_moeru, picked_bit.count_ones());

    // while rest_moeru > 0 {
    //     let mut best_perf = (-1e300, 0, 0, 0);

    //     state.pos_moeru_l = state.moeru[cl].p;
    //     state.pos_moeru_r = state.moeru[cr].p;

    //     for i in 0..state.moeru.len() {
    //         for j in 0..state.moeru.len() {
    //             if i == cl && j == cr {
    //                 continue;
    //             }

    //             if sigen_bit[cl][cr][i] != 0 || sigen_bit[i][cr][j] != 0 {
    //                 continue;
    //             }

    //             let perf = calc_perf_moeru2(&state, i, j);

    //             if best_perf.0 <= perf {
    //                 best_perf = (perf, i, j, 0);
    //             }
    //         }
    //     }

    //     if best_perf.0 == 0.0 {
    //         best_perf.1 = cr;
    //         best_perf.2 = cr;
    //     }

    //     // dbg!(cl, cr, best_perf);

    //     let (_, l, r, _) = best_perf;
    //     for i in 0..state.moeru.len() {
    //         if state.moeru[i].picked {
    //             continue;
    //         }

    //         if contains_sq(
    //             state.moeru[i].p,
    //             state.moeru[cl].p,
    //             state.moeru[cr].p,
    //             state.moeru[l].p,
    //             state.moeru[r].p,
    //         ) {
    //             state.moeru[i].picked = true;
    //             rest_moeru -= 1;
    //             // dbg!(i);
    //         }
    //     }
    //     cl = l;
    //     cr = r;

    //     println!(
    //         "{} {} {} {} {} {} {} {}",
    //         state.moeru[l].p.0,
    //         state.moeru[l].p.1,
    //         state.moeru[r].p.0,
    //         state.moeru[r].p.1,
    //         0,
    //         0,
    //         0,
    //         0,
    //     );
    // }

    // let mut moeru_sq = cover_square_moeru(&mut state);
    // // cover_square_moenai(&mut state);

    // let max_temp = 1000.0;
    // let mut cur_score = eval(&mut state, &moeru_sq);
    // let mut iter = 0;
    // loop {
    //     let t = elapsed();
    //     if t >= 1900.0 {
    //         break;
    //     }

    //     iter += 1;
    //     let temp = (1.0 - (t / 1900.0)) * max_temp;
    //     if rng::f64() < 0.1 {
    //         let (cnt, index, broken_sq) = break_random_square_moeru(&mut state, &mut moeru_sq);

    //         if cnt <= 0 {
    //             continue;
    //         }

    //         let recovered_sq = recover_square_moeru(&mut state);

    //         for i in 0..recovered_sq.len() {
    //             moeru_sq.insert(i + index, recovered_sq[i].clone());
    //         }

    //         let new_score = eval(&mut state, &moeru_sq);

    //         if accept(temp, cur_score, new_score) {
    //             if cur_score != new_score {
    //                 dbg!(cur_score);
    //             }
    //             cur_score = new_score;
    //             continue;
    //         } else {
    //             undo_moeru(&mut state, &mut moeru_sq, (index, broken_sq), recovered_sq);
    //         }
    //     } else {
    //         let i = rng::usize(moeru_sq.len());
    //         let j = rng::usize(moeru_sq.len());

    //         let v = moeru_sq.remove(i);
    //         moeru_sq.insert(j, v);
    //         let new_score = eval(&mut state, &moeru_sq);

    //         if accept(temp, cur_score, new_score) {
    //             if cur_score != new_score {
    //                 dbg!(cur_score);
    //             }
    //             cur_score = new_score;
    //             continue;
    //         } else {
    //             let v = moeru_sq.remove(j);
    //             moeru_sq.insert(i, v);
    //         }
    //     }
    // }

    // dbg!(iter);
    // print(&mut state, &moeru_sq);
}

fn accept(temp: f64, old_score: f64, new_score: f64) -> bool {
    new_score >= old_score - temp * rng_log::ln()
}

#[cfg(feature = "visualize")]
#[allow(dead_code)]
mod visualize {
    use std::{
        fs::File,
        io::{BufWriter, Write},
        sync::Mutex,
    };

    use once_cell::sync::OnceCell;
    use vis::{Canvas, Command, Shape, P};

    static WRITER: OnceCell<Mutex<BufWriter<File>>> = OnceCell::new();
    static CANVAS: OnceCell<Canvas> = OnceCell::new();

    #[no_mangle]
    extern "C" fn drop_writer() {
        WRITER.get().unwrap().lock().unwrap().flush().unwrap();
    }

    pub fn new_empty_canvas(name: &str, width: usize, height: usize) {
        // stop_world();

        shutdown_hooks::add_shutdown_hook(drop_writer);

        let w = BufWriter::new(File::create(name).unwrap());
        WRITER.set(Mutex::new(w)).unwrap();

        {
            let mut w = WRITER.get().unwrap().lock().unwrap();
            let canvas = Canvas::Empty {
                w: width as i64,
                h: height as i64,
            };
            writeln!(w, "{}", serde_json::to_string(&canvas).unwrap()).unwrap();
        }

        reset_colors();

        // restart_world();
    }

    // pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {
    //     // stop_world();

    //     shutdown_hooks::add_shutdown_hook(drop_writer);

    //     let w = BufWriter::new(File::create(name).unwrap());
    //     WRITER.set(Mutex::new(w)).unwrap();

    //     let mut w = WRITER.get().unwrap().lock().unwrap();
    //     let canvas = Canvas::Grid {
    //         w: width as i64,
    //         h: height as i64,
    //         row: row as i64,
    //         col: col as i64,
    //     };
    //     writeln!(w, "{}", serde_json::to_string(&canvas).unwrap()).unwrap();

    //     // restart_world();
    // }

    pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {
        // stop_world();

        shutdown_hooks::add_shutdown_hook(drop_writer);

        let w = BufWriter::new(File::create(name).unwrap());
        WRITER.set(Mutex::new(w)).unwrap();

        let canvas = Canvas::Grid {
            w: width as i64,
            h: height as i64,
            row: row as i64,
            col: col as i64,
        };

        // キャンバス情報を保存
        CANVAS.set(canvas.clone()).unwrap();

        {
            let mut w = WRITER.get().unwrap().lock().unwrap();
            writeln!(w, "{}", serde_json::to_string(&canvas).unwrap()).unwrap();
        }

        reset_colors();

        // restart_world();
    }

    pub fn new_turn() {
        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&Command::NewTurn).unwrap()).unwrap();
    }

    pub fn add_path(path: &[(i64, i64)]) {
        let p = path.iter().cloned().map(|(i, j)| vis::P { i, j }).collect();
        let p = Command::AddShape(Shape::Path {
            points: p,
            close: false,
            color_info: None,
        });

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&p).unwrap()).unwrap();
    }

    pub fn add_closed_path(path: &[(i64, i64)]) {
        let p = path.iter().cloned().map(|(i, j)| vis::P { i, j }).collect();
        let p = Command::AddShape(Shape::Path {
            points: p,
            close: true,
            color_info: None,
        });

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&p).unwrap()).unwrap();
    }

    pub fn add_circle(i: i64, j: i64, r: i64) {
        let p = vis::P { i, j };
        let c = Command::AddShape(Shape::Circle(p, r, None));

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&c).unwrap()).unwrap();
    }

    pub fn add_rect(i1: i64, j1: i64, i2: i64, j2: i64) {
        let p1 = P { i: i1, j: j1 };
        let p2 = P { i: i2, j: j2 };
        let r = Command::AddShape(Shape::Rect(p1, p2, None));

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&r).unwrap()).unwrap();
    }

    // グリッドの座標を指定して円を描画するメソッド
    pub fn add_grid_circle(row: usize, col: usize) {
        if let Some(Canvas::Grid {
            w,
            h,
            row: rows,
            col: cols,
        }) = CANVAS.get()
        {
            let cell_width = *w as f64 / *cols as f64;
            let cell_height = *h as f64 / *rows as f64;

            // セルの中心座標を計算
            let j = (col as f64 * cell_width + cell_width / 2.0) as i64;
            let i = (row as f64 * cell_height + cell_height / 2.0) as i64;

            // 円を描画
            add_circle(i, j, (cell_width.min(cell_height) as i64) / 3);
        }
    }

    // グリッドの座標を指定して長方形を描画するメソッド
    pub fn add_grid_rect(row: usize, col: usize) {
        if let Some(Canvas::Grid {
            w,
            h,
            row: rows,
            col: cols,
        }) = CANVAS.get()
        {
            let cell_width = *w as f64 / *cols as f64;
            let cell_height = *h as f64 / *rows as f64;

            // セルの左上と右下の座標を計算
            let j1 = (col as f64 * cell_width + 4.0) as i64;
            let i1 = (row as f64 * cell_height + 4.0) as i64;
            let j2 = ((col + 1) as f64 * cell_width - 4.0) as i64;
            let i2 = ((row + 1) as f64 * cell_height - 4.0) as i64;

            // 長方形を描画
            add_rect(i1, j1, i2, j2);
        }
    }

    pub fn add_segment(i1: i64, j1: i64, i2: i64, j2: i64) {
        let p1 = P { i: i1, j: j1 };
        let p2 = P { i: i2, j: j2 };
        let s = Command::AddShape(Shape::Segment(p1, p2, None));

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&s).unwrap()).unwrap();
    }

    pub fn set_text(text: &str) {
        let cmd = Command::SetText(text.to_string());

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&cmd).unwrap()).unwrap();
    }

    pub fn add_text(text: &str) {
        let cmd = Command::AddText(text.to_string());

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&cmd).unwrap()).unwrap();
    }

    // 色の定義
    #[derive(Debug, Clone)]
    struct CurrentColors {
        stroke: vis::Color,
        fill: Option<vis::Color>,
    }

    // 現在の色を保持する静的変数
    static CURRENT_COLORS: OnceCell<Mutex<CurrentColors>> = OnceCell::new();

    // 初期化
    fn init_colors() {
        if CURRENT_COLORS.get().is_none() {
            CURRENT_COLORS
                .set(Mutex::new(CurrentColors {
                    stroke: vis::Color {
                        r: 0,
                        g: 0,
                        b: 0,
                        a: 1.0,
                    },
                    fill: None,
                }))
                .unwrap();
        }
    }

    // 線の色を設定する関数
    pub fn set_stroke_color(r: u8, g: u8, b: u8, a: f32) {
        init_colors();
        let color = vis::Color { r, g, b, a };
        let cmd = Command::SetStrokeColor(color.clone());

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&cmd).unwrap()).unwrap();

        CURRENT_COLORS.get().unwrap().lock().unwrap().stroke = color;
    }

    // 塗りつぶし色を設定する関数
    pub fn set_fill_color(r: u8, g: u8, b: u8, a: f32) {
        init_colors();
        let color = Some(vis::Color { r, g, b, a });
        let cmd = Command::SetFillColor(color.clone());

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&cmd).unwrap()).unwrap();

        CURRENT_COLORS.get().unwrap().lock().unwrap().fill = color;
    }

    // 塗りつぶしを無効にする関数
    pub fn clear_fill_color() {
        init_colors();
        let cmd = Command::SetFillColor(None);

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&cmd).unwrap()).unwrap();

        CURRENT_COLORS.get().unwrap().lock().unwrap().fill = None;
    }

    // 色をデフォルトにリセットする関数
    pub fn reset_colors() {
        init_colors();
        let cmd = Command::ResetColors;

        let mut w = WRITER.get().unwrap().lock().unwrap();
        writeln!(w, "{}", serde_json::to_string(&cmd).unwrap()).unwrap();

        let mut colors = CURRENT_COLORS.get().unwrap().lock().unwrap();
        colors.stroke = vis::Color {
            r: 0,
            g: 0,
            b: 0,
            a: 1.0,
        };
        colors.fill = None;
    }

    // 便利なヘルパー関数
    pub fn set_red() {
        set_stroke_color(255, 0, 0, 1.0);
    }

    pub fn set_green() {
        set_stroke_color(0, 255, 0, 1.0);
    }

    pub fn set_blue() {
        set_stroke_color(0, 0, 255, 1.0);
    }

    pub fn set_fill_red() {
        set_fill_color(255, 0, 0, 1.0);
    }

    pub fn set_fill_green() {
        set_fill_color(0, 255, 0, 1.0);
    }

    pub fn set_fill_blue() {
        set_fill_color(0, 0, 255, 1.0);
    }
}

#[cfg(not(feature = "visualize"))]
#[allow(dead_code)]
mod visualize {
    pub fn new_empty_canvas(name: &str, width: usize, height: usize) {}
    pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {}
    pub fn new_turn() {}
    pub fn add_path(path: &[(i64, i64)]) {}
    pub fn add_circle(i: i64, j: i64, r: u64) {}
    pub fn add_rect(i1: i64, j1: i64, i2: i64, j2: i64) {}
    pub fn add_segment(i1: i64, j1: i64, i2: i64, j2: i64) {}
    pub fn set_text(text: &str) {}
    pub fn add_text(text: &str) {}
}

#[allow(dead_code)]
mod time {
    use std::time::Instant;

    use crate::TIMER;

    #[derive(Debug, Clone)]
    pub struct Timer {
        start: Instant,
        elapsed: f64,
        throttle: usize,
    }

    impl Timer {
        pub fn new() -> Self {
            Self {
                start: Instant::now(),
                elapsed: 0.0,
                throttle: 0,
            }
        }

        pub fn reset(&mut self) {
            self.start = Instant::now();
        }

        pub fn elapsed(&mut self) -> f64 {
            if true || self.throttle == 0xF {
                self.elapsed = self.start.elapsed().as_nanos() as f64 * 1e-6;
                self.throttle = 0;
            } else {
                self.throttle += 1;
            }

            self.elapsed
        }
    }

    pub fn elapsed() -> f64 {
        unsafe { TIMER.assume_init_mut().elapsed() }
    }
}

#[allow(dead_code)]
mod rng {
    use crate::RNG;

    pub struct Rng {
        x: u64,
    }

    pub struct RandomIter<'a, T> {
        index: usize,
        rng: Rng,
        indices: Vec<usize>,
        data: &'a [T],
    }

    impl Rng {
        pub fn new() -> Self {
            let rng = Self {
                x: 88172645463325252,
            };
            rng
        }

        pub fn from_seed(seed: u64) -> Self {
            let rng = Self { x: seed };
            rng
        }

        pub fn split(&mut self) -> Self {
            Self { x: self.xor64() }
        }

        pub fn u64(&mut self) -> u64 {
            self.xor64()
        }

        pub fn xor64(&mut self) -> u64 {
            self.x = self.x ^ (self.x.wrapping_shl(7));
            self.x = self.x ^ (self.x.wrapping_shr(9));
            self.x
        }

        pub fn next<T: From<u64>>(&mut self) -> T {
            From::from(self.xor64())
        }

        pub fn f64(&mut self) -> f64 {
            self.u64() as f64 / std::u64::MAX as f64
        }

        pub fn f32(&mut self) -> f32 {
            self.f64() as f32
        }

        pub fn usize(&mut self, n: usize) -> usize {
            (((self.xor64() & 0xFFFFFFFF) * n as u64) >> 32) as usize
        }

        pub fn i64(&mut self, n: u64) -> i64 {
            (self.xor64() % n) as i64
            // ((self.xor64() & 0xFFFFFFFF) * n as u64 >> 32) as i64
        }

        pub fn bool(&mut self) -> bool {
            self.xor64() & 1 == 0
        }

        pub fn usize_ordered_pair(&mut self, n: usize) -> (usize, usize) {
            let (mut i, mut j) = self.usize_pair(n);
            if i > j {
                std::mem::swap(&mut i, &mut j);
            }
            (i, j)
        }

        pub fn usize_ordered_4(&mut self, n: usize) -> (usize, usize, usize, usize) {
            let mut i = self.usize(n);
            let mut j = self.usize(n - 1);
            if j < i {
                std::mem::swap(&mut i, &mut j);
            } else {
                j += 1;
            }

            let mut k = self.usize(n - 2);
            if k < i {
                let t = k;
                k = j;
                j = i;
                i = t;
            } else if k + 1 < j {
                k += 1;
                std::mem::swap(&mut j, &mut k);
            } else {
                k += 2;
            }

            let mut l = self.usize(n - 3);
            if l < i {
                let t = l;
                l = k;
                k = j;
                j = i;
                i = t;
            } else if l + 1 < j {
                l += 1;
                let t = l;
                l = k;
                k = j;
                j = t;
            } else if l + 2 < k {
                l += 2;
                std::mem::swap(&mut k, &mut l);
            } else {
                l += 3;
            }

            (i, j, k, l)
        }

        pub fn usize_pair(&mut self, n: usize) -> (usize, usize) {
            let i = self.usize(n);
            let mut j = self.usize(n - 1);
            if j >= i {
                j += 1;
            }
            (i, j)
        }

        pub fn random_iter<'a, T>(&mut self, xs: &'a [T]) -> RandomIter<'a, T> {
            RandomIter {
                index: xs.len(),
                rng: self.split(),
                indices: (0..xs.len()).collect(),
                data: xs,
            }
        }

        pub fn shuffle<T>(&mut self, xs: &mut [T]) {
            for i in 0..xs.len() {
                xs.swap(i, self.usize(i + 1));
            }
        }

        pub fn choose_random<T>(&mut self, xs: impl AsRef<[T]>) -> Option<T>
        where
            T: Clone,
        {
            let xs = xs.as_ref();

            if xs.is_empty() {
                None
            } else {
                Some(xs[self.usize(xs.len())].clone())
            }
        }

        pub fn choose_random_ref<'a, T>(&mut self, xs: &'a Vec<T>) -> Option<&'a T> {
            if xs.is_empty() {
                None
            } else {
                xs.get(self.usize(xs.len()))
            }
        }

        pub fn choose_random_mut<'a, T>(&mut self, xs: &'a mut Vec<T>) -> Option<&'a mut T> {
            if xs.is_empty() {
                None
            } else {
                let n = xs.len();
                xs.get_mut(self.usize(n))
            }
        }

        // pub fn nth_element<T>(&mut self, vec: &mut [T], n: usize)
        // where
        //     T: Ord + Clone,
        // {
        //     let n = n - 1;
        //     let mut left = 0;
        //     let mut right = vec.len() - 1;
        //     loop {
        //         let i = self.usize(right - left + 1) + left;
        //         let v = vec[i].clone();
        //         let mut l = left;
        //         let mut r = right;

        //         let mut same_pivot = 0;
        //         loop {
        //             unsafe {
        //                 while l <= right {
        //                     match vec.get_unchecked(l).cmp(&v) {
        //                         std::cmp::Ordering::Less => (),
        //                         std::cmp::Ordering::Equal => {
        //                             same_pivot += 1;
        //                         }
        //                         _ => break,
        //                     }
        //                     l += 1;
        //                 }
        //                 while vec.get_unchecked(r) > &v {
        //                     r -= 1;
        //                 }
        //                 if l > r {
        //                     break;
        //                 }
        //                 // swap_unchecked
        //                 let data_ptr = vec.as_mut_ptr();
        //                 std::ptr::swap(data_ptr.add(l), data_ptr.add(r));
        //             }
        //         }
        //         if r - same_pivot < n && n <= r {
        //             // TODO same_pivot > 1 の時はpivotだけ後ろに集める
        //             break;
        //         }
        //         if n < r {
        //             right = r - same_pivot;
        //         } else {
        //             left = r + 1;
        //         }
        //     }
        // }
    }

    impl Default for Rng {
        fn default() -> Self {
            Rng::new()
        }
    }

    // impl<'a, T> Iterator for RandomIter<'a, T>
    // where
    //     T: Clone,
    // {
    //     type Item = &'a T;

    //     fn next(&mut self) -> Option<Self::Item> {
    //         if self.index == 0 {
    //             return None;
    //         }

    //         let i = self.rng.usize(self.index);
    //         let j = self.indices[i];

    //         self.index -= 1;
    //         self.indices.swap(i, self.index);

    //         Some(&self.data[j])
    //     }
    // }

    fn ensure_initialized() {}

    /// 新しいRngインスタンスを分岐して作成します。
    pub fn split() -> Rng {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().split() }
    }

    /// u64の乱数を生成します。
    pub fn u64() -> u64 {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().u64() }
    }

    /// xor64アルゴリズムによる乱数を生成します。
    pub fn xor64() -> u64 {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().xor64() }
    }

    /// 型Tの乱数を生成します。TはFrom<u64>を実装している必要があります。
    pub fn next<T: From<u64>>() -> T {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().next() }
    }

    /// 0.0〜1.0の範囲のf64乱数を生成します。
    pub fn f64() -> f64 {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().f64() }
    }

    /// 0.0〜1.0の範囲のf32乱数を生成します。
    pub fn f32() -> f32 {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().f32() }
    }

    /// 0〜n-1の範囲のusize乱数を生成します。
    pub fn usize(n: usize) -> usize {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().usize(n) }
    }

    /// 0〜n-1の範囲のi64乱数を生成します。
    pub fn i64(n: u64) -> i64 {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().i64(n) }
    }

    /// ランダムなブール値を生成します。
    pub fn bool() -> bool {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().bool() }
    }

    /// 0〜n-1の範囲の順序付きのランダムなペアを生成します。i <= j が保証されます。
    pub fn usize_ordered_pair(n: usize) -> (usize, usize) {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().usize_ordered_pair(n) }
    }

    /// 0〜n-1の範囲の順序付きのランダムな4つの値を生成します。i <= j <= k <= l が保証されます。
    pub fn usize_ordered_4(n: usize) -> (usize, usize, usize, usize) {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().usize_ordered_4(n) }
    }

    /// 0〜n-1の範囲のランダムなペアを生成します。
    pub fn usize_pair(n: usize) -> (usize, usize) {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().usize_pair(n) }
    }

    /// スライスの要素をランダムな順序で返すイテレータを作成します。
    pub fn random_iter<'a, T>(xs: &'a [T]) -> RandomIter<'a, T> {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().random_iter(xs) }
    }

    /// スライスの要素をその場でランダムにシャッフルします。
    pub fn shuffle<T>(xs: &mut [T]) {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().shuffle(xs) }
    }

    /// スライスからランダムな要素を選択します。
    pub fn choose_random<T>(xs: impl AsRef<[T]>) -> Option<T>
    where
        T: Clone,
    {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().choose_random(xs) }
    }

    /// ベクタからランダムな要素への参照を返します。
    pub fn choose_random_ref<'a, T>(xs: &'a Vec<T>) -> Option<&'a T> {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().choose_random_ref(xs) }
    }

    /// 可変ベクタからランダムな要素への可変参照を返します。
    pub fn choose_random_mut<'a, T>(xs: &'a mut Vec<T>) -> Option<&'a mut T> {
        ensure_initialized();
        unsafe { RNG.assume_init_mut().choose_random_mut(xs) }
    }
}

#[allow(dead_code)]
mod rng_log {
    use crate::{rng::Rng, RNG_LOG};

    pub struct RngLog {
        logs_index: usize,
        logs: Vec<f64>,
    }

    impl RngLog {
        pub fn from_rng(rng: &mut Rng) -> Self {
            let len = 0x10000;
            let mut logs: Vec<f64> = (0..len)
                .map(|i| ((i as f64 + 0.5) / len as f64).ln())
                .collect();

            rng.shuffle(&mut logs);

            Self {
                logs_index: 0,
                logs,
            }
        }

        pub fn ln(&mut self) -> f64 {
            let v = self.logs[self.logs_index];
            self.logs_index += 1;
            if self.logs_index == self.logs.len() {
                self.logs_index = 0;
            }
            v
        }
    }

    pub fn ln() -> f64 {
        unsafe { RNG_LOG.assume_init_mut().ln() }
    }
}

Submission Info

Submission Time
Task A - Cooperative Trash Sorting (A)
User tanzaku
Language Rust (rustc 1.70.0)
Score 747572970
Code Size 46845 Byte
Status AC
Exec Time 1953 ms
Memory 34116 KiB

Compile Error

warning: unknown lint: `static_mut_refs`
 --> src/main.rs:2:10
  |
2 | #![allow(static_mut_refs)]
  |          ^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unknown_lints)]` on by default

warning: unused import: `nalgebra::coordinates::IJKW`
 --> src/main.rs:7:5
  |
7 | use nalgebra::coordinates::IJKW;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused import: `marker::Chars`
  --> src/main.rs:10:23
   |
10 | use proconio::{input, marker::Chars};
   |                       ^^^^^^^^^^^^^

warning: unused imports: `SmallVec`, `smallvec`
  --> src/main.rs:14:16
   |
14 | use smallvec::{smallvec, SmallVec};
   |                ^^^^^^^^  ^^^^^^^^

warning: unused import: `itertools::Itertools`
 --> src/main.rs:6:5
  |
6 | use itertools::Itertools;
  |     ^^^^^^^^^^^^^^^^^^^^

warning: unused variable: `state`
   --> src/main.rs:236:24
    |
236 | fn cover_square_moenai(state: &mut State) {
    |                        ^^^^^ help: if this is intentional, prefix it with an underscore: `_state`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: variable `penalty` is assigned to, but never used
   --> src/main.rs:329:13
    |
329 |     let mut penalty = 0;
    |             ^^^^^^^
    |
    = note: consider using `_penalty` instead

warning: variable `turn` is assigned to, but never used
   --> src/main.rs:604:13
    |
604 |     let mut turn = 0;
    |             ^^^^
    |
    = note: consider using `_turn` instead

warning: unused variable: `name`
    --> src/main.rs:1189:29
     |
1189 |     pub fn new_empty_canvas(name: &str, width: usize, height: usize) {}
     |                             ^^^^ help: if this is intentional, prefix it with an underscore: `_name`

warning: unused variable: `width`
    --> src/main.rs:1189:41
     |
1189 |     pub fn new_empty_canvas(name: &str, width: usize, height: usize) {}
     |                                         ^^^^^ help: if this is intentional, prefix it with an underscore: `_width`

warning: unused variable: `height`
    --> src/main.rs:1189:55
     |
1189 |     pub fn new_empty_canvas(name: &str, width: usize, height: usize) {}
     |                                                       ^^^^^^ help: if this is intentional, prefix it with an underscore: `_height`

warning: unused variable: `name`
    --> src/main.rs:1190:28
     |
1190 |     pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {}
     |                            ^^^^ help: if this is intentional, prefix it with an underscore: `_name`

warning: unused variable: `width`
    --> src/main.rs:1190:40
     |
1190 |     pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {}
     |                                        ^^^^^ help: if this is intentional, prefix it with an underscore: `_width`

warning: unused variable: `height`
    --> src/main.rs:1190:54
     |
1190 |     pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {}
     |                                                      ^^^^^^ help: if this is intentional, prefix it with an underscore: `_height`

warning: unused variable: `row`
    --> src/main.rs:1190:69
     |
1190 |     pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {}
     |                                                                     ^^^ help: if this is intentional, prefix it with an underscore: `_row`

warning: unused variable: `col`
    --> src/main.rs:1190:81
     |
1190 |     pub fn new_grid_canvas(name: &str, width: usize, height: usize, row: usize, col: usize) {}
     |                                                                                 ^^^ help: if this is intentional, prefix it with an underscore: `_col`

warning: unused variable: `path`
    --> src/main.rs:1192:21
     |
1192 |     pub fn add_path(path: &[(i64, i64)]) {}
     |                     ^^^^ help: if this is intentional, prefix it with an underscore: `_path`

warning: unused variable: `i`
    --> src/main.rs:1193:23
     |
1193 |     pub fn add_circle(i: i64, j: i64, r: u64) {}
     |                       ^ help: if this is intentional, prefix it with an underscore: `_i`

warning: unused variable: `j`
    --> src/main.rs:1193:31
     |
1193 |     pub fn add_circle(i: i64, j: i64, r: u64) {}
     |                               ^ help: if this is intentional, prefix it with an underscore: `_j`

warning: unused variable: `r`
    --> src/main.rs:1193:39
     |
1193 |     pub fn add_circle(i: i64, j: i64, r: u64) {}
     |                                       ^ help: if this is intentional, prefix it with an underscore: `_r`

warning: unused variable: `i1`
    --> src/main.rs:1194:21
     |
1194 |     pub fn add_rect(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                     ^^ help: if this is intentional, prefix it with an underscore: `_i1`

warning: unused variable: `j1`
    --> src/main.rs:1194:30
     |
1194 |     pub fn add_rect(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                              ^^ help: if this is intentional, prefix it with an underscore: `_j1`

warning: unused variable: `i2`
    --> src/main.rs:1194:39
     |
1194 |     pub fn add_rect(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                                       ^^ help: if this is intentional, prefix it with an underscore: `_i2`

warning: unused variable: `j2`
    --> src/main.rs:1194:48
     |
1194 |     pub fn add_rect(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                                                ^^ help: if this is intentional, prefix it with an underscore: `_j2`

warning: unused variable: `i1`
    --> src/main.rs:1195:24
     |
1195 |     pub fn add_segment(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                        ^^ help: if this is intentional, prefix it with an underscore: `_i1`

warning: unused variable: `j1`
    --> src/main.rs:1195:33
     |
1195 |     pub fn add_segment(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                                 ^^ help: if this is intentional, prefix it with an underscore: `_j1`

warning: unused variable: `i2`
    --> src/main.rs:1195:42
     |
1195 |     pub fn add_segment(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                                          ^^ help: if this is intentional, prefix it with an underscore: `_i2`

warning: unused variable: `j2`
    --> src/main.rs:1195:51
     |
1195 |     pub fn add_segment(i1: i64, j1: i64, i2: i64, j2: i64) {}
     |                                                   ^^ help: if this is intentional, prefix it with an underscore: `_j2`

warning: unused variable: `text`
    --> src/main.rs:1196:21
     |
1196 |     pub fn set_text(text: &str) {}
     |                     ^^^^ help: if this is intentional, prefix it with an underscore: `_text`

warning: unused variable: `text`
    --> src/main.rs:1197:21
     |
1197 |     pub fn add_text(text: &str) {}
     |                     ^^^^ help: if this is intentional, prefix it with an underscore: `_text`

warning: variable `X` should have a snake case name
   --> src/main.rs:486:9
    |
486 |         X: usize,
    |         ^ help: convert the identifier to snake case (notice the capitalization): `x`
    |
    = note: `#[warn(non_snake_case)]` on by default

warning: variable `Y` should have a snake case name
   --> src/main.rs:487:9
    |
487 |         Y: usize,
    |         ^ help: convert the identifier to snake case (notice the capitalization): `y`

warning: variable `Z` should have a snake case name
   --> src/main.rs:488:9
    |
488 |         Z: usize,
    |         ^ help: convert the identifier to snake case (notice the capitalization): `z`

Judge Result

Set Name test_ALL
Score / Max Score 747572970 / 1500000000
Status
AC × 150
Set Name Test Cases
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
Case Name Status Exec Time Memory
test_0000.txt AC 648 ms 34020 KiB
test_0001.txt AC 539 ms 34048 KiB
test_0002.txt AC 456 ms 33856 KiB
test_0003.txt AC 950 ms 33960 KiB
test_0004.txt AC 338 ms 34004 KiB
test_0005.txt AC 723 ms 34016 KiB
test_0006.txt AC 1699 ms 33904 KiB
test_0007.txt AC 655 ms 33896 KiB
test_0008.txt AC 1940 ms 34000 KiB
test_0009.txt AC 716 ms 34116 KiB
test_0010.txt AC 874 ms 33928 KiB
test_0011.txt AC 1581 ms 33972 KiB
test_0012.txt AC 569 ms 34100 KiB
test_0013.txt AC 435 ms 33860 KiB
test_0014.txt AC 737 ms 34052 KiB
test_0015.txt AC 560 ms 34016 KiB
test_0016.txt AC 738 ms 34096 KiB
test_0017.txt AC 462 ms 34004 KiB
test_0018.txt AC 340 ms 34092 KiB
test_0019.txt AC 1919 ms 34040 KiB
test_0020.txt AC 624 ms 34032 KiB
test_0021.txt AC 768 ms 33852 KiB
test_0022.txt AC 406 ms 34112 KiB
test_0023.txt AC 989 ms 34004 KiB
test_0024.txt AC 465 ms 34004 KiB
test_0025.txt AC 315 ms 34100 KiB
test_0026.txt AC 621 ms 34016 KiB
test_0027.txt AC 1247 ms 34028 KiB
test_0028.txt AC 984 ms 34016 KiB
test_0029.txt AC 1925 ms 34004 KiB
test_0030.txt AC 812 ms 34016 KiB
test_0031.txt AC 1909 ms 34112 KiB
test_0032.txt AC 1239 ms 34096 KiB
test_0033.txt AC 1476 ms 33996 KiB
test_0034.txt AC 542 ms 34012 KiB
test_0035.txt AC 848 ms 34020 KiB
test_0036.txt AC 1491 ms 34004 KiB
test_0037.txt AC 554 ms 33904 KiB
test_0038.txt AC 524 ms 34100 KiB
test_0039.txt AC 523 ms 34000 KiB
test_0040.txt AC 323 ms 33964 KiB
test_0041.txt AC 632 ms 34028 KiB
test_0042.txt AC 580 ms 34112 KiB
test_0043.txt AC 318 ms 34100 KiB
test_0044.txt AC 770 ms 34000 KiB
test_0045.txt AC 770 ms 34004 KiB
test_0046.txt AC 301 ms 33944 KiB
test_0047.txt AC 1299 ms 33956 KiB
test_0048.txt AC 654 ms 34008 KiB
test_0049.txt AC 846 ms 34084 KiB
test_0050.txt AC 749 ms 33860 KiB
test_0051.txt AC 704 ms 34004 KiB
test_0052.txt AC 407 ms 33908 KiB
test_0053.txt AC 312 ms 34004 KiB
test_0054.txt AC 1015 ms 33996 KiB
test_0055.txt AC 302 ms 34060 KiB
test_0056.txt AC 529 ms 34012 KiB
test_0057.txt AC 798 ms 34004 KiB
test_0058.txt AC 344 ms 33960 KiB
test_0059.txt AC 317 ms 34008 KiB
test_0060.txt AC 443 ms 34004 KiB
test_0061.txt AC 466 ms 34112 KiB
test_0062.txt AC 513 ms 34016 KiB
test_0063.txt AC 365 ms 34048 KiB
test_0064.txt AC 939 ms 33996 KiB
test_0065.txt AC 700 ms 34020 KiB
test_0066.txt AC 322 ms 34012 KiB
test_0067.txt AC 491 ms 33992 KiB
test_0068.txt AC 1027 ms 34056 KiB
test_0069.txt AC 712 ms 34040 KiB
test_0070.txt AC 351 ms 34104 KiB
test_0071.txt AC 502 ms 34052 KiB
test_0072.txt AC 378 ms 33964 KiB
test_0073.txt AC 1780 ms 34112 KiB
test_0074.txt AC 1389 ms 34100 KiB
test_0075.txt AC 1031 ms 34056 KiB
test_0076.txt AC 282 ms 33960 KiB
test_0077.txt AC 1906 ms 34016 KiB
test_0078.txt AC 685 ms 33844 KiB
test_0079.txt AC 536 ms 33848 KiB
test_0080.txt AC 772 ms 34100 KiB
test_0081.txt AC 543 ms 33904 KiB
test_0082.txt AC 358 ms 34096 KiB
test_0083.txt AC 488 ms 34016 KiB
test_0084.txt AC 1513 ms 34028 KiB
test_0085.txt AC 1274 ms 34092 KiB
test_0086.txt AC 995 ms 34024 KiB
test_0087.txt AC 300 ms 34092 KiB
test_0088.txt AC 1216 ms 34052 KiB
test_0089.txt AC 530 ms 33904 KiB
test_0090.txt AC 945 ms 34092 KiB
test_0091.txt AC 537 ms 34000 KiB
test_0092.txt AC 564 ms 34024 KiB
test_0093.txt AC 1870 ms 33824 KiB
test_0094.txt AC 392 ms 33856 KiB
test_0095.txt AC 1058 ms 34008 KiB
test_0096.txt AC 641 ms 33908 KiB
test_0097.txt AC 487 ms 34096 KiB
test_0098.txt AC 1953 ms 34056 KiB
test_0099.txt AC 879 ms 33964 KiB
test_0100.txt AC 1399 ms 34012 KiB
test_0101.txt AC 518 ms 33952 KiB
test_0102.txt AC 1462 ms 34016 KiB
test_0103.txt AC 637 ms 34092 KiB
test_0104.txt AC 645 ms 34016 KiB
test_0105.txt AC 816 ms 34108 KiB
test_0106.txt AC 636 ms 34008 KiB
test_0107.txt AC 553 ms 33900 KiB
test_0108.txt AC 1548 ms 34036 KiB
test_0109.txt AC 1268 ms 34000 KiB
test_0110.txt AC 789 ms 34032 KiB
test_0111.txt AC 775 ms 33948 KiB
test_0112.txt AC 1922 ms 34016 KiB
test_0113.txt AC 1882 ms 33864 KiB
test_0114.txt AC 1098 ms 34004 KiB
test_0115.txt AC 502 ms 34040 KiB
test_0116.txt AC 1058 ms 34116 KiB
test_0117.txt AC 721 ms 34000 KiB
test_0118.txt AC 458 ms 34092 KiB
test_0119.txt AC 600 ms 34056 KiB
test_0120.txt AC 430 ms 33984 KiB
test_0121.txt AC 1031 ms 34024 KiB
test_0122.txt AC 1284 ms 33956 KiB
test_0123.txt AC 885 ms 34004 KiB
test_0124.txt AC 621 ms 33972 KiB
test_0125.txt AC 928 ms 33876 KiB
test_0126.txt AC 1936 ms 34096 KiB
test_0127.txt AC 839 ms 33956 KiB
test_0128.txt AC 991 ms 34032 KiB
test_0129.txt AC 426 ms 34016 KiB
test_0130.txt AC 1018 ms 34004 KiB
test_0131.txt AC 948 ms 33944 KiB
test_0132.txt AC 941 ms 34040 KiB
test_0133.txt AC 614 ms 34016 KiB
test_0134.txt AC 356 ms 33952 KiB
test_0135.txt AC 1927 ms 33896 KiB
test_0136.txt AC 1283 ms 34056 KiB
test_0137.txt AC 406 ms 33920 KiB
test_0138.txt AC 643 ms 33860 KiB
test_0139.txt AC 848 ms 34088 KiB
test_0140.txt AC 1363 ms 33956 KiB
test_0141.txt AC 1914 ms 34112 KiB
test_0142.txt AC 670 ms 34004 KiB
test_0143.txt AC 1038 ms 34008 KiB
test_0144.txt AC 357 ms 34096 KiB
test_0145.txt AC 1272 ms 34092 KiB
test_0146.txt AC 1358 ms 34028 KiB
test_0147.txt AC 520 ms 34020 KiB
test_0148.txt AC 420 ms 34112 KiB
test_0149.txt AC 1375 ms 34020 KiB