【Rust】ダイクストラ法

fn dijkstra(edges: Vec<Vec<[usize; 2]>>, num_v: usize)  -> Vec<usize>{
    let inf = 999;
    let mut dist = Vec::new();
    for _ in 0..num_v {
        dist.push(inf);
    }
    dist[0] = 0;

    let mut q = Vec::new();
    for i in 0..num_v {
        q.push(i);
    }
    
    while *&q.len() > 0 {
        let mut r = q[0];
        for i in &q{
            if dist[*i] < dist[r] {
                r = *i;
            }
        } 
        let n = q.iter().position(|n| *n == r).unwrap();
        let u = q[n];
        q.retain(|&x| x != u);
        
        for i in edges[u].clone() {
            if dist[i[0]] > dist[u] + i[1] {
                dist[i[0]] = dist[u] + i[1];
            }
        }      
    }
    return dist;
}

fn main() {
    let edges = vec![
        vec![[1, 4], [2, 3]],
        vec![[2, 1], [3, 1], [4, 5]],
        vec![[5, 2]],
        vec![[4, 3]],
        vec![[6, 2]],
        vec![[4, 1], [6, 4]],
        vec![],
    ];
    println!("{:?}", edges);

    println!("{:?}", dijkstra(edges, 7));
}

Compiling rust v0.1.0 (/home/vagrant/dev/algorithm/rust)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/rust`
[[[1, 4], [2, 3]], [[2, 1], [3, 1], [4, 5]], [[5, 2]], [[4, 3]], [[6, 2]], [[4, 1], [6, 4]], []]
[0, 4, 3, 5, 6, 5, 8]

おおおお、これは凄いな…

【Rust】bellman fordアルゴリズム

最短距離を探すアルゴリズム

fn bellman_ford(edges: Vec<[usize; 3]>, num_v: usize)  -> Vec<usize>{
    let inf = 999;
    let mut dist = Vec::new();
    for _ in 0..num_v {
        dist.push(inf);
    }
    

    dist[0] = 0;
    let mut changed = true;

    while changed == true {
        changed = false;
        for edge in &edges {
            if dist[edge[1]] > dist[edge[0]] + edge[2] {
                dist[edge[1]] =  dist[edge[0]] + edge[2];
                changed = true;
            }
        }
    }
    return dist;
}

fn main() {
    let edges = vec![[0, 1, 4], [0, 2, 3], [1, 2, 1], [1, 3, 1], 
    [1, 4, 5], [2, 5, 2], [4, 6, 2], [5, 4, 1], 
    [5, 6, 4]];

    let dist = bellman_ford(edges, 7);
    println!("{:?}", dist);
}

Compiling rust v0.1.0 (/home/vagrant/dev/algorithm/rust)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s
Running `target/debug/rust`
[0, 4, 3, 5, 6, 5, 8]

いまいちよーわからん…

【Rust】最短経路問題

M, N = 6, 5

route = [[0 for i in range(N + 1)]for j in range(M + 1)]

print(route)

$ python3 test.py
[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]

fn main() {
    let M = 6;
    let N = 5;

    let mut route: Vec<Vec<usize>> = Vec::new();
    
    for _ in 0..(M+1) {
        let mut L: Vec<usize> = Vec::new();
        for _ in 0..(N+1) {
            L.push(0);
        } 
        route.push(L);
    }
    println!("{:?}", route);
}

[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]

fn main() {
    let M = 6;
    let N = 5;

    let mut route: Vec<Vec<usize>> = Vec::new();
    
    for _ in 0..(M+1) {
        let mut L: Vec<usize> = Vec::new();
        for _ in 0..(N+1) {
            L.push(0);
        } 
        route.push(L);
    }

    for i in 0..(M+1){
        route[i][0] = 1;
    }
    
    for i in 1..(N+1) {
        route[0][i] = 1;
        for j in 1..(M+1) {
            route[j][i] = route[j - 1][i] + route[j][i - 1];
        }
    }
    println!("{:?}", route);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/rust`
[[1, 1, 1, 1, 1, 1], [1, 2, 3, 4, 5, 6], [1, 3, 6, 10, 15, 21], [1, 4, 10, 20, 35, 56], [1, 5, 15, 35, 70, 126], [1, 6, 21, 56, 126, 252], [1, 7, 28, 84, 210, 462]]

おおお、なるほど、これは凄い。

実はこう書ける

fn search(m: usize, n: usize) -> usize {
    if (m == 0) || (n == 0) {
        return 1
    }

    return search(m-1, n) + search(m, n - 1);
}

fn main() {
    let M = 6;
    let N = 5;

    println!("{}", search(M, N));
}

なるほど、これは凄い。
経路の問題も基本は、位置を数字で表現するのね。

【Rust】クイックソート

