Edited at

競技プログラミングにてミュータブルなグローバル変数を使ってみたら書くスピードが上がりそう

※ この記事はグローバル変数やUnsafeの多用を推奨するものではありません。

Rustで競技プログラミングをする際外部変数を関数内で使用するためにはクロージャを使うと良いのですが、dfsのように再帰を行う際クロージャを使うと書くのが面倒なことになるので関数を普通に使うことになるのですが、C++erみたくglobal変数を使ってみたら引数を長々と書かなくてよくなり、より早く書けそうと(副作用が少ない世界が最高だと思ってこのRustの世界に来たのに本末転倒なことを)思ったので以下それについて書きます。

UnsafeなRustの使用経験がほとんどないため

思うところがあれば、

コメントしていただけると嬉しいです。


global変数の宣言方法


配列

// immutableの場合

static D: &'static [usize] = & [1, 2, 3];

// mutableの場合
static mut D: &'static mut [[usize; 9]; 9] = &mut [[0; 9]; 9];


変数

// immutableの場合

const N: usize = 30;

// mutableの場合
static mut N: usize = 30;


global変数の改変方法

static mut で宣言した変数の変更はunsafeで指定した範囲内でのみ可能となります。

unsafe fn dfs() {

...
D[i] = 2;
...
}

または

fn dfs() {

unsafe {
...
D[i] = 2;
...
}
}


static mut d: &'static mut [[usize; NMAX+1]; NMAX+1] = &mut [[INF; NMAX + 1]; NMAX + 1];

static mut r: &'static mut [usize] = &mut [0; 9];
static mut res: usize = 0;

fn dfs(c: usize, las: Option<usize>, dist: usize) {
unsafe {
if c == R+1 {
if res>dist {
res = dist;
return;
}
}
for i in 1..R +1 {
if !used[i] {
used[i] = true;
if las == None {
dfs(c+1, Some(i), 0);
}
else {
dfs(c+1, Some(i), dist+d[r[las.unwrap()]][r[i]]);
}
used[i] = false;
}
}
}
}

見た感じかなりC++っぽい書き心地になったと思うのではないでしょうか?

美味しいです。味覚えちゃいました