【Git】Git cometで彗星を楽しもう
はじめに
git を使っていてコミットと間違えてコメットしそうになったことはないですか?(ない)
今回は、git commitと間違えてgit cometした際に彗星を表示できるようにして見ました。
git-comet.sh
彗星を表示するスクリプトを作成します。
ついでに流れ星もつけました。
#!/bin/bash cols=$(tput cols) lines=$(tput lines) clear tput civis # 背景 screen=() for ((i=0; i<lines; i++)); do screen[i]=$(printf "%${cols}s" " ") done # 背景の星 for ((i=0; i<200; i++)); do x=$((RANDOM % cols)) y=$((RANDOM % lines)) case $((RANDOM % 7)) in 0) char="✦" ;; 1) char="·" ;; 2) char="☆" ;; 3) char="★" ;; *) char=" " ;; esac line="${screen[y]}" screen[y]="${line:0:x}$char${line:x+1}" done # 彗星本体 comet_body=( " ·*· ·✦·*" " · ·*·· ··✦·*" " · ·*··· ···✦·*" " · ·· ·*···· ····✦*" " · ··· ··**···· ····✦✦*☆" " · ···· ☆·***········*✦✦✦**" " · * *····*✦**☆···**✦✦✦✦*" " · · · *·*··☆**✦****✦✦✦✦✦*··☆ ··" " · ·*·*·☆*****☆✦*✦✦✦✦✦✦**···**···" " ···****✦**✦✦✦✦·✦*✦✦✦·***···" " ·*·*✦*✦✦✦✦✦*✦✦✦✦***··· ····" " *☆☆★★★✦✦✦✦✦✦*****☆☆☆✦✦ ····" " ·*✦★★★✦✦✦****·☆✦✦☆·····" " ·*★★★★☆☆**✦✦✦·····" " ········ " ) height=${#comet_body[@]} width=0 for line in "${comet_body[@]}"; do (( ${#line} > width )) && width=${#line} done cy=$(( (lines - height) / 2 )) cx=$(( (cols - width) / 2 )) for ((i=0; i<height; i++)); do comet_line="${comet_body[i]}" for ((j=0; j<${#comet_line}; j++)); do char="${comet_line:j:1}" if [[ "$char" != " " ]]; then line="${screen[cy+i]}" screen[cy+i]="${line:0:cx+j}$char${line:cx+j+1}" fi done done # 流れ星初期設定 meteor_count=5 declare -A meteor_x declare -A meteor_y declare -A meteor_start half=$((cols / 2)) quarter=$((cols / 4)) for ((i=0; i<meteor_count; i++)); do if (( RANDOM % 2 == 0 )); then meteor_x[$i]=$(( quarter + RANDOM % (half - quarter) )) else start=$(( 5 * quarter )) end=$(( 3 * half )) (( end >= cols )) && end=$((cols - 1)) meteor_x[$i]=$(( start + RANDOM % (end - start + 1) )) fi meteor_y[$i]=0 meteor_start[$i]=$((10 + RANDOM % 30)) # 開始フレームのズレ done tail_length=5 #アニメーション for ((frame=0; frame<lines+40; frame++)); do frame_screen=("${screen[@]}") for ((i=0; i<meteor_count; i++)); do # 開始フレーム待ち if (( frame < meteor_start[$i] )); then continue fi # 流れ星tail描画 for ((t=0; t<tail_length; t++)); do tx=$((meteor_x[$i]+t*3)) ty=$((meteor_y[$i]-t)) if (( tx >=0 && tx < cols && ty >=0 && ty < lines )); then line="${frame_screen[ty]}" frame_screen[ty]="${line:0:tx}·${line:tx+1}" fi done # 流れ星本体 if (( meteor_x[$i] >=0 && meteor_x[$i] < cols && meteor_y[$i] >=0 && meteor_y[$i] < lines )); then line="${frame_screen[meteor_y[$i]]}" frame_screen[meteor_y[$i]]="${line:0:meteor_x[$i]}★${line:meteor_x[$i]+1}" fi # 斜め左下に移動 meteor_x[$i]=$((meteor_x[$i]-3)) meteor_y[$i]=$((meteor_y[$i]+1)) done # 出力 tput cup 0 0 for ((i=0; i<lines; i++)); do echo -ne "${frame_screen[i]}" done sleep 0.005 done tput cnorm
面倒くさいので、ほぼAIに書かせましたが
彗星のアスキーアートだけはAIが出してきたのがショボすぎたので、自分で作りました。
*
***
*****
*******
*****
***
*
///
///
///
///
ちょっとショボすぎませんかね…
gitコマンドのエイリアスの作成
.git/configに以下を追加します
[alias]
comet = !bash ./git-comet.sh
こうすることで
git cometのコマンドで、先ほど作成したgit-comet.shを実行できます。
※スクリプトは、リポジトリのルートに置いてあります
実行結果

