Call of Duty®ファンのための HDD が発売していた
不肖筆者は下記の自己紹介記事にもある通り、FPS と Minecraft が死ぬほど好きな一般人です。最近は若干忙しくて、FPS の方を触れていないのですが...
忙しい忙しいと嘆きながら Minecraft は、やっていたわけですが(苦笑)
で、筆者の FPS 歴はそれほど長くなく、簡単に述べると
BF4の現代戦に魅せられて FPS を始め、BFV の「ワタシガシタイノハコレジャナイ」感に困惑しつつも M1907 SF での銃剣突撃に楽しさを感じ、CoD:MW の発売が決定するとともに「これに決まりだ」と確信し、CoD に移行 |
といった流れになります。CoD:CW はまだ触れていません(泣)
このタイトルのページを読んでいる時点でないとは思いますが、CoD ってどんなゲームだよって方は筆者が自戒のために(?) YouTube にあげた謎の動画があったのでどうぞ。そんなに強くないのでお手柔らかにお願いします...
この動画では MP7 を使っていますが、筆者のお気に入りは Uzi です。個人的には強化前の Uzi の方が「正面では打ち勝てないから立ち回りで何とかする」という点で楽しかったです。今は強化され過ぎて逆にコレジャナイ感が漂っている...
と、身の上話はここまでにしておきましょう。
本題の HDD がこちらです。
WD ポータブルHDD 2TB WD_Black P10 Call of Duty Edition cod ポイント付き USB 3.2 Gen1 / 3年保証 WDBAZC0020BBK-WESN
- 発売日: 2020/12/29
- メディア: Personal Computers
WD から発売されています。調べた感じだと 2TB のみのようです。PC はもちろんのこと、更に PS4 pro, PS4, Xbox one にも対応しています。恐らく PS5 にも接続可能でしょう。1100 CoD ポイントが得点でついているので、(筆者確認時点で)実質11,000円強と言えるでしょう。PS4 などで容量を圧迫しているクリップの整理用にいかがでしょうか。
筆者自身はあまり重要視していないですが、表記を見る限りでは3年保証(HDDではかなり長いほう)のようなので安心して使いやすいと言えます。
いっそのこと JavaScript の Array で行列を計算できるようにしてしまおう
初めに
本稿は配列を配列のまま行列計算できるようにしたいという謎の考えの下で超絶適当な実装をしようとした筆者を供養するためのものです。ライブラリ使えよっていう
最新のコードはページ最下部のまとめに置いてます。
JavaScript を学び始めて1週間も経ってないのでエラーの出し方とかが気になる方もいるとは思いますが、そこは適宜変更を加えてください。
少し考えればLU分解とかも書けるのでしょうが疲れてしまったので気が向いたときに追記します。(たぶんそっちの方が重要なんだろうけど...)何か問題点を見つけた人はお手数ですがコメントまでお願いします。
関数群
配列(など)をJSONで厳密に比較
function JSON_equal(x, y) { return JSON.stringify(x) === JSON.stringify(y); }
例えば、
JSON_equal([[1,2],[1,2]], [[1,2],[1,2]])
にtrue
JSON_equal([[1,2],[1,2]], [[1,2],[1,3]])
にfalse
を返します。
今回は配列を比較するために使いますが、それ以外にも適応可能で結構万能です。たぶん、null や undifined もきちんと区別します。
行列として扱えるか確認する
function is_matrix(array) { let row = array.length; let col = array[0].length; if (col === undefined) { return false } for (i in array) { if (array[i].length !== col) { return false } } return [row, col]; }
各行の要素数を比較し、一致しなければfalse
を返します。要は、[[1,2], [3,4,5]]
などを除外するために使います。ちなみに、[1,2,3]
も除外します。行ベクトルを表現する場合は[[1,2,3]]
です。
返り値は[行数, 列数]
の配列です。
追記(今気づいた): 無駄に1回forを回しているので、気になる人は直しといてください。
m*nの零行列
function zeros(row, col) { if ((row < 1) || (col < 1)) { throw new Error('IndexError'); } let zeros = []; for (let i = 0; i < row; i++) { let tmp = []; for (let j = 0; j < col; j++) { tmp.push(0); } zeros.push(tmp); } return zeros; }
その名の通りzeros(m,n)
で m*n の零行列を返します。何のひねりもない素朴な実装です。
m*n の単位行列
function eye(row, col) { if ((row < 1) || (col < 1)) { throw new Error('IndexError'); } let eye = []; for (let i = 0; i < row; i++) { let tmp = []; for (let j = 0; j < col; j++) { tmp.push(Number(i === j)); } eye.push(tmp); } return eye; }
こちらも、その名の通りeye(m,n)
で m*n の単位行列を返します。何のひねりもない(ry
対角行列
function diag(...c) { let diag = []; for (let i = 0; i < c.length; i++) { let tmp = []; for (let j = 0; j < c.length; j++) { if (i !== j) { tmp.push(0); } else { tmp.push(c[i]); } } diag.push(tmp); } return diag; }
対角行列を求めます。例えば、diag(1,2)
で[[1,0],[0,2]]
を返します。diag(1)
もいけます。もちろん、[[1]]
が返ってきます。
行列の和
function add_asmatrix(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (!JSON_equal(Amn, Bmn)) { throw new Error('row or column does not match.'); } let tmp = zeros(...mn); for (i in A) { for (j in A[i]) { tmp[i][j] = A[i][j] + B[i][j]; } } return tmp; }
本当は X + Y みたいに書けるとベストなんだろうけど、そうすると Matrix オブジェクトを作って(たぶん)、演算子のオーバーロードをして...とそれをやりたくないから Array のまま計算できるようにしたかったのだ!と本末転倒なので関数での実装に留めます。
行列の差
function sub_asmatrix(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (!JSON_equal(Amn, Bmn)) { throw new Error('row or column does not match.'); } let tmp = zeros(...mn); for (i in A) { for (j in A[i]) { tmp[i][j] = A[i][j] - B[i][j]; } } return tmp; }
行列の差です。(見出しにそう書いてあるので、そうであることは当たり前)
和のときと同じです。特に言うことはありません。
行列のスカラー倍
function scalar_mul(A, x){ let mn = is_matrix(A); if (mn) { throw new Error('Array is not matrixlike.'); } let tmp = zeros(...mn); for (i in A) { for (j in A[i]) { tmp[i][j] = A[i][j] * x; } } return tmp; }
scalar_mul(A, x)
で を求めます。逆なのはあまり気にしないことにしましょう。スカラー倍なので。
行列の転置
function T(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } let tmp = zeros(mn[1], mn[0]); for (i in A) { for (j in A[i]) { tmp[j][i] = A[i][j]; } } return tmp; }
T(A)
で行列 A の転置を求めます。
行列の乗算
function mul_asmatrix(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (Amn[1] !== Bmn[0]) { throw new Error('multiplication is not defined.') } let tmp = zeros(Amn[0], Bmn[1]); for (i in tmp) { for (j in tmp[i]) { for (let k = 0; k < Amn[1]; k++) { tmp[i][j] += A[i][k] * B[k][j]; } } } return tmp; }
ここまで来てやっと一般的には であることを確認できますね。
対角成分の抽出
function extract_diag(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = [] for (i in A) { tmp.push(A[i][i]); } return diag(...tmp); }
正方行列 A の対角成分を抽出した正方行列を返します。
例えば、extract_diag([[1,2],[3,4]])
は[[1,0],[0,4]]
になります。
下三角行列
function lower(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = zeros(...mn); for (i in A) { for (let j = 0; j <= i; j++) { tmp[i][j] = A[i][j]; } } return tmp; }
正方行列 A の下三角行列を返します。
例えば、lower([[1,2],[3,4]])
は[[1,0],[3,4]]
になります。
上三角行列
function upper(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = zeros(...mn); for (i in A) { for (let j = i; j < mn[0]; j++) { tmp[i][j] = A[i][j]; } } return tmp; }
正方行列 A の上三角行列を返します。
例えば、upper([[1,2],[3,4]])
は[[1,2],[0,4]]
になります。
だんだん冗長になってきましたね?
行列の対角和(トレース)
function tr(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = 0; for (i in A) { tmp += A[i][i]; } return tmp; }
行列 A の対角和(トレース)を返します。
例えば、tr([[1,2],[3,4]])
なら1+4で5になります。
行列の内積
function inner_prod(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (!JSON_equal(Amn, Bmn)) { throw new Error('inner product is not defined.') } let tmp = 0; for (i in A) { for (j in A) { tmp += A[i][j] * B[i][j] } } return tmp; }
読んで字のごとく内積〈A, B〉を求めます。
まとめ
上記のコードをまとめておきます。見てもよくわからない人は取り敢えず以下をコピペすれば上で紹介した関数をすべて使えるようになります。使用者がこのページへのリンクを布教すると、筆者は泣いて喜びます。
//配列(など)をJSONで厳密に比較 function JSON_equal(x, y) { return JSON.stringify(x) === JSON.stringify(y); } //行列として扱えるか?扱えないならfalse, 扱えるなら[row, col]を返す。 function is_matrix(array) { let row = array.length; let col = array[0].length; if (col === undefined) { return false } for (i in array) { if (array[i].length !== col) { return false } } return [row, col]; } //零行列 function zeros(row, col) { if ((row < 1) || (col < 1)) { throw new Error('IndexError'); } let zeros = []; for (let i = 0; i < row; i++) { let tmp = []; for (let j = 0; j < col; j++) { tmp.push(0); } zeros.push(tmp); } return zeros; } //単位行列 function eye(row, col) { if ((row < 1) || (col < 1)) { throw new Error('IndexError'); } let eye = []; for (let i = 0; i < row; i++) { let tmp = []; for (let j = 0; j < col; j++) { tmp.push(Number(i === j)); } eye.push(tmp); } return eye; } //対角行列 function diag(...c) { let diag = []; for (let i = 0; i < c.length; i++) { let tmp = []; for (let j = 0; j < c.length; j++) { if (i !== j) { tmp.push(0); } else { tmp.push(c[i]); } } diag.push(tmp); } return diag; } //行列の和 A+B function add_asmatrix(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (!JSON_equal(Amn, Bmn)) { throw new Error('row or column does not match.'); } let tmp = zeros(...mn); for (i in A) { for (j in A[i]) { tmp[i][j] = A[i][j] + B[i][j]; } } return tmp; } //行列の差 A-B function sub_asmatrix(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (!JSON_equal(Amn, Bmn)) { throw new Error('row or column does not match.'); } let tmp = zeros(...mn); for (i in A) { for (j in A[i]) { tmp[i][j] = A[i][j] - B[i][j]; } } return tmp; } //行列のスカラー倍 xA function scalar_mul(A, x) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.'); } let tmp = zeros(...mn); for (i in A) { for (j in A[i]) { tmp[i][j] = A[i][j] * x; } } return tmp; } //行列の転置 A^t function T(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } let tmp = zeros(mn[1], mn[0]); for (i in A) { for (j in A[i]) { tmp[j][i] = A[i][j]; } } return tmp; } //行列の乗算 AB function mul_asmatrix(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (Amn[1] !== Bmn[0]) { throw new Error('multiplication is not defined.') } let tmp = zeros(Amn[0], Bmn[1]); for (i in tmp) { for (j in tmp[i]) { for (let k = 0; k < Amn[1]; k++) { tmp[i][j] += A[i][k] * B[k][j]; } } } return tmp; } //行列の対角成分を抽出する function extract_diag(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = [] for (i in A) { tmp.push(A[i][i]); } return diag(...tmp); } //行列Aの下三角行列 function lower(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = zeros(...mn); for (i in A) { for (let j = 0; j <= i; j++) { tmp[i][j] = A[i][j]; } } return tmp; } //行列Aの上三角行列 function upper(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = zeros(...mn); for (i in A) { for (let j = i; j < mn[0]; j++) { tmp[i][j] = A[i][j]; } } return tmp; } //行列のトレース(対角和) function tr(A) { let mn = is_matrix(A); if (mn === false) { throw new Error('Array is not matrixlike.') } if (mn[0] !== mn[1]) { throw new Error('square matrix only')} let tmp = 0; for (i in A) { tmp += A[i][i]; } return tmp; } //行列の内積 <A,B> function inner_prod(A, B) { let Amn = is_matrix(A); Bmn = is_matrix(B); if (Amn === false || Bmn === false) { throw new Error('Array is not matrixlike.'); } if (!JSON_equal(Amn, Bmn)) { throw new Error('inner product is not defined.') } let tmp = 0; for (i in A) { for (j in A) { tmp += A[i][j] * B[i][j] } } return tmp; }
今日から Raspberry Pi 4 Model B (8GB) が Amazon でセールだった(気づいてなかった)
Raspberry Pi 4 Model B (8GB) が Amazon でセールになって安くなっていた。
2021/1/17 の 23:45 までらしい。
ちゃんと技適マークがついているので申請無しで使えるからありがたい。
一応、付属の microSD には NOOBS がプリインストールされているっぽいので、ラズパイ初めて買う人にも優しそう。ラズパイ買おうか悩んでいる人はこの機会に是非、という布教活動。私もサーバー用に買い足そうか悩んでいます(笑)
という喜びのほぼ日記。
足し算の暗算をしよう!(開発中)
はてなブログを開設したら Google Search Console に登録しよう!
そもそも Google Search Console って?
Google Search Console は Google が提供するウェブサイト制作者向けのツールです。このツールを使うことで、「自身のサイトが平均して何位程度の位置に表示されるのか」や、「どのようなキーワードで表示され、サイトのクリックにつながったのか」などといったことを知ることができます。さらには、「拡張としてリッチリザルトに対応しているか(これに対応していると Google が使いやすいサイトであると認識してくれる可能性が高まります)」や、「サイト全体にセキュリティの面で問題はないか」を確認することができます。
Google Search Console はブログを運営していくうえで、なくてはならない存在だといえるでしょう。
どうやって登録するの?
登録の方法自体は至って簡単です。
1.「今すぐ開始」
Google Search Console リンクを貼っておきました。
上記のリンクで Google Search Console のページに飛べます。
迷わずに(迷う人いるのか?)これをクリックします。
2. URL を登録する
1 で今すぐ開始をクリックすると、""Google Search Console へようこそ""と書かれたこのような画面が表示されると思います。
この画面の右側、URL プレフィックスの欄に自身のブログ URL (はてなブログの場合は 設定->基本設定->ブログURL で確認できます。)を入力し、続行をクリックします。例えば、私の場合はhttps://northclimb.hatenablog.com
と入力します。
3. 所有権の確認を行う
「所有権の確認」というフォームが開くので、少しスクロールして HTML タグと書かれた部分をクリックします。すると、コピーボタンのあるタグが表示されます。
この中のcontent="~~"
の~~
の部分だけをコピーしてください。
~~
はアルファベットと数字で構成されています。
上手くコピーできない人はコピーボタンを押して全体をコピーし、テキストエディタなどに貼り付けてcontent="~~"
の~~
の部分をコピーしなおしてください。
そのコピーした部分をはてなブログの 設定->詳細設定->解析ツール->Google Search Console にある入力欄に貼り付けます。
こんな感じのところです。そして、ページ下まで行き、変更するボタンを押して更新してください。
ここで先ほどの Google Search Console の画面に戻り、確認ボタンを押します。そのまま確認されれば登録の完了です。
上手くいかない場合は、HTML タグのコピーする箇所を間違えていないか、タグを貼り付けた後にはてなブログの変更ボタンを押し忘れていないかを確認してください。
興味あったら読んでみてください。
SEO 関連の個人的な良書を載せておきます。
2015年から長く売られている入門書
- 作者:土居 健太郎
- 発売日: 2015/04/23
- メディア: 単行本(ソフトカバー)
ストーリー性があって、とっつきやすい本。これも結構長く売られている。
はてなブログのサイトマップがGoogle Search Consoleに読み込まれないときにすること
前提
既に Google Search Console にサイトの登録は済んでいて以下のような画面を開ける状態だと仮定します。
この画面で左側のサイトマップをクリックしたときに、
こんな感じで sitemap.xml の検出されたURLが0件になってしまっている人が本記事の対象です。
URLが検出されるサイトマップの追加方法
1. 自身のサイトマップを開く
まずはどんなブラウザでもよいので、このように自身のサイトマップを検索欄に入力して開きます。
一般的にサイトマップはブログURL/sitemap.xml
に置かれているようです。私の場合はブログURLがhttps://northclimb.hatenablog.com
なのでhttps://northclimb.hatenablog.com/sitemap.xml
を入力します。
2. 要素を探して登録を繰り返す
このようなページを開けたでしょうか?
この中で<loc></loc>
で囲われている部分を Google Search Console にサイトマップとして登録していきます。
この部分に、
こんな感じですね。そのまま送信を押します。
これを繰り返して、全ての<loc></loc>
部分を登録すれば完了です。
このような状態になっていれば成功です。正しくURLが検出されています。
編集後記&思いついたこと
Python の beauftifulsoup とかを使えばこの作業も自動化できる気がします。なんせ繰り返し作業が多いので。
Google Search Console に API があれば簡単に作れそうです。
Pythonで自動化を頑張ってみたい人とかはこの本を読んでみてください。私の聖書兼文鎮です。かなり重い。(物理的)
iPhone 8 以降なら充電器はワイヤレスにしてしまおう(Anker PowerWave 10 Stand のレビュー)
前口上
皆さんはスマートフォンの充電はどのように行っているのでしょうか。ほとんどの人が充電ケーブルを使っていると思います。
私は2020年11月から Anker 製のワイヤレス充電器を使っています。
それまでは私も充電ケーブルを使っていたのですが、晴れて(曇って?) Lightning ケーブルのメス ( iPhone 側のほう) がお亡くなりになりました。そうなると普通はもう充電ができなくなって買い替えになるのですが、ありがたいことに iPhone X は Qi 対応なのでワイヤレス充電ができるらしい。ということで、使い始めた次第です。
買ったのがこちら↓
そもそもQiって何ぞ
Qi (チー) は、WPC (Wireless Power Consortium) が策定した、ワイヤレス給電のオープンな国際標準規格です。 チーという発音からも想像できるように、この名前の由来は中国語の"气"です。様々なワイヤレス充電器が世界で独自開発されていく中で製品の互換性を担保するために策定されました。Qi 対応と表記されている製品は Qi に認証された充電器を使ってワイヤレス充電ができるようになります。
商品レビューが悪いけどそんなことはない。
さて、本題の私が購入した Anker PowerWave 10 Stand(改善版) なのですが、商品レビューがかなり酷いことになっています。私が見たところでは、「おそらく、説明書が簡易的なもので誤解が生じてしまっているのだろう。」と感じるようなレビューが多かったです。
実際には縦置きでも横置きでも充電できる、何なら逆さまに置けば AirPods Pro も充電できる強者です。平べったいワイヤレス充電器が多い中でスマートフォンを立てたまま充電できるのはなかなかに使い勝手が良いといえるでしょう。
補遺: 私から充電できなかった時のアドバイスを以下に記しておきます。
1. 使用するACアダプターに注意
使用するACアダプターは5V/2A以上のものを使ってください。 Apple 製スマートフォンに付属しているACアダプターは5V/1Aなのでワイヤレス充電をするには出力不足になります。さらに、一般的にはPCのUSBポートでも出力不足になります。
また、5V/2A以上の出力を持つACアダプターでも、ポートが2つ以上あるものについては接続されている機器が増えるほど1つのポート当たりの出力が低下します。その場合は使用するポートをワイヤレス充電器のみに絞ることをお勧めします。比較的安価なものであれば、例えば下記のACアダプターは5V/3Aなので余裕をもって使えるでしょう。
2. 使用するケーブルに注意
もう一つ見落としがちなのが本体につなぐmicroUSBケーブルです。microUSBケーブルにも出力できる限度があるので、素直に付属でつけてくれているものを使いましょう。
3. スマートフォンのケースに関して
スマートフォン本体と充電器の間は5mm以内である必要があります。また、ワイヤレス充電は磁気を使った充電方法なので、スマートフォン本体と充電器の間にクレジットカードなどの磁気を帯びたカードや金属製のケースがあると安定して充電できません。
4. システムソフトウェアに関して
1~3のアドバイスは購入直後に使えない場合ですが、これは今まで使えていたのに急に使えなくなった場合にかなり当てはまりそうです。Apple サポートにも書いてある通り最新のシステムソフトウェアでないと充電できないです。筆者も1度充電できなくなったことがあったのですが、システムソフトウェアアップデートを行ったら直ちに充電が可能になりました。
皆様の良いワイヤレスライフを願って...