Atcoder ABS ABC081B Shift only

こんにちは、ナナオです。 前回に引き続き競プロを実施していきたいと思います。 今回の問題は以下です。 ABC081B - Shift only 実装 以下のように実装しました。 use proconio::input; fn main() { input! { n: u8, mut a: [u32; n], } let mut cnt = 0; loop { if !a.iter().find(|&&a| a % 2 != 0).is_some() { a = a.into_iter().map(|a| a / 2).collect(); } else { break; } cnt += 1; } println!("{cnt}"); } まぁまぁすっきり実装できたんじゃないでしょうか。 では今回はこれで👍

2026年4月22日 · にあえん

Atcoder ABS ABC081A Placing Marbles

こんにちは、ナナオです。 前回に引き続き競プロを実施していきたいと思います。 今回の問題は以下です。 ABC081A - Placing Marbles 実装 以下のようにすっきり実装できました。 use proconio::{input, marker::Chars}; fn main() { input! { s: Chars, } let cnt = s.into_iter().filter(|c| c == &'1').count(); println!("{cnt}"); } proconio、マジで最高すぎる。。。 では今回はこれで👍

2026年4月20日 · にあえん

Atcoder ABS ABC086A Product

こんにちは、ナナオです。 前回に引き続き競プロを実施していきたいと思います。 今回の問題は以下です。 ABC086A - Product 実装 前回は入力に手間取りましたが、今回はproconioというライブラリを使ってかなりすっきり書くことができました。 use proconio::input; fn main() { input! { a: i32, b: i32, } if a * b % 2 == 0 { println!("Even"); } else { println!("Odd"); } } いやぁ、標準入力がすっきり書けるだけでここまですっきり書けるようになるとは… 驚きです。 ということで今回はこれで👍

2026年4月19日 · にあえん

Atcoder ABS PracticeA Welcome to AtCoder

こんにちは、ナナオです。 前回に引き続き競プロを実施していきたいと思います。 今回の問題は以下です。 PracticeA - Welcome to AtCoder 実装 以下のように実装しました。 今回はRustを使います。 (前回の記事であまりにもGoが遅かったので。。。) fn main() { let a = read().trim().parse::<i32>().unwrap(); let t = read(); let mut iter = t.split_whitespace().map(|i| i.parse::<i32>().unwrap()); let b = iter.next().unwrap(); let c = iter.next().unwrap(); let s = read(); println!("{} {s}", a + b + c) } fn read() -> String { let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); s.clone() } 文字列受け取って数値に変換するだけで手間かかりすぎでしたが、Rustの強力な型安全性やエラーハンドリングを考えると納得…ではあるんですが、やっぱり競技プログラミングには向いていない気がしますね。 というわけで今回はこれで👍

2026年4月18日 · にあえん

hugoの予約投稿アプリをtauriで作る

こんにちは、ナナオです。 今回は、前回作ったhugoの予約投稿ツールをtauriでUI作って見やすくしようよ、という記事になります。 Githubはこちら↓ GitHub - satodaiki/hugo-local-cms: hugoの予約投稿管理 tauriのインストールと起動まで まずはプロジェクトにtauriを入れます。 やり方はこちらを参考にします。 プロジェクトの作成 | Tauri フロントエンドのビルドにはviteを利用します。 ❯ npm create vite@latest . > npx > "create-vite" . │ ◇ Current directory is not empty. Please choose how to proceed: │ Ignore files and continue │ ◇ Select a framework: │ React │ ◇ Select a variant: │ TypeScript │ ◇ Use rolldown-vite (Experimental)?: │ No │ ◇ Install with npm and start now? │ Yes │ ◇ Scaffolding project in /home/nanao/Project/personal/hugo-local-cms... │ ◇ Installing dependencies with npm... added 175 packages, and audited 176 packages in 14s 45 packages are looking for funding run `npm fund` for details found 0 vulnerabilities │ ◇ Starting dev server... React + TypeScriptで実装することにしました。 ...

2026年2月5日 · にあえん

Zedで最速で最高の開発環境を手に入れる

