あると便利かもしれないスニペット集2
あると便利かもしれないものたち
みなさんこんにちは、ALH開発事業部のREIYAです。
かゆいところに手が届くような便利スニペットをまとめてみました。
前回分もよろしくお願いします。
今回書いたもの
JS
Ajax
「あじゃっくす」と呼んでいます。ただしくは「えいじゃっくす」
// XXX こんなの環境変数でやってね!!!!これだめだからね!!!!
export const url = window.location.host == 'localhost:8080'
? 'http://localhost:3000/'
: 'https://商用.com/なんとかapi/';
export const Ajax = {
post(url, data, func, efunc) {
const method = "POST";
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'x-custom-header': 'some value',
};
const request = {
'data': data
};
console.debug(request);
const body = JSON.stringify(request);
fetch(url, {method, headers, body})
.then(res => {
// 400 <= res.status && res.status <= 499
// でもよい
if ([400, 401, 403].some(v => res.status == v)) {
if (efunc) {
efunc(res)
};
return;
}
if (!res.ok) {
throw new Error(res.statusText);
}
return res.json();
})
.then(v => {
console.debug(v);
// ここからはAPIレスポンス形による
if (v.api_status_core === '0') {
func(v);
} else {
efunc(v);
}
})
.catch(e => {
console.error(e);
});
},
// GET ...
};
現在日時
//yyyyMMdd
const now = new Date().toISOString().split("T")[0].replaceAll("-", "");
Date.now() // ミリ秒
sleep
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
async () => {
console.debug("start")
await sleep(1000)
console.debug("end")
}
連番生成
先頭が「[」で始まるので、前の行にセミコロンが必須です。
[...Array(100)].map((_, i) => i).forEach(...); // 0-indexed
[...Array(100).keys()].forEach(...); // 0-indexed
forどうしても書きたくない人向け
let a = 1
for (let i = 0; i < 10; ++i) {
a *= 2
}
console.log(a) // 1024
この程度(前回の結果を次に使う漸化式型、動的計画法)であれば以下でよい
console.log([...Array(10).keys()].reduce((x, y) => x * 2, 1))
こうでもいい。a *= 2のが文字数少ないですがなんとなくビット演算したかった
for(a=1,i=0;i<10;a<<=1,++i==10&&console.log(a));
文字列→数値へ変換
二重ビット否定で数値になる。数値変換できない文字の時は0になる(はず)
let str = "12345";
let number = ~~str;
const toint = str => ~~str;
jQueryもどき
HTMLいじる系です
const $$ = document;
const $ = v => v.startsWith('#') ? $$.getElementById(v.slice(1)) : $$.querySelector(v);
const _$ = (e = "div") => $$.createElement(e);
const DOM = str => new DOMParser().parseFromString(str, "text/html").body.firstElementChild;
const attr = (e, att) => Object.entries(att).map(([k, v]) => e[k] = v);
const css = (e, sty) => Object.entries(sty).map(([k, v]) => e.style[k] = v);
const event = (e, f, v = 'click') => e.addEventListener(v, f);
FFT
JSである必要は全くないですが、過去に理解のために書いたことがあるのでせっかくだから置いておきますね。
参考:
参考記事で勉強した際の名残でナイーブ実装のDFTもありますので、せっかくだから実行時間比較してみました。
なおデータ数が2冪じゃないとバグるので未完成ではあります。
wandboxでのpermlink共有
投入データ
dat = [10,10,12,13,15,13,12,10, 10,10,12,13,15,13,12,10];
[...Array(9).keys()].forEach(_ => dat = [...dat, ...dat]);
console.log(dat)
複素数用
exp = theta => [Math.cos(theta), Math.sin(theta)]
add = ([x1, y1], [x2, y2]) => [x1 + x2, y1 + y2]
sub = ([x1, y1], [x2, y2]) => [x1 - x2, y1 - y2]
mul = ([x1, y1], [x2, y2]) => [x1 * x2 - y1 * y2, x1 * y2 + y1 * x2]
DFT
dftc = (c, T) => [...Array(c.length).keys()]
.map(i => c.map((cn, n) => mul(cn, exp(T * n * i))).reduce(add, [0, 0]));
DFT = f => dftc(f, -2 * Math.PI / f.length)
IDFT = F => dftc(F, 2 * Math.PI / F.length).map(([r, i]) => [r / F.length, i / F.length])
start = Date.now()
discrete_tx = DFT(dat.map(r => [r, 0]));
discrete_rev = IDFT(discrete_tx).map(([r]) => r).map(Math.round);
console.assert(JSON.stringify(dat) === JSON.stringify(discrete_rev), {dat, discrete_rev});
console.log(discrete_tx)
console.log(discrete_rev)
console.log(Date.now() - start)
[
[ 97280, 0 ],
[ -4.778399897986674e-12, 9.47056669198254e-13 ],
[ 3.907985046680551e-14, -2.0174036052811317e-12 ],
中略
]
[
10, 10, 12, 13, 15, 13, 12, 10, 10, 10, 12, 13,
中略
]
13480
FFT
※ビット反転のとこでなにも考えずに$${log_2N}$$してるからだめです。バタフライ部分は大丈夫
function fftc(c, T, N) {
const rec = c.map((_, n) => c[[...Array(Math.log2(N)).keys()].reduce((x, y) => (x << 1) | ((n >>> y) & 1), 0)]);
for (let Nh = 1; Nh < N; Nh *= 2) {
T /= 2;
for (let s = 0; s < N; s += Nh * 2) {
for (let i = 0; i < Nh; i++) {
const l = rec[s + i], re = mul(rec[s + i + Nh], exp(T * i));
[rec[s + i], rec[s + i + Nh]] = [add(l, re), sub(l, re)];
}
}
}
return rec;
}
FFT = f => fftc(f, -2 * Math.PI, f.length)
IFFT = F => fftc(F, 2 * Math.PI, F.length).map(([r, i]) => [r / F.length, i / F.length])
start = Date.now()
FFT_tx = FFT(dat.map(r => [r, 0]));
FFT_rev = IFFT(FFT_tx).map(([r]) => r).map(Math.round);
console.assert(JSON.stringify(dat) === JSON.stringify(FFT_rev), {dat, FFT_rev});
console.log(FFT_tx)
console.log(FFT_rev)
console.log(Date.now() - start)
[
[ 97280, 0 ], [ 0, 0 ], [ 0, 0 ], [ 0, 0 ], [ 0, 0 ],
[ 0, 0 ], [ 0, 0 ], [ 0, 0 ], [ 0, 0 ], [ 0, 0 ],
中略
]
[
10, 10, 12, 13, 15, 13, 12, 10, 10, 10, 12, 13,
中略
]
53
DFT 13480msに対しFFT 53msですね、こう見ると威力を感じます。logは偉大。
最初の方でデータ数16個を$${2^9}$$倍していますが、10乗あたりからwandboxではメモリ足りなくなったからです。
だれか2冪丸め版作ってください。
React
ReactもJSじゃないか!というツッコミは受け付けていません。
ちなみに分割代入とスプレッド構文が入り乱れるのでReduxはあまり好きではないです...。
useStateコピー注意やつ
const [arr, setArr] = useState<[]>([]);
let tmp = [...arr] // ディープコピーすること!
// tmpに操作
setArr(tmp)
以下がダメ例。昔ずっと悩んでたstate更新されない問題はだいたいこれが原因でした。ほんまこいつ...
let tmp = arr
// tmpに操作
setArr(tmp)
メモ化
お手軽の高速になる(!?)やつ。仮装DOMとの差分レンダリングを操作しているイメージ。なるべく変えるなよって感じ。
const isOpen = useMemo(() => {
let st: boolean = false;
// なにやら処理
return st;
}, [watchArg]);
副作用管理
useEffectです。hookって過激派多いので深くは触れないでおきますね
const [cnt, setCnt] = useState(0);
useEffect(() => {
console.log(`new count is ${cnt}`);
}, [cnt]);
オレオレコンポーネント
なんかこう、カッコが多いのであんま好きじゃないです。
type Props = {
name: string;
value: string;
func: (e: React.ChangeEvent<HTMLInputElement>) => void;
};
const MyComponent: React.FC<Props> = (({name, value, func}) => {
useEffect(() => {}, []);
return (
<div className={some}>
<div ...>
</div>
);
});
export default MyComponent;
axios
Reactじゃないですが、どうせみなさん一緒に使ってますよね?
import axios from "axios"
export function my_post(url, data) {
const host = 'いいかんじに取得';
// cookieにtoken、sessionStorageに値があるとする
let token = document.cookie.split(";").map(v => v.trim()).filter(v => v.startsWith("token="))
token = token.length === 0 ? "" : token[0].split("=")[1]
const headers = {
'Content-Type': 'application/json',
'x-custome-header': sessionStorage.getItem("some value"),
'x-custome-token': token
}
return axios.post(host + url, data, {headers: headers});
}
Rust
チェーン
Javaでいうstreamのようにiterのチェーンを。
forと一応比較しておく
fn main() {
let list = vec!["test", "test"];
let a: Vec<String> = list.iter()
.filter(|&v| *v == "test")
.inspect(|&v| println!("{}", *v))
.map(|&v| v.to_string())
.collect();
for v in list.iter() {
if *v == "test" {
println!("{}", v);
}
}
for v in 0..a.len() {
println!("{}", v);
}
}
フィボナッチ
行列累乗です。多倍長数値演算ライブラリrugを使用する版はこちらの記事で取り上げられています。FFTらしいので高速。
$$
\begin{pmatrix}
1 & 1 \\
1 & 0
\end{pmatrix}
\begin{pmatrix}
F_{n+1} \\ F_{n}
\end{pmatrix} =
\begin{pmatrix}
F_{n + 1} + F_{n}\\ F_{n+1}
\end{pmatrix}
\begin{pmatrix}
F_{n + 2} \\ F_{n+1}
\end{pmatrix}
$$
use std::io::stdin;
fn fib(n: i32) -> i32 {
if n < 1 {
return 0;
}
let mut mat: Vec<Vec<i32>> = vec![
vec![1, 1],
vec![1, 0],
];
let factor: Vec<Vec<i32>> = vec![
vec![1, 1],
vec![1, 0],
];
for _ in 1..n {
let mut tmp = vec![
vec![0, 0],
vec![0, 0],
];
tmp[0][0] = (
mat[0][0].clone() * &factor[0][0]
) + (
mat[0][1].clone() * &factor[1][0]
);
tmp[0][1] = (
mat[0][0].clone() * &factor[0][1]
) + (
mat[0][1].clone() * &factor[1][1]
);
tmp[1][0] = (
mat[1][0].clone() * &factor[0][0]
) + (
mat[1][1].clone() * &factor[1][0]
);
tmp[1][1] = (
mat[1][0].clone() * &factor[0][1]
) + (
mat[1][1].clone() * &factor[1][1]
);
mat = tmp;
}
return mat[0][1].clone();
}
fn input() -> i32 {
let mut buf = String::new();
stdin().read_line(&mut buf).unwrap();
return buf.trim().parse().unwrap();
}
fn main() {
let n: i32 = input();
let res = fib(n);
println!("{}", res);
}
C++
約数
いったい何が役立つのか全くわからず苦しまぎれ。
未ソートでの約数全列挙
#include <iostream>
#include <vector>
template <typename T> std::vector<T> divisors(T a) {
std::vector<T> res;
for (T i = 1; i * i <= a; ++i) {
if (a % i != 0) continue;
res.push_back(i);
if (a / i != i) res.push_back(a / i);
}
return res;
}
int main() {
int N;
std::cin >> N;
for (auto &&v : divisors(N)) {
std::cout << v << std::endl;
}
}
素因数分解
なんとなく書いておきます。
#include <iostream>
#include <map>
template <typename T> std::map<T, int> p_fact(T N) {
std::map<T, int> P;
for (T i = 2; i * i <= N; ++i) {
while (N % i == 0) {
++P[i];
N /= i;
}
}
if (N > 1) ++P[N];
return P;
}
int main() {
int N;
std::cin >> N;
for (auto &&[k, v] : p_fact(N)) std::cout << k << ": " << v << std::endl;
}
FFT
jsで書いたのでせっかくですし。
ついでに畳み込みも作ってあるので載せときます。
こっちはちゃんと2冪丸めしてます。
#include <bits/stdc++.h>
using namespace std;
namespace FFT {
using real = double;
struct C {
real x, y;
C() : x(0), y(0){};
C(real x, real y) : x(x), y(y){};
inline C operator+(const C &c) const {
return C(x + c.x, y + c.y);
}
inline C operator-(const C &c) const {
return C(x - c.x, y - c.y);
}
inline C operator*(const C &c) const {
return C(x * c.x - y * c.y, x * c.y + y * c.x);
}
inline C conj() const {
return C(x, -y);
}
};
const real PI = acosl(-1);
int base = 1;
vector<C> rts = {{0, 0}, {1, 0}};
vector<int> rev = {0, 1};
void ensure_base(int nbase) {
if (nbase <= base) return;
rev.resize(1 << nbase);
rts.resize(1 << nbase);
for (int i = 0; i < (1 << nbase); i++) {
rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
}
while (base < nbase) {
real angle = PI * 2.0 / (1 << (base + 1));
for (int i = 1 << (base - 1); i < (1 << base); i++) {
rts[i << 1] = rts[i];
real angle_i = angle * (2 * i + 1 - (1 << base));
rts[(i << 1) + 1] = C(cos(angle_i), sin(angle_i));
}
++base;
}
}
void fft(vector<C> &a, int n) {
assert((n & (n - 1)) == 0);
int zeros = __builtin_ctz(n);
ensure_base(zeros);
int shift = base - zeros;
for (int i = 0; i < n; i++) {
if (i < (rev[i] >> shift)) swap(a[i], a[rev[i] >> shift]);
}
for (int k = 1; k < n; k <<= 1) {
for (int i = 0; i < n; i += 2 * k) {
for (int j = 0; j < k; j++) {
C z = a[i + j + k] * rts[j + k];
a[i + j + k] = a[i + j] - z;
a[i + j] = a[i + j] + z;
}
}
}
}
} // namespace FFT
畳み込みと呼んでみる。
llround誤差あるので気になる場合はNTTすること
template <typename R>
vector<long long> convolution_fft(const vector<R> &a, const vector<R> &b) {
using C = FFT::C;
int need = (int)a.size() + (int)b.size() - 1, nbase = 1;
while ((1 << nbase) < need) ++nbase;
FFT::ensure_base(nbase);
int sz = 1 << nbase;
vector<C> fa(sz);
for (int i = 0; i < sz; i++) {
double x = i < (int)a.size() ? a[i] : 0;
double y = i < (int)b.size() ? b[i] : 0;
fa[i] = C(x, y);
}
FFT::fft(fa, sz);
C r(0, -0.25 / (sz >> 1)), s(0, 1), t(0.5, 0);
for (int i = 0; i <= (sz >> 1); i++) {
int j = (sz - i) & (sz - 1);
C z = (fa[j] * fa[j] - (fa[i] * fa[i]).conj()) * r;
fa[j] = (fa[i] * fa[i] - (fa[j] * fa[j]).conj()) * r;
fa[i] = z;
}
for (int i = 0; i < (sz >> 1); i++) {
C A0 = (fa[i] + fa[i + (sz >> 1)]) * t;
C A1 = (fa[i] - fa[i + (sz >> 1)]) * t * FFT::rts[(sz >> 1) + i];
fa[i] = A0 + A1 * s;
}
FFT::fft(fa, sz >> 1);
vector<long long> ret(need);
for (int i = 0; i < need; i++) {
ret[i] = llround(i & 1 ? fa[i >> 1].y : fa[i >> 1].x);
}
return ret;
}
int main() {
vector<int> A = {1, 2, 3, 4, 5};
vector<int> B = {2, 3, 5, 7, 11, 13};
for (auto &&v : convolution_fft(A, B)) {
cout << v << endl;
}
}
おわり
前回同様統一感ないですが、どこかで使えることがあったらうれしいです。
ALHについて知る
↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓
↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓
↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