アルゴリズム的にはこれが一番簡単。それでこれが早いのか。。

fn quick_sort(data: Vec<i32>) -> Vec<i32> {

    if data.len() <= 1{
        return data;
    }
    let pivot = data[0];
    let mut left: Vec<i32> = Vec::new();
    let mut right: Vec<i32> = Vec::new();
    let mut result: Vec<i32> = Vec::new();
    let mut same = 0;

    for i in data {
        if i < pivot {
            left.push(i);
        } else if i > pivot {
            right.push(i);
        } else {
            same += 1;
        }
    }
    left = quick_sort(left);
    right = quick_sort(right);
    result.append(&mut left);
    if same != 0 {
        for i in 0..same {
            result.push(pivot);
        }
    }
    result.append(&mut right);

    return result;
}

fn main() {
    let mut data = vec![6, 15, 4, 2, 8, 5, 11, 9, 7, 13];

    println!("{:?}", quick_sort(data));
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.37s
Running `target/debug/rust`
[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]

【Rust】マージソート

大容量データの計算量が早い。

fn merge_sort(data: Vec<usize>) -> Vec<usize>{
    if data.len() <= 1 {
        return data;
    }
        
    let mid = data.len() / 2;
    let mut left: Vec<usize> = merge_sort(data[0..mid].to_vec());
    let mut right: Vec<usize>  = merge_sort(data[mid..].to_vec());

    return merge(left, right);
}

fn merge(left: Vec<usize>, right: Vec<usize>) -> Vec<usize> {
    let mut result: Vec<usize> = Vec::new();

    let mut i = 0;
    let mut j = 0;

    while (i < left.len()) && (j < right.len()) {
        if left[i] <= right[j] {
            result.push(left[i]);
            i += 1;
        } else {
            result.push(right[j]);
            j += 1;
        }
    }

    if i < left.len() {
        result.append(&mut left[i..].to_vec());
    }
    if j < right.len() {
        result.append(&mut right[j..].to_vec());
    }
    return result;
}

fn main() {
    let mut data = vec![6, 15, 4, 2, 8, 5, 11, 9, 7, 13];
    println!("{:?}", merge_sort(data));
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s
Running `target/debug/rust`
[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]

何だこれは… 凄いな

【Rust】ヒープソート

ヒープは木構造で構成され、子ノードは常に親ノードより大きいか等しい。
ヒープに要素を追加する場合は、木構造の最後に要素を追加し、親と要素を比較して親よりも小さければ親と交換する。
最小値は必ずルートにある。
取り出した場合は、最後の要素を一番上に移して木を再構成する。

木構造が
A
B C
D E F G
の時、リストでは
[ABCDEFG] で表現する。


fn main() {
    
    let mut data = [6, 15, 4, 2, 8, 5, 11, 9, 7, 13];

    for i in 0..data.len() {
        let mut j = i;
        while ( j > 0 ) && (data[(j - 1) / 2] < data[j]) {
            data.swap(j, (j - 1) / 2);
            j = (j - 1) / 2;
        }
    }
    println!("{:?}", data);

    let mut n: Vec<usize> = Vec::new();
    for i in 1..(data.len()+1) {
        n.push(i.try_into().unwrap());
    }
    n.reverse();

    for i in n {
        data.swap(0, i - 1);
        let mut j = 0;
        while(((2 * j + 1) < (i - 1)) && (data[j] < data[2 * j + 1])) || (((2 * j + 2) < (i - 1)) && (data[j] < data[2 * j + 2])) {
            if ((2 * j + 2) == (i - 1)) || (data[2 * j + 1] > data[2 * j + 2]) {
                data.swap(2 * j + 1, j);
                j = 2 * j + 1;
            } else {
                data.swap(2 * j + 2, j);
                j = 2 * j + 2;
            } 
        }
    }
    println!("{:?}", data);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.37s
Running `target/debug/rust`
[15, 13, 11, 8, 9, 4, 5, 2, 7, 6]
[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]

ヒープの構成のところで、
15
13 11
8 9 4 5
2 7 6
と、ヒープの構成になっていることがわかる。
heap sortはbubble, insert, selection sortより早いことがわかっている。

関数化する。

use std::collections::VecDeque;

fn heapify(data: &mut VecDeque<usize>, i: usize) {
    let left = 2 * i + 1;
    let right = 2 * i + 2;
    let size = data.len() - 1;
    let mut min = i;
    if left <= size && data[min] > data[left] {
        min = left;
    }
    if right <= size && data[min] > data[right] {
        min = right;
    }
    if min != i {
        data.swap(min, i);
        heapify(data, min);
    }
}

fn main() {
    
    let mut data = VecDeque::from([6, 15, 4, 2, 8, 5, 11, 9, 7, 13]);

    let mut n: Vec<usize> = Vec::new();
    for i in 0..(data.clone().len()/2) {
        n.push(i.try_into().unwrap());
    }
    n.reverse();

    println!("{:?}", n);

    for i in n {
        heapify(&mut data, i);
    }
    println!("{:?}", data);

    let mut sorted_data: VecDeque<usize> = VecDeque::new();

    for _ in 0..(data.len()) {
        let k = data.clone().len();
        data.swap(0, k - 1);
        sorted_data.push_back(data.pop_back().unwrap());
        println!("{:?}", sorted_data);
        println!("{:?}", data);
        if (k != 1) {
            heapify(&mut data, 0);
        }
    }

    println!("{:?}", sorted_data);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.41s
Running `target/debug/rust`
[4, 3, 2, 1, 0]
[2, 6, 4, 7, 8, 5, 11, 9, 15, 13]
[2]
[13, 6, 4, 7, 8, 5, 11, 9, 15]
[2, 4]
[15, 6, 5, 7, 8, 13, 11, 9]
[2, 4, 5]
[9, 6, 11, 7, 8, 13, 15]
[2, 4, 5, 6]
[15, 7, 11, 9, 8, 13]
[2, 4, 5, 6, 7]
[13, 8, 11, 9, 15]
[2, 4, 5, 6, 7, 8]
[15, 9, 11, 13]
[2, 4, 5, 6, 7, 8, 9]
[15, 13, 11]
[2, 4, 5, 6, 7, 8, 9, 11]
[15, 13]
[2, 4, 5, 6, 7, 8, 9, 11, 13]
[15]
[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]
[]
[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]

ほう、これは凄いな。というか、debugしながらやらないと理解できない。。

【Rust】スタック(push, pop)を実装する

rustのvectorのスタックはpush, popを使う

fn main() {
    
    let mut stack: Vec<i32> = Vec::new();

    stack.push(3);
    stack.push(5);
    stack.push(2);

    println!("{:?}", stack);

    let temp = stack.pop();

    println!("{:?}", temp);
    println!("{:?}", stack);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/rust`
[3, 5, 2]
Some(2)
[3, 5]

最初に入れたものから取り出すにはお馴染みのVecDequeを使います。

use std::collections::VecDeque;

fn main() {
    
    let mut stack: VecDeque<i32> = VecDeque::new();

    stack.push_back(3);
    stack.push_back(5);
    stack.push_back(2);

    println!("{:?}", stack);

    let temp = stack.pop_front();

    println!("{:?}", temp);
    println!("{:?}", stack);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.57s
Running `target/debug/rust`
[3, 5, 2]
Some(3)
[5, 2]

【Rust】バブルソート

後ろから順番に定まっているのが分かります。

fn main() {
    let mut data = [6, 15, 4, 2, 8, 5, 11, 9, 7, 13];

    for i in 0..data.len() {
        for j in 0..(data.len() - i - 1) {
            if data[j] > data[j + 1] {
                data.swap(j, (j + 1));
            }
            println!("sorted data:{:?}", data);
        }
    }
    println!("sorted data:{:?}", data);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.82s
Running `target/debug/rust`
sorted data:[6, 15, 4, 2, 8, 5, 11, 9, 7, 13]
sorted data:[6, 4, 15, 2, 8, 5, 11, 9, 7, 13]
sorted data:[6, 4, 2, 15, 8, 5, 11, 9, 7, 13]
sorted data:[6, 4, 2, 8, 15, 5, 11, 9, 7, 13]
sorted data:[6, 4, 2, 8, 5, 15, 11, 9, 7, 13]
sorted data:[6, 4, 2, 8, 5, 11, 15, 9, 7, 13]
sorted data:[6, 4, 2, 8, 5, 11, 9, 15, 7, 13]
sorted data:[6, 4, 2, 8, 5, 11, 9, 7, 15, 13]
sorted data:[6, 4, 2, 8, 5, 11, 9, 7, 13, 15]
sorted data:[4, 6, 2, 8, 5, 11, 9, 7, 13, 15]
sorted data:[4, 2, 6, 8, 5, 11, 9, 7, 13, 15]
sorted data:[4, 2, 6, 8, 5, 11, 9, 7, 13, 15]
sorted data:[4, 2, 6, 5, 8, 11, 9, 7, 13, 15]
sorted data:[4, 2, 6, 5, 8, 11, 9, 7, 13, 15]
sorted data:[4, 2, 6, 5, 8, 9, 11, 7, 13, 15]
sorted data:[4, 2, 6, 5, 8, 9, 7, 11, 13, 15]
sorted data:[4, 2, 6, 5, 8, 9, 7, 11, 13, 15]
sorted data:[2, 4, 6, 5, 8, 9, 7, 11, 13, 15]
sorted data:[2, 4, 6, 5, 8, 9, 7, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 9, 7, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 9, 7, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 9, 7, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 7, 9, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 7, 9, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 7, 9, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 7, 9, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 7, 9, 11, 13, 15]
sorted data:[2, 4, 5, 6, 8, 7, 9, 11, 13, 15]
sorted data:[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]

fn main() {
    let mut data = [6, 15, 4, 2, 8, 5, 11, 9, 7, 13];

    let mut change = true;
    for i in 0..data.len() {
        if (change != true)  {
            break;
        }
        change = false;
        for j in 0..(data.len() - i - 1) {
            if data[j] > data[j + 1] {
                data.swap(j, (j + 1));
            }
            println!("sorted data:{:?}", data);
            change = true;
        }
    }
    println!("sorted data:{:?}", data);
}

【Rust】挿入ソート

挿入ソートも n * (n – 1) / 2 の計算量になる。
対象データを一時領域に確保しておき、値が大きかどうかを判定して、大きい場合は入れ替えるという作業を繰り返す。
usizeは-にならないため、 j== 0の時は判定しています。

fn main() {
    let mut data = [6, 15, 4, 2, 8, 5, 11, 9, 7, 13];

    for i in 1..data.len() {
        let temp = data[i];
        let mut j = i - 1;
  
        while (j >= 0) && (data[j] > temp) {
            data[j + 1] = data[j];
            if j == 0 {
                break;
            }
            j -= 1;
        }
        if j == 0 && (data[j] > temp) {
            data[0] = temp;
        } else {
            data[j + 1] = temp;
        }
        println!("sorted data:{:?}", data);
    }
    println!("sorted data:{:?}", data);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
Running `target/debug/rust`
sorted data:[6, 15, 4, 2, 8, 5, 11, 9, 7, 13]
sorted data:[4, 6, 15, 2, 8, 5, 11, 9, 7, 13]
sorted data:[2, 4, 6, 15, 8, 5, 11, 9, 7, 13]
sorted data:[2, 4, 6, 8, 15, 5, 11, 9, 7, 13]
sorted data:[2, 4, 5, 6, 8, 15, 11, 9, 7, 13]
sorted data:[2, 4, 5, 6, 8, 11, 15, 9, 7, 13]
sorted data:[2, 4, 5, 6, 8, 9, 11, 15, 7, 13]
sorted data:[2, 4, 5, 6, 7, 8, 9, 11, 15, 13]
sorted data:[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]
sorted data:[2, 4, 5, 6, 7, 8, 9, 11, 13, 15]

途中経過を見ると美しいが、これも計算量が多くなる模様。

【Rust】○✖️ゲーム(minmax)

use rand::Rng;
use std::cmp::Ordering;

static goal:[i32; 8] = [ 0b111000000, 0b000111000, 0b000000111, 0b100100100,
            0b010010010, 0b001001001, 0b100010001, 0b001010100];

fn check(player: i32) -> bool {
    for mask in goal {
        if player & mask == mask {
            return true
        }
    }
    return false 
}

fn minmax(p1: i32, p2: i32, turn: bool) -> i32 {
    if check(p2) {
        if turn {
            return 1
        } else {
            return -1
        }
    }
    let board: i32 = p1 | p2;
    if board == 0b111111111{
        return 0
    }

    let mut w = Vec::new();
    for i in 0..9 {
        if board & (1 << i) == 0 {
            w.push(i);
        }
    }

    let mut k = Vec::new();
    if turn {
        for i in w {
           k.push(minmax(p2, p1 | (1 << i), !turn))
        }
        return *k.iter().min().unwrap();
    } else {
        for i in w {
            k.push(minmax(p2, p1 | (1 << i), !turn))
        }
        return *k.iter().max().unwrap();
    }
    

}

fn play(p1: i32, p2: i32, turn: bool) {
    if check(p2) {
        println!("{:09b}, {:09b}", p1, p2);
        return
    } 

    let board: i32 = p1 | p2;
    if board == 0b111111111{
        println!("{:09b}, {:09b}", p1, p2);
        return
    }
    let mut w = Vec::new();
    for i in 0..9 {
        if board & (1 << i) == 0 {
            w.push(i);
        }
    }

    let mut r  = Vec::new();
    for i in w.clone() {
        r.push(minmax(p2, p1 | (1 << i), true))
    }
    let n = r.iter()
        .enumerate()
        .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal))
        .map(|(index, _)| index).unwrap();
    let j = w[n];
    play(p2, p1 | (1 << j), !turn);
}

fn main() {
    play(0, 0, true);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/rust`
001110010, 110001101

う、なんか違うな…

    let mut rnd = rand::thread_rng();
    let k = rnd.gen_range(1..n);
    let j = w[k];

このようにすると、ランダム性が出る。。