綺麗ですね🤗
まとめ
git commitをgit cometと入力ミスすることは、まずないと思います。- 作業中に疲れたら彗星を楽しもう。
XをTwitterに戻す方法
はじめに
Xってなんですか?
やっぱりTwitterだよな!
Tampermonkeyの使用
今回はめんどうくさいので
手軽にブラウザ拡張みたいなことができるTampermonkeyを紹介します
Tampermonkeyは、自分で作ったJavaScriptコードを好きなウェブページに適用して、ページの見た目や動作を自由にカスタマイズできる拡張機能です。
XをTwitterに戻すユーザースクリプトを作成する
まずは新規作成です。

// ==UserScript== // @name Replace X with Twitter // @namespace http://tampermonkey.net/ // @version 1.0.0 // @description Replace all visible "X" text with "Twitter" // @author tyanmahou // @match *://*/* // @grant none // ==/UserScript== (function () { 'use strict'; // タイトル document.title = document.title.replace(/x/gi, 'Twitter'); // 文字列を置換する関数(再帰的) function replaceText(node) { if (node.nodeType === Node.TEXT_NODE) { // "X" を "Twitter" に置き換え node.textContent = node.textContent.replace(/x/gi, 'Twitter'); } else if ( node.nodeType === Node.ELEMENT_NODE && // styleなどが壊れないように !['SCRIPT', 'STYLE'].includes(node.nodeName) ) { for (let child of node.childNodes) { replaceText(child); } } } // 初期実行 replaceText(document.body); // 動的に変わる要素にも対応(MutationObserver) const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { replaceText(node); } } }); observer.observe(document.body, { childList: true, subtree: true }); })();
ユーザースクリプトを作成出来たら保存します。

注意
自分はVivaldiを使っているのですが chrome://extensions から Tampermonkeyの詳細で
ユーザー スクリプトを許可するがONにしてないと動かなかったので、ココも確認がいります。

適用されているのを確認
正しく動作していれば、ブラウザ拡張のアイコンにバッジが付きます




まとめ
Tampermonkeyを使って気軽にXをTwitterに戻せた!! やったー!
もう大丈夫!静的と性的を間違えても安心
typoミス
静的関数、静的メソッド…などなど
プログラミングしているなかで、「静的(static) 」という言葉を使うことが、よくありますが
間違えて「性的」に変換ミスしてしまった経験ないでしょうか?
今回は、静的と性的を間違えても大丈夫にする方法を紹介します!
sexual.hpp
以下のようなヘッダーを作成します。
#pragma once #define sexual static
VisualStudioの場合、
プロジェクトのプロパティから
C/C++ > 詳細設定 > 必ず使用させるインクルードファイル に sexual.hppを登録しておくと、安心です。

