[Rust] 調べたこと、やったこと、メモ

# リンク集

[C++入門](https://amzn.to/2Nf1ntW)
[プログラミングRust (日本語) ](https://amzn.to/2Bs7vvS)
[プログラミング言語Rust入門](https://amzn.to/2BkGP0n)
[実践Rust入門](https://amzn.to/2zRbu4W)

[std::検索](https://doc.rust-lang.org/stable/std/)
[[wiki] Rust](https://ja.wikipedia.org/wiki/Rust_(プログラミング言語))


# 自分の記事

[[基礎] 数学](https://qiita.com/osorezugoing/items/3241f290eec65b8527f3)
[[基礎] シグネチャ](https://qiita.com/osorezugoing/items/508601d7d14ba2cb454c)
[[基礎] ファイルハンドル](https://qiita.com/osorezugoing/items/ed1ab48a155425f058a7)
[[Rust] メモリの知見をふやす](https://qiita.com/osorezugoing/items/a70a4fdf91f1c0bf6fc6)

## チュートリアルメモ
[[Rust] チュートリアル① 所有権〜構造体、Enumまで](https://qiita.com/osorezugoing/items/59d8d02cda65b34f91bb)
[[Rust] チュートリアル② モジュール〜ライフタイムまで](https://qiita.com/osorezugoing/items/80e4a599336603e9246a)
[[Rust] チュートリアル③ 入出力プロジェクト〜イテレータ](https://qiita.com/osorezugoing/items/dd140bca687c580e02a0)
[[Rust] チュートリアル④ CargoとCrates.io〜循環参照まで](https://qiita.com/osorezugoing/items/335d03a7bf15eb4d25da)
[[Rust] チュートリアル⑤ 並列性〜パターン記法まで](https://qiita.com/osorezugoing/items/941488b9fc661ad94111)
[[Rust] チュートリアル⑥　高度な型〜高度な関数とクロージャまで
](https://qiita.com/osorezugoing/items/66fc3406e3aff046f0a2)[[Rust] チュートリアル⑦　マルチスレッドのWebサーバーを構築する〜
](https://qiita.com/osorezugoing/items/abccef261fa10ea84998)


# AtCoderメモ

[[Rust] AtCoderをやる Rustを褒める　C/C+をディスる
](https://qiita.com/osorezugoing/items/0034acb1a1d8558d45c4)


## ビット全探索

ビットを用いて、求めたい対象のすべての組み合わせを表す。
数学的にいえば、ある集合のべき集合を求めるという。

具体的なべき乗の生成方法は、２重ループを回して行う。
最初のループで部分集合の全探索(べき集合を求める)をする。
そして、その内側のループでbitの表す集合を求める。


### [復習] べき集合とは

>集合 A に対して、A の部分集合を全て集めたものを A のべき集合
>集合の集合であり、集合族ともいわれる
>べき集合の要素数 = ２の要素数乗 ( 2^n )

```markdown
`
集合A
`
A = {a,b,c}
`
集合Aのべき集合の要素数 
2 ^ n 
n = 3 
2 ^ 3 = 2 x 2 x 2 = 8 
`
Φ,
{a},{b},{c}
{a,b},{a,c},{b,c}
{a,b,c}
```

### [実践] bit全探索

3種類の配列があり、2つの配列の同じ要素を足し合わせたときに、すべて１０以上になる配列の組み合わせはどれか?

a = [4, 3, 5];
b = [2, 6, 8];
c = [5, 5, 9];
d = [6, 3, 1];
e = [5, 4, 3];
f = [5, 8, 7];

例). 
a[0] + b[0] = 4 + 2 = 6  ☓
c[0] + d[0] = 5 + 6 = 11 ◯


```rust
fn main() {
	let a = [4, 3, 5];
	let b = [2, 6, 8];
	let c = [5, 5, 9];
	let d = [6, 3, 1];
	let e = [5, 4, 3];
	let f = [5, 8, 7];
	let arr = vec![a, b, c, d, e, f];

	let mut ans = 0;
	let n = arr.len(); // 要素数
	for bit in 0..1 << n {
		let mut idx: Vec<usize> = Vec::new(); // 組み合わせを格納する箱
		for i in 0..n {
			if bit & (1 << i) != 0 {
				idx.push(i);
			}
		}
		// 2つの組み合わせ
		if idx.len() == 2 {
			let v1 = arr[idx[0]];
			let v2 = arr[idx[1]];
			println!("v1:{:?}, v2:{:?}", v1, v2);
			for i in 0..3 {
				if v1[i] + v2[i] < 10 {
					break;
				}
				if i == 2 {
					ans += 1;
				}
			}
		}
	}
	println!("ans={}", ans);
}

```
```
idx:[0, 1] [4, 3, 5], [2, 6, 8]
idx:[0, 2] [4, 3, 5], [5, 5, 9]
idx:[1, 2] [2, 6, 8], [5, 5, 9]
idx:[0, 3] [4, 3, 5], [6, 3, 1]
idx:[1, 3] [2, 6, 8], [6, 3, 1]
idx:[2, 3] [5, 5, 9], [6, 3, 1]
idx:[0, 4] [4, 3, 5], [5, 4, 3]
idx:[1, 4] [2, 6, 8], [5, 4, 3]
idx:[2, 4] [5, 5, 9], [5, 4, 3]
idx:[3, 4] [6, 3, 1], [5, 4, 3]
idx:[0, 5] [4, 3, 5], [5, 8, 7]
idx:[1, 5] [2, 6, 8], [5, 8, 7]
idx:[2, 5] [5, 5, 9], [5, 8, 7]
idx:[3, 5] [6, 3, 1], [5, 8, 7]
idx:[4, 5] [5, 4, 3], [5, 8, 7]

ans=2
```

[AtCoder abc167 C問題 C - Skill Up](https://atcoder.jp/contests/abc167/tasks/abc167_c)

```rust
use proconio::{fastout, input};

const INF: usize = 1 << 30;

#[fastout]
fn main() {
	input! {
		n: usize,
		m: usize,
		x: usize,
		ca: [(usize, [usize; m]); n], // CとAをタプルに入れる
	}

	let mut ans = INF;

	// bit全探索
	for bit in 0..(1 << n) {
		let mut cost = 0;
		let mut skill = vec![0_usize; m]; // スキルの合計値を入れる
		for i in 0..n {
			if bit >> i & 1 == 1 {
				// ------------------
				// ビットロジックで生成した任意のインデックスに対する値を合計していく
				// ------------------
				// コストを加算する
				cost += ca[i].0;
				for j in 0..m {
					// 理解度を加算してskill箱に入れる
					skill[j] += ca[i].1[j];
				}
			}
		}
		// 値が入れ終わったら、各skillの合計値の全てがが目標の満足値を超えているか？
		// そして、超えてていた場合、今回のコストが、暫定の最小コストよりも小さければ最小コストとする
		if skill.iter().fold(true, |ans, &s| ans && s >= x) {
			ans = std::cmp::min(cost, ans);
		}
	}

	if ans >= INF {
		println!("-1");
	} else {
		println!("{}", ans);
	}
}

```

## ビットシフト

２進数のビットの位置をずらす演算のことをシフト演算といい、左シフトと右シフトがある
左に1ビットシフトすると任意の数値は２倍となり、右に１ビットシフトすると1/倍となる


```rust
fn main() {
	for i in 0..=64 {
        // 1のままだと32ビットシフト以上できない 
        // println!("1を{}ビット左シフトさせると、{}", i, 1 << i); 
        // (Rustはプリミティブな数はデフォルトでi32なので)
		println!("1を{}ビット左シフトさせると、{}", i, 1_u64 << i); 
	}
}
```
```
1を0ビット左シフトさせると、1
1を1ビット左シフトさせると、2
1を2ビット左シフトさせると、4
1を3ビット左シフトさせると、8
1を4ビット左シフトさせると、16
1を5ビット左シフトさせると、32
1を6ビット左シフトさせると、64
... snip ...
1を63ビット左シフトさせると、9223372036854775808
```

## 複数の配列を格納する (多次元配列)

```rust
use proconio::input;

fn main() {
	input! {
		// 2次元配列
		v: [[usize; 3]; 3],
	}
	println!("{:?}", v);
}

// input
// 1 2 3
// 4 5 6
// 7 8 9

// output
// [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
```


# etc (未整理)


## as_プリミティブ型 じゃない書き方

```rust
let a:i64 = 100.0;
let b = 100f64; // 100_f64でもOk
assert_eq!(a, b);

// output
// 
```

## 配列の合計


### iterとsumメソッドを使う。

```rust
let v = vec![1,2,3,4];
let sum = v.iter().sum();

// output
// 10
```

### iterとfoldメソッドを使う

```rust
let v = vec![1,2,3,4];
// fold(初期値, |上書きする値, 配列の値)| 上書きする値 + 配列の値)
let sum = v.iter().fold(0, |sum, elem| sum + elem);

// output
// 10
```

## (0..n=)

レンジ範囲でnを含むことを意味する

```rust
fn main() {
    let n = 3;
	for i in 0..=n {
		println!("{}", i);
	}
}

// output
// 0
// 1
// 2
// 3
```

## strと&str

Rustのコンパイラは特定の型の値１つにどれくらいのメモリスペースを確保するかなど特定の詳細を知りたがる

`str`は動的サイズ付け型といい、この型により、実行時にしかサイズを知ることのできない値を使用するコードを書くことができる

`&str`は文字列スライスといい、開始地点とスライスの長さを格納している

```rust:str
// こんにちは
let s1: str = "Hello there!"; // 12バイトのストレージが必要
// 調子はどう？
let s2: str = "How's it going?"; // 15バイトのストレージが必要
```

&Tは、Tがどこにあるのかのメモリアドレスを格納する単独の値だけれども、&strは２つの値、つまり、strのアドレスとその長さ

そのため、コンパイル時に&strのサイズを知ることができる
usizeの長さの2倍のメモリスペースを確保している

(ちょっと無駄だよね!チリツモだから使うの控えねば...とか思ったけど、今はそんなにメモリのことは気にすることでもないかな？それよりポインタの管理を徹底すべきかな)


## whereとは?

トレイト境界を指定する時に`<>`内にごちゃごちゃと書くのは見づらいので境界名だけ<>内に書き、詳細を`where`に示すことで可読性の良くなるように工夫された書き方

```rust

// whereなし
// ごちゃごちゃと長ったらしい書き方
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {

// whereあり
// 可読性が良い
fn some_function<T, U>(t: T, u: U) -> i32
    where T: Display + Clone,
          U: Clone + Debug
{

```

## Fnとは?

- structのシグネチャによく登場するFn
- `Fnトレイト`といい、標準ライブラリで用意されている(FnMut,FnOneもある)
-  トレイト境界にFnと型を指定することで、これに合致するクロージャが持つべき引数と戻り値の型を示す

```rust:[Fnトレイトの例]　u32の引数をとりu32の戻り値のクロージャをトレイト境界に指定する

struct Foo <T>
    where T: Fn(u32) -> u32
{
    clojure: T, 
    bar: Option<u32>,
}

```



## スモールなselfとラージなSelf

スモールな`self`は、
他の言語と同様の意味で、現在のインスタンス自身（メソッドやモジュール)のこと 

ラージな`Self`は、
traitやimplブロック内の型、もしくは型定義内の現在の型のこと

```rust:self
impl Add for Point {
    type Output = Point;

    fn add(self, other: Point) -> Point {
        Point {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}
```


```rust:Self
trait Add<RHS=Self> {
    type Output;

    fn add(self, rhs: RHS) -> Self::Output;
}
```


## トレイト境界で何ができる？何が便利なのか

**トレイトの復習**
他の言語でいうところのインタフェース
他の型と共有できる機能（振る舞い)を抽象的に定義できる
トレイトは構造体を包んで使う

```rust:トレイトの復習

trait Fly {
	fn fly(&self) -> &str;
}

struct Bird<'b> {
	name: &'b str,
}

impl<'b> Fly for Bird<'b> {
	fn fly(&self) -> &str {
		"飛ぶ"
	}
}

fn main() {
	let bird = Bird { name: "鳥" };
	println!(
		"私の名前は{}, 私は{}ことができます",
		bird.name,
		bird.fly()
	);
	skill(blue_bird);
}

// output
// 私は鳥, 私は飛ぶことが出来ます
```


**トレイト境界**

`トレイト`はいろいろな機能をいろいろな型で実装できる
`トレイト境界`という概念によって、特定の型でしか実装できないように制限する

```rust
// -- snip --

fn skill<T: Fly>(ican: T) {
	println!("私の特技は{}ことです。", ican.fly());
}

fn main() {
	let bird = Bird { name: "鳥" };
	skill(bird);
}

// output
// 私の特技は飛ぶことです。
```

```rust:Flyトレイトを持っていないインスタンスでflyメソッドを呼ぼうとするとエラーとなる

// -- snip --

struct Fish<'f> {
	name: &'f str,
}

fn main() {
	let bird = Bird { name: "鳥" };
	skill(bird);

	let fish = Fish { name: "魚" };
	skill(fish);
}


// output
error[E0277]: the trait bound `Fish<'_>: Fly` is not satisfied
  --> src/main.rs:28:8
   |
15 | fn skill<T: Fly>(ican: T) {
   |             --- required by this bound in `skill`
...
28 |     skill(fish);
   |           ^^^^ the trait `Fly` is not implemented for `Fish<'_>`
```


## 参照&はどこで使う？何と一緒に使う？それはなぜ？

- &は型定義(enum)以外で使われる
  - 変数、構造体、関数、ジェネリック、トレイト、ライフタイム、
- &を使わない場合、所有権がムーブするし、つまりそれは値の移動コストが発生するということなので、それらが積み重なればプログラムのコンパイルや実行速度のオーバーヘッドになりかねない


## cargo build時のwarningを非表示にする

warningを表示したくないモジュールの最初の行に ` #![allow(warnings)] `を記述する。

```rust:foo/src/lib.rs
#![allow(warnings)]

pub struct Bar{
    // -- snip -- 
}
```

## 構造体に参照を持たせようとするとエラー？

構造体に&str文字列スライスのような参照をもたせようとするとエラーになるのは、構造体のインスタンスは全データを所有する必用があり、このデータは、構造体全体が有効な期間と`同じ期間`、有効である必要がある。

データの有効な期間が不明だと駄目？つまり、データのライフタイムを明示する必要がある。ライフタイムを指定せずに構造体に参照を保持させようとするとコンパイルエラーとなる。

```rust:エラー

struct User {
    username: &str,
    email: &str,
    sign_in_count: u64,
    active: bool,
}

fn main() {
    let user1 = User {
        email: "someone@example.com",
        username: "someusername123",
        active: true,
        sign_in_count: 1,
    };
}
```
```rust:Ok

// 構造体に参照をもたせるにはライフタイムを指定する
struct User<'a> {
    username: &'a str,
    email: &'a str,
    sign_in_count: u64,
    active: bool,
}

fn main() {
    let user1 = User {
        email: "someone@example.com",
        username: "someusername123",
        active: true,
        sign_in_count: 1,
    };
}
```


## isizeとusize

あなたのパソコンのCPUアーキテクチャに合ったビット分のサイズを取ってくれる整数型です。

```:例

 [32bitのPC]
isize = i32
usize = u32

 [64bitのPC]
isize = i64
usize = u64
```