こんにちは、ナナオです。 今回はRust製のめちゃ早エディター「Zed」を触っていきたいと思います。 初期設定 インストールはwingetから行えます。 winget install -e --id ZedIndustries.Zed インストール後、zedコマンドで起動できます。 起動直後のzedはこんな感じです。 VSCodeとの比較ですが、私個人的にはまぁ早いかなくらいでした。 普段WSLを使うのですが、設定とかは特に必要なくwsl上からzedコマンドが使用できました。 感想 拍子抜けするくらい簡単でした。 今後使っていく中でまた何かあったら追記していこうと思います。 参考 VSCodeをやめてZedにするぞ! - Chienomi ZedのWindows Beta版、WSLでうごくっぽいぞ! #VSCode - Qiita RUST製エディター「Zed」とは #Rust - Qiita

2026年1月26日 · にあえん

tauriを使ってXCodeでiPhoneをエミュレーションする

どうも、やっぱりRustが好きなナナオです。 前回、せっかくHackintosh化に成功したので、XCodeでなんかエミュレートしたいんですよね。 Lenovo ThinkPad X270にHackintoshでSequoiaを入れた | にあえん ということで今回はtauriを使ってみようと思います。 プロジェクトの作成 tauriのプロジェクトの作成は公式ドキュメントに従ってやっていきましょう。 Create a Project | Tauri とりあえずプロジェクト作成に必要なツールをダウンロードしていきましょう。 cargo install create-tauri-app --locked tauri cliというのもインストールしておきましょう。 Command Line Interface | Tauri cargo install tauri-cli --version "^2.0.0" --locked これで準備ができました。 プロジェクトを作成していきます。 cargo create-tauri-app 出来上がったsrc-tauriディレクトリ内で以下のコマンドを実行します。 cargo tauri dev とりあえずデスクトップアプリの起動には成功しました! iPhoneでエミュレートしてみる iOSで起動するには、同ディレクトリ内で以下のコマンドを実行する必要があります。 cargo tauri ios init しかし残念ながらエラーが出てしまいました。。 Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP. Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`). Info package `cocoapods` present: false Installing `cocoapods`... Error: Cask 'cocoapods' is not installed. `sudo` is required to install cocoapods using gem Error failed to install Apple dependencies: Failed to install `cocoapods`: No such file or directory (os error 2): No such file or directory (os error 2) cocoapodsというツールがインストールされていなかったようです。 ...

2024年12月22日 · にあえん

Rustで標準入力受け取りたいとき

こんにちは。ナナオです。 AtCoderでRustが使えるので使いたいなーと思ったんですが、標準入力どう受け取ればいいんだ?ってなったので備忘録。 Rustで標準入力受け取るコード こんな感じにしました。 use std::io::{self, Read}; fn main() { let input = read_stdin(); print!("{}", input); } /// 標準入力を受け取る関数 fn read_stdin() -> String { let mut buf = String::new(); io::stdin().read_to_string(&mut buf).expect("Failed to read stdin."); buf.to_string() } これで大抵の競プロは乗り切れるはず。。

2024年11月10日 · にあえん

maturinをワークスペースで運用してみる

どうも、ナナオです。 最近PythonからRustを呼び出す実装をすることがありまして、pyo3にお世話になることがありました。 pyo3のビルドにはmaturinというCLIを使うのですが、これをRustのワークスペース機能と併用できるのかどうか気になったので、検証してみたいと思います。 準備 とりあえず適当にpyo3を使用したライブラリを作ります。 ryeを使っていれば以下のコマンドでmaturinをビルダーに指定したプロジェクトを作成できます。 rye init maturin-workspace-playground --build-system maturin maturinをインストールしていなかったので、以下のコマンドでインストールしておきます。 rye install maturin 作ったプロジェクトに移動して、ワークスペースのメンバーになるプロジェクトを作成しておきます。 cd maturin-workspace-playground mkdir rust && cd rust cargo init --lib app cargo init --lib python-api 作成したプロジェクトをワークスペースのメンバーになるように設定をしていきます。 ルートディレクトリのCargo.tomlを以下のように編集します。 [workspace.package] name = "maturin-workspace-playground" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] members = ["rust/python-api", "rust/app"] rust/appのCargo.tomlは以下のように編集します。 [package] name = "app" version.workspace = true edition.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rust/python-apiのCargo.tomlは以下のように編集します。 ...

2024年8月26日 · にあえん

LineのOAuth認証を試してみた

OAuth触るの5年ぶり。ナナオです。 今回はLINEのOAuth認証を、実際にサーバーを実装しながら試していきたいと思います。 LINEログイン v2.1 APIリファレンス | LINE Developers そもそもOAuthとは?といったところは↓ 一番分かりやすい OAuth の説明 #OAuth - Qiita OAuthでログイン画面表示まで まずLINE Developersコンソールからログインチャネルを作成します。 これはMessaging APIなどとは別で作成する必要があります。 以下のように設定しました。 続けて、「LINEログイン設定」からコールバックURLを設定します。 コールバックURLのリクエスト先はまだ実装していなくても大丈夫です。 今回はウェブアプリから使用する設定で実装します。 ここまで出来たらブラウザからログインの様子を確認することができます。 認可リクエストのドキュメントを確認し、URLを作ってブラウザからリクエストしてみましょう。 うまくいけば以下のようなLINEのログイン画面に遷移します。 コールバックURLを実装する 今のままだとリダイレクトURLの先には何もないので、自分で実装しましょう。 Cargoパッケージを作成します。 cargo new rust-line-oauth-playground 必要な依存関係も追加しておきます。 [dependencies] axum = "0.7.1" dotenv = "0.15.0" reqwest = { version = "0.11.22", features = ["json"] } serde = { version = "1.0.193", features = ["derive"] } serde_json = "1.0.108" tokio = { version = "1.34.0", features = ["macros", "rt", "rt-multi-thread"] } では実際にリダイレクト先の実装をしてあげましょう。 これを実施すると、アクセストークンが取得できるようにになります。 以下のように行いました。 use axum::{extract::{Query, State}, routing::get, Router}; use serde::Deserialize; use reqwest::Client; use serde_json::{Value, json}; #[derive(Debug, Deserialize)] struct LineCallbackQuery { code: String, state: String, friendship_status_changed: Option<bool>, liffClientId: Option<String>, liffRedirectUri: Option<String>, } #[derive(Debug, Deserialize)] struct LineCallbackError { error: String, error_description: Option<String>, state: Option<String>, } #[derive(Debug, Deserialize)] struct AccessTokenResponse { access_token: String, expires_in: i32, id_token: String, refresh_token: String, scope: String, token_type: String, } #[derive(Debug, Clone)] struct BaseSetting { redirect_uri: String, client_id: String, client_secret: String, } #[derive(Debug, Clone)] struct AppState { http_client: Client, setting: BaseSetting, } async fn line_callback( Query(query): Query<Value>, State(state): State<AppState>, ) { // エラーの場合 // https://developers.line.biz/ja/docs/line-login/integrate-line-login/#receiving-an-error-response if query.get("error").is_some() { let query: LineCallbackError = serde_json::from_value(query).unwrap(); eprintln!("リダイレクト時にエラーが発生しました: {:?}", query); return } // 正常な場合 // https://developers.line.biz/ja/docs/line-login/integrate-line-login/#receiving-the-authorization-code let query: LineCallbackQuery = serde_json::from_value(query).unwrap(); let params = json!({ "grant_type": "authorization_code", "code": query.code, "redirect_uri": state.setting.redirect_uri, "client_id": state.setting.client_id, "client_secret": state.setting.client_secret, }); // アクセストークンを取得する // https://developers.line.biz/ja/docs/line-login/integrate-line-login/#get-access-token let res = state.http_client.post("https://api.line.me/oauth2/v2.1/token") .form(&params) .send().await.unwrap(); let res_json: AccessTokenResponse = res.json().await.unwrap(); println!("res: {:?}", res_json); } #[tokio::main] async fn main() { // 環境変数をdotenvで取得する dotenv::dotenv().ok(); let setting = BaseSetting { redirect_uri: std::env::var("REDIRECT_URI") .expect("REDIRECT_URI must be set"), client_id: std::env::var("CLIENT_ID") .expect("CLIENT_ID must be set"), client_secret: std::env::var("CLIENT_SECRET") .expect("CLIENT_SECRET must be set"), }; let http_client = reqwest::Client::new(); let state = AppState { http_client, setting, }; let app = Router::new() .route("/callback", get(line_callback)) .with_state(state); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") .await .unwrap(); println!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); } あとはルートパッケージ直下に.envを配置します。 ...

2023年11月30日 · にあえん