参考 https://blog.hamadu.net/2018/08/vscode-rust.html
https://github.com/TheAlgorithms/Rust
from https://atcoder.jp/contests/abc259/submissions/33076989
fn run_length_encoding<T: Eq>(a: Vec<T>) -> Vec<(T, usize)> {
let mut a = a.into_iter().map(|a| (a, 1)).collect::<Vec<_>>();
a.dedup_by(|a, b| {
a.0 == b.0 && {
b.1 += a.1;
true
}
});
a
}
3 つ以上の整数の XOR の計算は自由な順序で行える a ⊕ b ⊕ c = b ⊕ c ⊕ a = (a ⊕ b) ⊕ c = c ⊕ (a ⊕ b) a ⊕ b ⊕ a = (a ⊕ a) ⊕ b = 0 ⊕ b = b 参考:abc171
競技プログラミングにおけるXORのTips https://qiita.com/kuuso1/items/778acaa7011d98a3ff3a
upper_bound, lower_bound https://docs.rs/superslice/1.0.0/superslice/trait.Ext.html
https://kyopro.hateblo.jp/entry/2019/04/25/134128
https://stackoverflow.com/questions/58669865/how-to-get-the-minimum-value-of-a-vector-in-rust
let ans = dp[n - 1].iter().max().unwrap();
https://qiita.com/osanshouo/items/71b0272cd5e156cbf5f2
https://algo-logic.info/divisor/
abc121-c
shops.sort_by_key(|s| s.price);
# keyが複数の場合はtupleをkeyとする。
vec.sort_by_key(|(time, p)| (*time, *p));
sort_by(|a, b| a.partial_cmp(b).unwrap())
https://stackoverflow.com/questions/60916194/how-to-sort-a-vector-in-descending-order-in-rust
use std::cmp::Reverse;
vec.sort_by_key(|w| Reverse(*w));
c.is_uppercase(), c.is_lowercase()... c: char, return: bool
for (i, c) in s.into_iter().enumerate() {
&Charsでiterationしたい場合 https://webbibouroku.com/Blog/Article/rust-iter-index
for (i, val) in (0_i32..).zip(a.iter()) {
println!("{}: {}", i, val);
}
vec.sort()
vec.reverse()
https://doc.rust-jp.rs/book-ja/ch08-03-hash-maps.html#古い値に基づいて値を更新する https://qiita.com/hystcs/items/75183bcf38bf95cc2ce0
let mut map = std::collections::HashMap::new();
for c in "abcabc".chars() {
*map.entry(c).or_insert(0) += 1;
}
https://keens.github.io/blog/2020/05/23/rustnohashmaphaentrygabenri/
// 準備
let mut map = HashMap::<String, Vec<String>>::new();
let key = "Hoge".to_string();
let value = "Huga".to_string();
// Entry APIを使ったコード
map.entry(key).or_insert_with(|| vec![]).push(value);
println!("{:?}", map); // {'c': 2, 'a': 2, 'b': 2}
let mut memo = HashMap::new();
for (i, ai) in a.iter().enumerate() {
memo.entry(*ai)
.or_insert(vec![])
.push(i as i32 + 1);
}
for _ in 0..q {
input! {x: usize, k: usize};
let ans = memo.get(&x)
.map_or(-1, |p| p.get(k - 1)
.cloned()
.unwrap_or(-1));
println!("{}", ans);
}
最大値と最小値を取り出す https://maguro.dev/btree-maximum-value/
// BTreeSetのある値よりも1つ小さな値、もしくは1つ大きな値を返す。
trait Neighbors<T> {
fn before(&self, x: T) -> Option<&T>;
fn after(&self, x: T) -> Option<&T>;
}
impl<T: Ord> Neighbors<T> for BTreeSet<T> {
fn before(&self, x: T) -> Option<&T> {
let mut bfr = self.range((std::ops::Bound::Unbounded, std::ops::Bound::Excluded(x)));
bfr.next_back()
}
fn after(&self, x: T) -> Option<&T> {
let mut aftr = self.range((std::ops::Bound::Excluded(x), std::ops::Bound::Unbounded));
aftr.next()
}
}
i64にはsqrtメソッドはないので、f64にキャストします。
let s = (q as f64).sqrt();
https://doc.rust-lang.org/std/primitive.f64.html#method.max
let x = 1.0_f64;
let y = 2.0_f64;
assert_eq!(x.min(y), x);
fn main() {
let a = "Hello";
let b = "World";
let matching = a.chars().zip(b.chars()).filter(|&(a, b)| a == b).count();
println!("{}", matching);
let a = [1, 2, 3, 4, 5];
let b = [1, 1, 3, 3, 5];
let matching = a.iter().zip(&b).filter(|&(a, b)| a == b).count();
println!("{}", matching);
}
fn main() {
let test = vec!["one", "two", "three"];
let index = test.iter().position(|&r| r == "two").unwrap();
println!("{}", index);
}
let vec:Vec<Vec<i64>> = (0..N).combinations(2).collect();
num::integer::gcd(x, y)
を用いた方が良い(ゼロ除算など回避できる)
// ユークリッドの互助法による最大公約数
fn gcd(m:usize, n:usize) -> usize {
// 再帰関数で実装する。
// ベースケース
if m % n == 0 {
return n;
}
// 再帰呼び出し
gcd(n, m % n)
}
// 最小公倍数
fn lcm(m:usize, n:usize) -> usize {
let u = max(m, n);
let l = min(m, n);
u * l / gcd(u, l)
}
https://qiita.com/wotsushi/items/4a6797f52080453a0440#deque
let mut d = std::collections::VecDeque::new();
# dequeの先頭に要素を追加する
#(例)deque d の先頭に4を追加する
d.push_front(4);
# deque d の末尾に2を追加する
d.push_back(2);
# deque d の先頭要素を削除し、削除した要素をpopped_headに束縛する。
let popped_head = d.pop_front().unwrap();
# deque d の末尾要素を削除し、削除した要素をpopped_tail に束縛する
let popped_tail = d.pop_back().unwrap();
let ans = ans.into_iter().collect::<String>();
// use itertools::Itertools; をインポートしておく
let ans: String = tmp_vec
.into_iter()
.map(|x| x.to_string())
.join(" ");
// パスカルの三角形をテーブルとして作る
let mut comb = vec![vec![0; 61]; 61]; // 可変配列の確保
comb[0][0] = 1_i64;
for i in 0..60 {
for j in 0..i+1 {
comb[i+1][j] += comb[i][j];
comb[i+1][j+1] += comb[i][j];
}
}
https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a#4-累乗-an
// mod_powの実装。型がprimitiveなら何でも取れるようにする。
// a: 底, n: 指数, m: mod
fn mod_pow<T>(mut a: T, mut n: T, m: T) -> T
where
T: num_traits::PrimInt,
{
let mut res = T::one();
while n > T::zero() {
if n & T::one() == T::one() {
res = res * a % m;
}
a = a * a % m;
n = n >> 1;
}
res
}
// 逆元の計算
fn mod_inf<T>()
// 2の累乗かどうかの判定
fn is_pow2<T>(x: T) -> bool
where
T: num_traits::PrimInt,
{
if x == T::zero() {
return false
} else {
return (x & x - T::one()) == T::zero()
}
}
// 素因数分解する関数
fn prime_factorize(mut n: i64) -> Vec<(i64, i64)> {
let mut vec = vec![];
let mut cnt = 2;
while cnt * cnt <= n {
if n % cnt != 0 {
cnt += 1;
continue;
}
let mut ex = 0; // 指数
while n % cnt == 0 {
ex += 1;
n /= cnt;
}
vec.push((cnt, ex));
cnt += 1;
}
// 最後に残った数について
if n != 1 {
vec.push((n, 1));
}
vec
}
// 素数判定の関数
fn is_prime(n: i64) -> bool {
if n == 1 {
return false;
}
for j in 2..=n {
if j * j > n {
break;
}
if n % j == 0 {
return false;
}
}
true
}
use itertools::Itertools;
// nPr (n = 3, r = 2)
println!("Permutation.");
for perm in (0..3).permutations(2) {
println!("{:?}", perm);
}
// nCr (n = 3, r = 2)
println!("\nCombination.");
for perm in (0..3).combinations(2) {
println!("{:?}", perm);
}
// nHr (n = 3, r = 2)
println!("\nCombination with replacement.");
for perm in (0..3).combinations_with_replacement(2) {
println!("{:?}", perm);
}
let s: &str = "foo foo foo";
assert_eq!("faa faa faa", s.replace("o", "a"));
assert_eq!("fee fee foo", s.replacen("o", "e", 4));
https://qiita.com/aflc/items/f2be832f9612064b12c6
"あいう".chars().collect::<Vec<char>>();
順列の生成 https://github.com/bluss/permutohedron/blob/master/src/lexical.rs
追記 : superslice というクレートもあった。
// T が Vector の場合、昇順にsortしてある必要があるので注意
pub trait LexicalPermutation {
/// Return `true` if the slice was permuted, `false` if it is already
/// at the last ordered permutation.
fn next_permutation(&mut self) -> bool;
/// Return `true` if the slice was permuted, `false` if it is already
/// at the first ordered permutation.
fn prev_permutation(&mut self) -> bool;
}
impl<T> LexicalPermutation for [T] where T: Ord {
/// Original author in Rust: Thomas Backman <serenity@exscape.org>
fn next_permutation(&mut self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
// Step 1: Identify the longest, rightmost weakly decreasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] >= self[i] {
i -= 1;
}
// If that is the entire vector, this is the last-ordered permutation.
if i == 0 {
return false;
}
// Step 2: Find the rightmost element larger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j] <= self[i-1] {
j -= 1;
}
// Step 3: Swap that element with the pivot
self.swap(j, i-1);
// Step 4: Reverse the (previously) weakly decreasing part
self[i..].reverse();
true
}
fn prev_permutation(&mut self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
// Step 1: Identify the longest, rightmost weakly increasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] <= self[i] {
i -= 1;
}
// If that is the entire vector, this is the first-ordered permutation.
if i == 0 {
return false;
}
// Step 2: Reverse the weakly increasing part
self[i..].reverse();
// Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j-1] < self[i-1] {
j -= 1;
}
// Step 4: Swap that element with the pivot
self.swap(i-1, j);
true
}
}
use petgraph::unionfind::UnionFind;
fn main() {
input!{
n: usize,
m: usize,
}
let mut uf = UnionFind::new(n);
for _ in 0..m {
input! {mut a: usize, mut b: usize};
a -= 1;
b -= 1;
uf.union(a, b);
}
let set: HashSet<_> = uf.into_labeling()
.into_iter()
.collect();
println!("{:?}", set.len() - 1);
}
input!{#[allow(unused_imports)]
use proconio::{input, fastout, marker::Chars, marker::Usize1, marker::Bytes};
#[allow(unused_imports)]
use std::collections::{HashSet, HashMap, BTreeSet, VecDeque, BinaryHeap};
#[allow(unused_imports)]
use std::cmp::{max, min, Reverse};
#[allow(unused_imports)]
use itertools::Itertools;
#[allow(unused_imports)]
use petgraph::unionfind::UnionFind;
#[allow(unused_imports)]
use superslice::Ext;
fn main() {
input!{
mut s: Chars,
a: usize,
b: usize,
}
let aa = s[a-1];
let bb = s[b-1];
s[a-1] = bb;
s[b-1] = aa;
println!("{}", s.iter().join(""));
}
s: Chars,
t: Chars,
}
let ans = if s < t {
"Yes"
} else {
"No"
};
println!("{}", ans);
このサイト がわかりやすかった。
fn main() {
let mut s = String::new();
std::io::stdin().read_line(&mut s).ok();
let ans = s.split_ascii_whitespace().join(",");
println!("{}", ans);
}
fn main() {
input!{
_h: usize,
_w: usize,
p: [(u32, u32)],
}
// 座標圧縮で解く
let (mut x, mut y): (Vec<_>, Vec<_>) = p.iter().cloned().unzip();
x.sort();
x.dedup(); // 連続した重複要素を除去
y.sort();
y.dedup();
// superslice crate の Ext::lowerboundを使う
for (a, b) in p {
let a = x.lower_bound(&a) + 1;
let b = y.lower_bound(&b) + 1;
println!("{} {}", a, b);
}
}
https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_right
let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.rotate_right(2);
assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
while k > 0 {
if k % 2 == 1 {
ans.push(2);
} else {
ans.push(0);
}
k /= 2;
}
常に最大値 or 最小値を取り出せるデータ構造
// abc234 D
// 最小値を取り出す構造にするためには Reverse を用いる
let mut heap = BinaryHeap::new();
for i in 0..k {
heap.push(Reverse(p[i]));
}
println!("{}", heap.peek().unwrap().0);
for i in k..n {
if heap.peek().unwrap().0 < p[i] {
heap.pop();
heap.push(Reverse(p[i]));
println!("{}", heap.peek().unwrap().0);
} else {
println!("{}", heap.peek().unwrap().0);
}
}
}
https://zenn.dev/toga/books/rust-atcoder/viewer/13-format 2 進法,8 桁(0 埋め)
println!("{:08b}", 1_u8);
「!」をつけるとbit反転する
println!("{:08b} {:08b}", 1_u8, !1_u8);
// 00000001 11111110
https://zenn.dev/anozon/articles/rust-bit-len
fn blen(v: i64) -> u32 {
64 - v.leading_zeros()
}
std::mem::swap(&mut a, &mut b);
vec.swap(i, j); // Vec<_> バージョン
https://minerva.mamansoft.net/Notes/Rustのcloneとclonedの違い
(a + (b - 1)) / b
dfsで再帰から帰ってくるときのフラグを考える past202107-open J問題
https://note.com/kirimin_chan/n/n7663e3bb8a05
https://qiita.com/scivola/items/60141f262caa53983c3a code-formula-2014-final/src/bin/c.rs
根付き木が構成出来るなら、根からの深さの和を考えればよい https://yunix-kyopro.hatenablog.com/entry/2021/07/11/020240?_ga=2.121161536.9506465.1625937519-1301098457.1625937519#f-cd9f4786 https://blog.hamayanhamayan.com/entry/2021/07/11/154020
https://www.slideshare.net/satanic2/ss-72500089 (例)abc167 d
https://algo-logic.info/lca/ abc209 d
木ならば、頂点 N、辺 N - 1 木は 2部グラフ
EPSを適切に設定して比較に使う(誤差対策でA < BはA < B - EPSとするテンプレがある)
let mut d = format!("{:b}", x);
let ans = format!("{:010b}", n); // 10桁左0詰め
i64::from_str_radix(&d, 2).unwrap()
// https://qiita.com/hystcs/items/d33e77084277cdba8052
(例)
let v = vec![1, 2, 3];
for w in v.windows(2) {
let (prev, next) = (w[0], w[1]);
println!("{} {}", prev, next)
}
// 1 2
// 2 3
(例)
ans += t.windows(2).filter(|t| t[0] != t[1]).count(); // 前後で値が異なるときにカウント
let a = [1, 2, 3];
// the sum of all of the elements of the array
let sum = a.iter().fold(0, |acc, x| acc + x);
# 例えばこんな使い方
# abc109 c
use proconio::{input};
use num::integer::gcd;
fn main() {
input!{n:u32,x:u64,mut xn:[u64;n]}
xn.push(x);
xn.sort();
println!("{:?}",xn.windows(2).map(|a| a[1]-a[0]).fold(xn[1]-xn[0],|ans,v| gcd(ans,v)));
}