【Rust】最大値・最小値【Algorithm】

変数を用意しておいて、最大値、最小値の値を更新していくだけですね。
ループを抜けるのは10000以上か0以下としています。

fn main() {

   let mut imax: i32 = -1;
   let mut imin: i32 = 10000;
   let mut kmax: i32 = 0;
   let mut kmin: i32 = 0;
   let mut k: i32 = 0;
   let mut i: i32 = 0;

   while(i >= 0 && i <= 9999){
      println!("4桁以内の正の整数を入力してください。");
      let mut x = String::new();
      std::io::stdin().read_line(&mut x).expect("Failed to read line");
      x = x.trim_end().to_owned();
      i = x.parse::<i32>().unwrap();
      if (0 < i && i < 10000) {
         k += 1;
         if(imax < i) {
            imax = i;
            kmax = k;
         }

         if(imin > i) {
            imin = i;
            kmin = k;
         }
      }
   }

   if (k == 0) {
      println!("入力されていません。");
   } else {
      println!("最大値 {}({}回目)", imax, kmax);
      println!("最小値 {}({}回目)", imin, kmin);
   }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.90s
Running `target/debug/basic`
4桁以内の正の整数を入力してください。
100
4桁以内の正の整数を入力してください。
20
4桁以内の正の整数を入力してください。
50
4桁以内の正の整数を入力してください。
29
4桁以内の正の整数を入力してください。
829
4桁以内の正の整数を入力してください。
2222
4桁以内の正の整数を入力してください。
2452
4桁以内の正の整数を入力してください。
11245
最大値 2452(7回目)
最小値 20(2回目)

うーむ なるほど〜

【Rust】反復処理【Algorithm】

偶数の和の場合は、n += 2;とする

fn main() {

   let mut n: i32 = 1;
   let mut t: i32 = 0;

   while n <= 100 {
      t = t + n;
      n += 1;
   }
   println!("{}", t);
}
fn main() {

   println!("入力されたmからnまでの合計を求めます。二つの数字を入力してください。");
   let mut x = String::new();
   let mut y = String::new();
   std::io::stdin().read_line(&mut x).expect("Failed to read line");
   x = x.trim_end().to_owned();
   let mut x: i32 = x.parse::<i32>().unwrap();
   std::io::stdin().read_line(&mut y).expect("Failed to read line");
   y = y.trim_end().to_owned();
   let mut y: i32 = y.parse::<i32>().unwrap();
   
   if x > y {
      println!("mの方が大きいです。")
   }
   let mut w: i32 = 0;
   while x <= y {
      w = w + x;
      x += 1;
   }
   println!("mからnまでの合計値は{}", w);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.38s
Running `target/debug/basic`
入力されたmからnまでの合計を求めます。二つの数字を入力してください。
2
5
mからnまでの合計値は14

ユークリッド互助法

fn main() {

   println!("最大公約数を求めます。二つの数字を入力してください。");
   let mut x = String::new();
   let mut y = String::new();
   std::io::stdin().read_line(&mut x).expect("Failed to read line");
   x = x.trim_end().to_owned();
   let mut x: i32 = x.parse::<i32>().unwrap();
   std::io::stdin().read_line(&mut y).expect("Failed to read line");
   y = y.trim_end().to_owned();
   let mut y: i32 = y.parse::<i32>().unwrap();
   
   let mut a: i32;
   let mut b: i32;
   let mut r: i32;
   if (x > y) {
      a = x;
      b = y;
   } else {
      a = y;
      b = x;
   }

   r = a % b;

   while (r != 0) {
      a = b;
      b = r;
      r = a % b;
   }
   println!("最大公約数は{}", b);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.18s
Running `target/debug/basic`
最大公約数を求めます。二つの数字を入力してください。
100
75
最大公約数は25

【Rust】分岐処理【Algorithm】

fn main() {

   println!("数字を入力してください。");
   let mut x = String::new();
   std::io::stdin().read_line(&mut x).expect("Failed to read line");
   x = x.trim_end().to_owned();
   let x: i32 = x.parse::<i32>().unwrap();

   if x > 100 {
      println!("{}は100より大きい", x);
   } else {
      println!("{}は100より小さい", x);
   }
}

最小値

fn main() {

   let a = 10;
   let b = 15;
   let c = 9;
   let mut w: i32;

   if a <= b {
      if a <= c {
         w = a;
      } else {
         w = c;
      }
   } else {
      if b <= c {
         w = b;
      } else {
         w = c;
      }
   }
   println!("{}", w);
}

Rustにはstd::cmp::minという関数があるが、argmentは2つでないといけない
https://doc.rust-lang.org/std/cmp/fn.min.html
std::cmp::min(a, b, c);とは書けない。

fn main() {

   let a = 10;
   let b = 15;
   let c = 9;
   let mut w: i32;
   
   if(a <= b && a <= c) {
      w = a;
   } else if (a <= b && a > c) {
      w = c;
   } else if (a > b && b <= c) {
      w = b;
   } else {
      w = c;
   }
   println!("{}", w);
}

計算量を少なくする方法

fn main() {

   let a = 10;
   let b = 15;
   let c = 9;
   let mut w: i32;
   
   w = a;
   if(b < w) {
      w = b;
   }
   if (c < w) {
      w = c;
   }
   println!("{}", w);
}

大文字小文字

fn main() {

   println!("一文字入力してください。");
   let mut x = String::new();
   std::io::stdin().read_line(&mut x).expect("Failed to read line");
   x = x.trim_end().to_owned();
   let char_vec: Vec<char> = x.chars().collect();
   for y in char_vec {
      if y.is_uppercase() {
         println!("大文字です");
      } else {
         println!("子文字です");
      }
   }
}

【Rust】四則演算【Algorithm】

fn main() {

   println!("二つの数字を入力してください。");
   let mut x = String::new();
   let mut y = String::new();
   std::io::stdin().read_line(&mut x).expect("Failed to read line");
   x = x.trim_end().to_owned();
   let x: i32 = x.parse::<i32>().unwrap();
   std::io::stdin().read_line(&mut y).expect("Failed to read line");
   y = y.trim_end().to_owned();
   let y: i32 = y.parse::<i32>().unwrap();

   println!("{} + {} = {}", x, y, x+y);
   println!("{} - {} = {}", x, y, x-y);
   println!("{} * {} = {}", x, y, x*y);
   println!("{} / {} = {}", x, y, x/y);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
Running `target/debug/basic`
二つの数字を入力してください。
24
6
24 + 6 = 30
24 – 6 = 18
24 * 6 = 144
24 / 6 = 4

【Rust】mem::swap【Algorithm】

mem::swap(&mut x, &mut y);でswapできる。
https://doc.rust-lang.org/std/mem/fn.swap.html

use std::mem;

fn main() {

   println!("二つの数字を入力してください。");
   let mut x = String::new();
   let mut y = String::new();
   std::io::stdin().read_line(&mut x).expect("Failed to read line");
   x = x.trim_end().to_owned();
   std::io::stdin().read_line(&mut y).expect("Failed to read line");
   y = y.trim_end().to_owned();

   mem::swap(&mut x, &mut y);
   println!("入力した値をswapすると「{}」と「{}」です", x, y);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.39s
Running `target/debug/basic`
二つの数字を入力してください。
20
15
入力した値をswapすると「15」と「20」です

既に用意されているのね…

【Rust/React.js】jsonで保存したデータをsetTimeoutで表示する

React(Json)で、入れ子のデータを扱うには、data.map((value) => と書くと、for(let d in data) のような処理ができる。

main.rs

#[derive(Serialize, Deserialize, Debug, Clone)]
struct Name {
    first : String,
    last: String,
}

#[tokio::main]
async fn main()  {
    let mut names : Vec<Name> = Vec::new();
    let n1 = Name { first:"taro".to_string(), last:"yamata".to_string()};
    let n2 = Name { first:"hajime".to_string(), last:"tanaka".to_string()};
    let n3 = Name { first:"hanako".to_string(), last:"yoshida".to_string()};
    names.push(n1);
    names.push(n2);
    names.push(n3);
    println!("{:?}", names);
    let serialized: Vec<u8> = serde_json::to_vec(&names).unwrap();
    println!("{:?}", serialized);
    let file_path = format!("./data/data.txt");
    let mut file = File::create(file_path.clone()).unwrap();
    file.write_all(&serialized).expect("write failed");

}

data.txt

[{"first":"taro","last":"yamata"},{"first":"hajime","last":"tanaka"},{"first":"hanako","last":"yoshida"}]

App.js

import React, {Component} from 'react';
import './App.css';
 
class App extends Component {
 
  render() {
    return <div className="App">
    <h1>React</h1>
    <Blocks />
  </div>;
  }
}
 
class Blocks extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: null,
    };
  }

  componentDidMount() {
      this.timer = setInterval(
          () => 
              fetch('./data/data.text').then(response => {
                  return response.json();
                  }).then(json => {
                      this.setState({ data: json});
                  }),
          2000,
      );
  }

  componentWillUnmount() {
      clearInterval(this.timer);
  }

  render() {
    if (this.state.data) {
      return <div>
        {this.state.data.map((value) => (
          <p>名前:{value.first} {value.last}</p>
        ))}
      </div>
    }
    else {
      return <div>Loading...</div>
    }
  }
}
export default App;

これを少し応用したい。

【Rust】ステートマシンによるメール判定【Algorithm】

fn isalphanum(c: char) -> bool {
    return c.is_alphabetic() || c.is_numeric();
}

fn isdot(c: char) -> bool {
    return c == '.';
}

fn isatmark(c: char) -> bool {
    return c == '@';
}

fn isend(c: char) -> bool {
    return c == '$';
}

fn isemail(mut s: String) -> bool {
    s += "$";

    let INIT = 0;
    let LOCAL_NOTDOT = 1;
    let LOCAL_DOT = 2;
    let ATMART = 3;
    let DOMAIN_NOTDOT = 4;
    let DOMAIN_DOT = 5;
    let OK = 6;
    let NG = 7;

    let mut state = INIT;

    for c in s.chars() {
        if state == INIT {
            if isalphanum(c) {
                state = LOCAL_NOTDOT;
            } else {
                state = NG;
                break;
            }
        } else if state == LOCAL_NOTDOT {
            if isalphanum(c) {
                state = LOCAL_NOTDOT;
            } else if isdot(c) {
                state = LOCAL_DOT;
            } else if isatmark(c) {
                state = ATMART;
            } else {
                state = NG;
                break;
            }
        } else if state == LOCAL_DOT {
            if isalphanum(c) {
                state = LOCAL_NOTDOT;
            } else {
                state = NG;
                break;
            }
        } else if state == ATMART {
            if isalphanum(c) {
                state = DOMAIN_NOTDOT;
            } else {
                state = NG;
                break;
            }
        } else if state == DOMAIN_NOTDOT {
            if isalphanum(c) {
                state = DOMAIN_NOTDOT;
            } else if isdot(c) {
                state = DOMAIN_DOT;
            } else if isend(c) {
                state = OK;
            } else {
                state = NG;
                break;
            }
        } else if state == DOMAIN_DOT {
            if isalphanum(c) {
                state = DOMAIN_NOTDOT;
            } else {
                state = NG;
                break;
            }
        } else if state == OK {
            break;
        } else if state == NG {
            break;
        } else {
            state = NG
        }
    }
    return state == OK;
}

fn main() {
    let email = "t@g.m".to_string();
    if isemail(email.clone()) {
        println!("メールアドレスです。{}", email);
    } else {
        println!("メールアドレスではありません。");
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s
Running `target/debug/basic`
メールアドレスです。t@g.m

【Rust】ボイアーとムーアで過半数の取得を計算する【Algorithm】

### 単純に計算していく方法

fn main() {
    
    let mut vote = [
        "山田太郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), 
        "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), 
        "鈴木花子".to_string(), "鈴木花子".to_string(), "山田太郎".to_string(), "鈴木花子".to_string(), 
    ];

    let n = vote.len();

    let half = n / 2;
    let mut winner = "".to_string();

    for i in 0..n {
        if vote[i] == "" {
            continue;
        }

        let mut count = 1;

        for j in i+1..n {
            if vote[j] == vote[i] {
                count += 1;
                vote[j] = "".to_string();
                if count > half {
                    winner = vote[i].clone();
                    break;
                }
            }
        }
        if winner != "".to_string() {
            break;
        }
    }

    if winner != "".to_string() {
        println!("{}が過半数を取りました", winner);
    } else {
        println!("過半数を取った人はいません");
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/basic`
鈴木花子が過半数を取りました

### ボイアーとムーアのアルゴリズム
最初に最も多い組み合わせを調べ、それが過半数に達しているか計算する。
計算量が少なくて済む。

fn main() {
    
    let vote = [
        "山田太郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), 
        "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), 
        "鈴木花子".to_string(), "鈴木花子".to_string(), "山田太郎".to_string(), "鈴木花子".to_string(), 
    ];

    let n = vote.len();
    let mut candidate = "".to_string();

    let mut survivor = 0;

    for i in 0..n {
        if survivor == 0 {
            candidate = vote[i].clone();
            survivor = 1;
        } else if candidate == vote[i] {
            survivor += 1;
        } else {
            survivor -= 1;
        }
    }
    let mut count = 0;
    if survivor != 0 {
        for i in 0..n {
            if candidate == vote[i] {
                count += 1;
            }
        }
    }

    if count > (n / 2) {
        println!("{}が過半数を取りました。", candidate);
    } else {
        println!("過半数を取った人はいません。");
    }
}

### ソートによるカウント
ソートして真ん中の値のカウントをする。これも美しい。

fn main() {
    
    let mut vote = vec![
        "山田太郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), 
        "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), 
        "鈴木花子".to_string(), "鈴木花子".to_string(), "山田太郎".to_string(), "鈴木花子".to_string(), 
    ];

    let half = vote.len() / 2;

    vote.sort();

    if vote.clone().into_iter().filter(|n| *n == vote[half]).count() > half {
        println!("{}が過半数を取りました。", vote[half]);
    } else {
        println!("過半数を取った人はいません。");
    }
}

### hashmapで計算する

use std::collections::HashMap;

fn main() {
    
    let vote = [
        "山田太郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), 
        "鈴木花子".to_string(), "佐藤三郎".to_string(), "鈴木花子".to_string(), "佐藤三郎".to_string(), 
        "鈴木花子".to_string(), "鈴木花子".to_string(), "山田太郎".to_string(), "鈴木花子".to_string(), 
    ];

    let mut blackboard: HashMap<String, i32> = HashMap::new();

    for v in vote.clone() {
        if !blackboard.contains_key(&v) {
            blackboard.insert(v.clone(),1);
        } else {
            blackboard.insert(v.clone(), 1 + blackboard[&v]);
        }
        println!("{:?}", blackboard);
    }

    let key_with_max_value =blackboard.iter().max_by_key(|entry | entry.1).unwrap();
    if *key_with_max_value.1 as usize > (vote.len() / 2) {
        println!("過半数を取得しました。{:?}", key_with_max_value);
    } else {
        println!("過半数を取った人はいません。");
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/basic`
{“山田太郎”: 1}
{“山田太郎”: 1, “鈴木花子”: 1}
{“山田太郎”: 1, “鈴木花子”: 1, “佐藤三郎”: 1}
{“佐藤三郎”: 1, “山田太郎”: 1, “鈴木花子”: 2}
{“佐藤三郎”: 1, “山田太郎”: 1, “鈴木花子”: 3}
{“佐藤三郎”: 2, “山田太郎”: 1, “鈴木花子”: 3}
{“佐藤三郎”: 2, “山田太郎”: 1, “鈴木花子”: 4}
{“佐藤三郎”: 3, “山田太郎”: 1, “鈴木花子”: 4}
{“佐藤三郎”: 3, “山田太郎”: 1, “鈴木花子”: 5}
{“佐藤三郎”: 3, “山田太郎”: 1, “鈴木花子”: 6}
{“佐藤三郎”: 3, “山田太郎”: 2, “鈴木花子”: 6}
{“佐藤三郎”: 3, “山田太郎”: 2, “鈴木花子”: 7}
過半数を取得しました。(“鈴木花子”, 7)

これが感覚的には一番わかりやすい。でもアルゴリズム的にはボイヤーの方が優れているんだよなー

【Internet Computer】Rust ではじめてのキャニスター開発をやってみる

こちらの記事を参考にRustでDapps開発を行います。
https://smacon.dev/posts/hello-icp-rust/

### dfxのインストール
sh -ci “$(curl -fsSL https://sdk.dfinity.org/install.sh)”

dfxのインストールだが、mac m1チップのARMアーキテクチャではできない。
https://forum.dfinity.org/t/ubuntu-vm-on-macbook-m1-dfx-install-unknown-cpu-type-aarch64/21486

$ uname -m
aarch64

おいおいおい、いきなりつまづいてしまった。これのトラブルシューティングに丸一日かかりました。
どうしてもやりたかったので、結局、別の環境で作ることに。
# uname -m
x86_64

# dfxのプロジェクトファイル実行
# dfx new –type=rust rust_hello
# cd rust_hello
# dfx start –background
# rustup target add wasm32-unknown-unknown
# dfx deploy
Installed code for canister rust_hello_backend, with canister ID bkyz2-fmaaa-aaaaa-qaaaq-cai

# dfx canister call bkyz2-fmaaa-aaaaa-qaaaq-cai greet ‘(“everyone”: text)’
(“Hello, everyone!”)

# dfx canister status bkyz2-fmaaa-aaaaa-qaaaq-cai
Canister status call result for bkyz2-fmaaa-aaaaa-qaaaq-cai.
Status: Running
Controllers: bnz7o-iuaaa-aaaaa-qaaaa-cai wbqzn-2jy52-icft2-erprw-b52eq-e4ixe-4yxqb-5neaf-miz3k-arx3m-gae
Memory allocation: 0 Bytes
Compute allocation: 0 %
Freezing threshold: 2_592_000 Seconds
Idle cycles burned per day: 1_257_808 Cycles
Memory Size: 1_600_075 Bytes
Balance: 3_061_352_105_201 Cycles
Reserved: 0 Cycles
Reserved cycles limit: 5_000_000_000_000 Cycles
Wasm memory limit: 3_221_225_472 Bytes
Wasm memory threshold: 0 Bytes
Module hash: 0xb60872271f3ca7c4ee2b18a54434c344e3095982685ce10f2c7217c08dfb1cf7
Number of queries: 0
Instructions spent in queries: 0
Total query request payload size: 0 Bytes
Total query response payload size: 0 Bytes
Log visibility: controllers

$ dfx stop

どうやら、「デプロイして、キャニスターを実行」という流れになるようだ。
私の理解では、このキャニスターがスマートコントラクト。
そして、FrontはデフォルトでReactが用意されている。

なるほど、

【Rust】rustでメールを送信する

use lettre:: {
    transport::smtp::authentication::Credentials, Message,
    message::{header, SinglePart},
    SmtpTransport, Transport, message::Mailbox, Address
};

#[tokio::main]
async fn main()  {
    
    let username = "hogehoge@gmail.com";
    let app_password = "**** **** **** ****";
    let smtp = "smtp.gmail.com";
    let email = Message::builder()
        .to(Mailbox::new(None, username.parse::<Address>().unwrap()))
        .from(Mailbox::new(None, username.parse::<Address>().unwrap()))
        .subject("題名: Rust Mail Test")
        .singlepart(
            SinglePart::builder()
                .header(header::ContentType::TEXT_PLAIN)
                .body(String::from("本文 Test"))
        )
        .unwrap();
    let credentials = Credentials::new(username.into(), app_password.into());
    let mailer = SmtpTransport::starttls_relay(smtp)
        .unwrap()
        .credentials(credentials)
        .build();
    let result = mailer.send(&email);
    println!("{:?}", result);
}