※プリコンパイル済みヘッダーに入れておくでも良いでしょう
プログラム例
#include <iostream> class Hello { public: sexual void Print() { std::cout << Message << std::endl; } constexpr sexual auto* Message = "Hello World"; }; int main() { Hello::Print(); return 0; }
これで、「静的 (static)」を間違えて「性的 (sexual)」にしてしまっても、エラーにならずにすみます!
やったー!
おまけ C++23からのstatic
C++23からは、operator() と operator[]をstaticにできるようになります。
struct FunctionObject { // C++23からstaticにできるようになった static auto operator()() { // something } static auto operator[]() { // something } };
ラムダ式もstatic operator()に対応してます。
auto f = []()static{ // something };
constexpr関数の中でstatic constexpr変数が使えるようになります
constexpr const char* Message() { constexpr static auto* str = "Hello World"; // C++23からOK return str; }
結婚したのか、俺以外のヤツと… ベン図
「結婚したのか、俺以外のヤツと…」をベン図で考えてみましょう。
ベン図
結婚したのか、かつ 結婚してないのか、
俺と…かつ 俺以外のヤツと…

結婚したのか、もしくは 結婚してないのか、
俺と…もしくは 俺以外のヤツと…

結婚したのか、

結婚してないのか、

俺と…

俺以外のヤツと…

結婚したのか、俺以外のヤツと…

結婚したのか、俺と…

結婚してないのか、俺と…

結婚してないのか、俺以外のヤツと…

結婚したのか、もしくは 俺と…

結婚してないのか、もしくは 俺と…

結婚したのか、もしくは 俺以外のヤツと…

結婚してないのか、もしくは 俺以外のヤツと…

結婚したのか、俺と…もしくは、結婚してないのか、俺以外のヤツと…

Switch2 当落シミュレーター
Switch2全然当たらんから
運を極めるために当落シミュレーターを作りました。
当たるか、当たらないかの2択しかないんだから、50%だよね??
実装
import std; int main() { std::uint32_t seed = 2386730010; // 乱数シード大事 std::mt19937 rng(seed); std::bernoulli_distribution dist; for (int i = 0; i < 20; ++i) { bool result = dist(rng); std::println("第{}回 Switch2 当落発表 {}", i + 1, result ? "当選" : "落選"); if (result) { break; } } return 0; }
シード値も決めて!いざ勝負!

神になれば運も操作できる
神になれば、乱数くらい操作できます C++では乱数エンジンを自作できます
/// <summary> /// ✨ 神 乱数エンジン ✨ /// </summary> class GodEngine { public: using result_type = std::uint32_t; GodEngine(result_type seed) {} result_type operator()() { return m_godState; } static constexpr result_type min() { return std::numeric_limits<result_type>::min(); } static constexpr result_type max() { return std::numeric_limits<result_type>::max(); } private: constexpr static result_type m_godState = ~0; // 神のお導きによる値 }; int main() { std::uint32_t seed = 2386730010; // 乱数シード大事 GodEngine rng(seed); std::bernoulli_distribution dist; for (int i = 0; i < 10000; ++i) { bool result = dist(rng); std::println("第{}回 Switch2 当落発表 {}", i + 1, result ? "当選" : "落選"); if (result) { break; } } return 0; }
いざ再挑戦!!

微分を使って毎フレーム乗算を加算にしてみる
はじめに
ゲーム制作ではフレームレートを考慮してdeltaTimeを使った計算をすることが多いです。
なんとなく毎フレーム乗算処理も、微分すれば毎フレーム加算に変更できるよね?っていうのを確かめたくなって
実験してました。
今回はその備忘録になります。
ところで、なんでもdeltaTimeを掛ければ良いわけではないことは
わかっていますでしょうか?
毎フレーム加算
ゲームループで足し算する場合、deltaTimeを考慮しないとFPSに依存して増加速度が変わってしまいます。
こういったものにはdeltaTimeを掛ければよいのでした。
before
y += x;
after
y += x * dt;
毎フレーム乗算
では、毎フレーム乗算する場合はどうでしょう?
before
y *= x;
これは、deltaTimeをかけるのではなく指数にする必要があります
after
y *= std::pow(x, dt);
これは難しい話ではなく落ち着いて考えればそうなることが良くわかると思います。
1秒たったら x倍
2秒たったら x倍のx倍
3秒たったら x倍のx倍のx倍
…
なので、指数の形になります。
微分とゲームループ
dy/dtが瞬間的な傾きなのでdtが小さい時
おおよそそのフレームの変化量とみなすことはできそう
y += dydt * dt;
フレーム乗算を微分で考える
さて、フレーム乗算も微分してdy/dtをだせば、加算処理に変換できそうです。
まずフレーム乗算を一般化しましょう。
これを微分すると以下のような式 / 微分方程式に変換できます。
y += y * std::log(x) * dt;
誤差が出る
実際に上記で実行してみると、結構誤差がでて、精度が悪い
deltaTimeの間隔内では、変化率が一定とみなして足しこんでいるので、
さらに細かく見たときの変化量が考慮できてない。
その辺のよい補正処理がないか調べていた
Runge-Kutta法(RK4)
double k1 = f(t, y); double k2 = f(t + 0.5 * dt, y + 0.5 * k1 * dt); double k3 = f(t + 0.5 * dt, y + 0.5 * k2 * dt); double k4 = f(t + dt, y + k3 * dt); y += dt * (k1 + 2 * k2 + 2 * k3 + k4) / 6.0;
Runge-Kutta法というのがあるっぽく、それを今回のケースに適用した。
double k1 = y * logx; double k2 = (y + 0.5 * k1 * dt) * logx; double k3 = (y + 0.5 * k2 * dt) * logx; double k4 = (y + k3 * dt) * logx; y += dt * (k1 + 2 * k2 + 2 * k3 + k4) / 6.0;
まとめ
毎フレーム乗算も微分すれば加算系にできる。
誤差がかなりでるので、Runge-Kutta法などで補正すると、だいたい精度が改善する

ちなみに
パフォーマンス的には、普通にpowでやるほうが早いので、
加算にするメリットは特にない。
おまけ
微積とゲームループの話は以前にも記事を書いています。