Python で書く代数 - pyarith よ, 私は帰ってきた

1年ぶりの pyarith の記事です. 実は Python で書く代数 を書いてから, 追加した実装があるのでそれについて書きます.

書いてあること

  • pyarith のおさらい
  • 環について
  • 環の公理とテストケースの対応

おさらい

pyarith とは Python でどこまで代数的対象が表現できるかの実験ライブラリです. Python コードは読めるけど代数学のことは知らない人に, 代数的概念を説明することを目的としています. 今のところライブラリとしての実用性は目指していません. おそらくパフォーマンスも出ません.

前々回の記事 で「群」の解説をし, 前回の記事 で群であることを確かめるテストについて解説しました. このテストでは pytest というライブラリを使用し, パラメータ化されたテストを行いました.

この記事を書いたおかげで pytest に興味を持ってくれた人もいたようで, ちょっと嬉しいです.

前回扱ったのは「群」という概念でしたが, 今回は「環」を取り上げます.

群はある規則を満たす集合でした. 環は, 群にさらに満たすべき規則を追加した集合です.

群と環にどんな差分があるかは環を実装した Ring クラスの実装を見てみましょう. https://bitbucket.org/cocoatomo/pyarith/src/dfbb010c50390e5dece00b92558a5c3461199507/tests/test_ring.py ここから分かるのは「環は群に無い __mul__ というメソッドを持つ」ということです.

この Ring クラスと __mul__ というメソッドに課せられた制限はテストケースで表すのでした.

テストケースとその意味
test_mul_welldefined_right 右からの乗算が well-defined であること
test_mul_welldefined_left 左からの乗算が well-defined であること
test_ONE (乗法に関する) 単位元の存在
test_mul_ONE 単位元の性質
test_mul_associative_law 乗法の結合律

乗法は可換とは限らない演算なので, 可換性に関するテストはありません.

また加算と乗算が両方登場する性質を表すテストケースとして以下のものがあります.

テストケースとその意味 (2)
test_distributing_law 分配法則

小学生の頃に分配法則という言葉が出てきましたが, 当時はここまで重要な性質だとは思いませんでした.

環の公理一覧については http://ja.wikipedia.org/wiki/%E7%92%B0_(%E6%95%B0%E5%AD%A6) を参照してください.

『「異様に難しいドラクエの謎解き」をモデル検査器で解く』代わりに数学で解く

前置き

タイトルは本歌取りもいい加減にしろ, という長さですが. こんなつぶやきをしたので, 予告どおり記事を書きます.

酒井さんの続きの記事 → http://msakai.jp/d/?date=20130402#p01

解説

まず方針としては酒井さんと同じく連立方程式を解きます. 酒井さんはモデル検査を用いて解いていますが, 私は数学で解きます. 一応, 数学を学んできた身としては, 数学で解けるものは数学で解きたいものです. (酒井さんも同じようなお考えなのかもしれません) 数学を使って厳密に解いてしまえば, この解が最適解かどうか考えるのも楽になります. 手法による違いを楽しんでいただけたら, と思います.

まず最初に立式する連立方程式は同じです.

$$ \begin{aligned} x_1 + x_2 + x_3 + a_1 &\equiv b_1\ (\bmod 4) \\ x_2 + x_3 + x_4 + a_2 &\equiv b_2\ (\bmod 4) \\ x_1 + x_3 + x_4 + a_3 &\equiv b_3\ (\bmod 4) \\ x_1 + x_2 + x_4 + a_4 &\equiv b_4\ (\bmod 4) \end{aligned} $$

4 次元の縦ベクトル \(\mathbf{a}\) は 4 つの銅像の初期状態, \(\mathbf{b}\) は終了状態を表します. 各要素は内側を向いている状態を 0 として, 右回りに 90 度回るごとに 1 増えるとします.

与えられた \(\mathbf{a}\) に対し \(\mathbf{b} \equiv 0\) の条件で \(\mathbf{x}\) について解くのですが, ここでおもむろに行列を持ち出します.

$$ \begin{aligned} \begin{pmatrix} 1 & 1 & 1 & 0 \\ 0 & 1 & 1 & 1 \\ 1 & 0 & 1 & 1 \\ 1 & 1 & 0 & 1 \end{pmatrix} \begin{pmatrix} x_1 \\ x_2 \\ x_3 \\ x_4 \end{pmatrix} + \begin{pmatrix} a_1 \\ a_2 \\ a_3 \\ a_4 \end{pmatrix} \equiv \begin{pmatrix} 0 \\ 0 \\ 0 \\ 0 \end{pmatrix} \end{aligned} $$

こうして

$$ \begin{aligned} \begin{pmatrix} 1 & 1 & 1 & 0 \\ 0 & 1 & 1 & 1 \\ 1 & 0 & 1 & 1 \\ 1 & 1 & 0 & 1 \end{pmatrix} \begin{pmatrix} x_1 \\ x_2 \\ x_3 \\ x_4 \end{pmatrix} \equiv \begin{pmatrix} - a_1 \\ - a_2 \\ - a_3 \\ - a_4 \end{pmatrix} \end{aligned} $$

こうして

$$ \begin{aligned} \begin{pmatrix} x_1 \\ x_2 \\ x_3 \\ x_4 \end{pmatrix} \equiv \begin{pmatrix} 1 & 2 & 1 & 1 \\ 1 & 1 & 2 & 1 \\ 1 & 1 & 1 & 2 \\ 2 & 1 & 1 & 1 \end{pmatrix} \begin{pmatrix} a_1 \\ a_2 \\ a_3 \\ a_4 \end{pmatrix} \end{aligned ...

LaTeX in reST test

スタート代数 #3

報告

数学の勉強会をしてきました.

http://partake.in/events/1009ce0b-a3ca-448e-bd83-8819bc6b1326

テキストは↓これです.

今回はテキストの「1.3 分解体」のところを扱いました.

ガロア理論はこの分解体の感覚が付くとだいぶ後が楽になるので, 丁寧に解説や指摘を入れました.

準備のポイント

数学のゼミの準備をするときは,

  • その命題, 定理が何を言っているかを, 自分の言葉で説明できるまで考える
  • 具体例を挙げる
  • 仮定の条件を1つ外したり, 別のものに変えたりして, 結論が成り立つか調べる
  • 成り立たない場合は反例を作る (それが条件が必要である根拠となる)

というあたりに気を付けて, 準備すると良いです. これをやっておくと単なるテキストの朗読ではなく自分の言葉で説明できますし, 講師役の人に突っ込まれてもすぐ答えられるようになっているはずです.

メモ

質問や議論ができる場所を作った方が良いかも, という話が出ました. LaTeX で数式が書けることが条件となると思うので, 色々調べないといけないですね. Wiki 感覚で LaTeX が書けると嬉しいのですが.

次回

次回は 7/23, 24 の 19:00--21:00 に「1.4 代数的閉体」「1.5 分離拡大体、非分離拡大体」を取り扱います. まだ日程は仮ですが2日間の集中勉強会の形式で行う予定です.

興味があれば是非参加してみてください.

それでは.

Python で書く代数 - pytest 編

テストについて

前回は群を Python で書いてみました. 群は公理というルールを使って定義されていました. この公理を Python で表現するのに, テストが使われていました.

Python でのテストと言えば unittest や nose が有名ですが, pytest という新しいテストライブラリのことを知ったので, これを使ってみました.

この pytest の大きな特徴はテストメソッドで使用する値を簡単にパラメータ化できることです.

人間がテストケースを考える場面では, ただ闇雲に適当な値を渡すのはテストとしては良いものではありません. とりあえずで値を列挙すると無駄な意味の無いテストケースを作ってしまうことが多く, テストの実行自体に時間がかかります. そしてエラーが起きたとしても, そのエラーがいったいどんな原因によって起きたのか考えないといけません. (個人的にはあまり頭を使わず安直にエイヤというのは好きではないです.)

ランダムな値を渡す手法は fuzzing と呼ばれていて, 人間がテストケースを想定する範囲の外にあるバグを見付けるのに使われるそうです. 詳しくはこのスライド http://www.slideshare.net/TokorotenNakayama/fuzzing-pyfes を見ると良いと思います.

群の公理は「群の任意の元」という表現を含んでいるため, 具体値を使用するテストでは無限の時間が必要になってしまい, 全てをテストすることは不可能です. なので, 今回の Group クラスのサブクラスのテストとしては, パラメータ化されたテストで特殊値の付近だけをテストすることにしました. 例えば, Integer クラスでは整数を表現しているので特殊値として 0 があります. 0 の付近の値でテストが通れば, 高い確率で他の値でも動くものと期待できます.

pytest によるテスト

pytest は easy_install もしくは pip コマンドでインストールできます. ここでは virtualenvwrapper を使って, pytest という名前の個別の環境にインストールしています.

pip, virtualenv, virtualenvwrapper についてはこの記事 http://d.hatena.ne.jp/rudi/20110107/1294409385 に詳しく載っています. そちらを参照してください.

$ echo $VIRTUALENV_USE_DISTRIBUTE
True
$ mkvirtualenv pytest
(pytest)$ pip install pytest

テストケースの実行は pytest コマンドで行います.

$ pytest tests/grouptest.py

pytest にテストケースとして認識させるには, メソッドの先頭を test にすれば良いようです. ここは nose などと仕様を合わせているようです. (ドキュメントには明記されていなかった気がしますが.)

肝心のテスト関数にパラメータを渡すところはデコレータを使用して以下のように書きます.

@pytest.mark.parametrize('cls', groups)
def test_ZERO(cls):
    cls.ZERO
    return True

pytest.mark.parametrize の第1引数にはテスト関数の引数の名前を, 第2引数にはテスト関数に渡す値の list を入れます. この list の部分を generator で書いてしまうとエラーが出て, テストが実行できません. どうやら pytest が最初にテストケースをカウントしていて, 長さが測れるものでないといけないようです. 最初エラーメッセージの意味が分からず, 長いことハマっていました.

複数の引数を持つテスト関数を書く場合は以下のようにします.

integer_values = [Integer(i) for i in range(-2, 3)]

@pytest.mark.parametrize(
    ('a', 'b'),
    [(a, b) for a in integer_values for b in integer_values]
)
def test_equals_symmetric_law(a, b):
    if a == b:
        assert b == a

第1引数が tuple になり, パラメータの値も tuple になっています.

今回使用したテストコードの完全なソースコードは https://bitbucket.org/cocoatomo/pyarith/changeset/08e381828aeb#chg-tests/grouptest.py を参照してください.

過去のリビジョンの URL を張っているのは, 実は現在は別の形式にしているからです. その話はまた次の記事で書こうと思います.

まとめ

この記事では pytest を使ってテスト関数の引数をパラメータ化し, そこに入れる値をリストとして書きました. これによって同じテスト関数を色々な値で実行できるようになりました.

pytest にはまだまだ機能があるので, 興味がある方は本家のドキュメントを読んでみてください.

Python で書く代数

代数は数学の中でもプログラミング言語と近しい存在です. 歴史的な事実関係は逆でプログラミング言語が抽象代数的な発想の中から生まれてきた, と言えるでしょう.

この記事では代数学上の事柄について, プログラミング言語の Python を使って記述していきます.

代数

現代の抽象的な代数は公理による定義を行います. 「公理」というのはひらたく言うとルールのことで, そのルールから証明という手続きを経て, 命題や定理を導き出します.

公理では

  • あるべき対象
  • あるべき演算
  • 満たすべき性質

について記述します.

プログラミングで言えば

  • あるべきオブジェクトや持っているべきプロパティ
  • あるべきメソッドやオペレータ
  • オブジェクトやメソッドが持つべき性質

にあたり, これらはテストでチェックしたり, Java の interface および abstract class 相当の仕組みを利用して, 実装しなければならないメソッドを表現します.

この対応関係を着想として, まずは代数的対象のうち「群 (group)」を Python で表現してみます.

ここで載せるソースコードは全て https://bitbucket.org/cocoatomo/pyarith にあります. 順次アップデートしていきます.

群を扱った Python スクリプトは https://bitbucket.org/cocoatomo/pyarith/src/1b3a578e1678/group.py です. テストスクリプトは https://bitbucket.org/cocoatomo/pyarith/src/1b3a578e1678/tests/grouptest.py です.

クラス Group を継承したクラスが群となり, そのクラスのインスタンスが群の元に相当します.

abstract method として実装してある __eq__, __add__, __neg__ メソッドが, 群であるために必須のメソッドとなります. a = b は実は a.__eq__(b) のことであり, a + b, -a もそれぞれ a.__add__(b), a.__neg__() に相当します. またテストの方でその存在をチェックしている ZERO というフィールドも, それが存在することが群に課せられた条件です. つまり, 群には「等号比較」「加法」「零元」「逆元」が必須の条件なのです. (等号の性質に関しては通常は群の公理に含めません. ここでは等号も実装しているので, 等号の性質も一緒にテストしています.)

これらは好き勝手に実装して良いのではなく, 満たすべき制約条件があります. このテストスクリプトでは, それをテスト関数の形で表現しています. (演算によって群が閉じていることのテストが抜けていますね…… 追加しておきます.)

テストケースとその意味
test_equals_reflexive_law 等号の反射律
test_equals_symmetric_law 等号の対称律
test_equals_transitive_law 等号の推移律
test_add_ZERO 零元の性質
test_add_negative 逆元の性質
test_add_commutative_law 加法の可換性
test_add_associative_law 加法の結合律

それぞれの制約がどういうものかはスクリプトを見ればすぐに分かると思います. 群の公理 (ルール) はこれで全てです. http://ja.wikipedia.org/wiki/%E7%BE%A4_(%E6%95%B0%E5%AD%A6) と見比べて確認してみてください.

(可換性は全ての群が備えているものとは限りません. 可換性を持つ群を「可換群」, 可換性を持たない群を「非可換群」と呼びます.)

まとめ

この記事では, 群の公理を abstract method とテスト関数を使って記述しました. Python スクリプトとして記述することで少しだけ理解しやすくなれば嬉しく思います.

これだけの少ないルールから群の様々な性質が証明されていくのは不思議ですね.

次回は環や体を対象としたり, テストを行うのに使用した pytest モジュールについて書こうと思います.

それでは.

スタート代数 第2回

今日はスタート代数の第2回でした.

スタート代数 #2

さて今回もガチにゼミをやってたわけで, 丁寧にゼミをやった結果, 今日の発表者は @mr_konn さん1人になってしまいました.

随所で参加者の方々から質問などが出てきて, 活発な議論ができて良かったと (主催者として) 感じています.

内容

今日の内容としては §1.1 を終え, やっと用語の定義などが終わりました. これでやっと本論に入っていけます. この先, 部分体全体とガロア群の部分群の対応を扱っていき, その美しさに心打たれる (予定) です.

定義ばっかりで面白くない部分だったのですが, 現代数学は定義のちょっとしたところに仕掛けがあったりするので気が抜けません. 「仕掛け」とは後々出てくる定理で必要な条件だったり, 他の概念と組み合わせるときに必要な条件だったりします. なので, 定義ばっかりでつまらないところは飛ばして, 命題や定理からまた定義に戻る, という本の読み方も良いです.

(と数学本の読み方の紹介など.)

ゼミの発表

発表者にツッコム係は主に主催者がやっているのですが, 私がゼミ発表するときに気を付けていることを書いていってみます.

状況としては, 教授の前で自分の勉強したことを話したり, 同じくらいのレベルの友達どうしで集まって発表し合うなど色んな場面が考えられますが, どの場面でも共通して大切に思っていることを書いていきます.

楽しくさせる

時間を割いて発表を聞いてもらうので, このゼミの時間の中で何かを得てもらいたい, と思っています. 「この時間を過ごして良かったな」と思ってもらうために「楽しくさせる」ということに気を遣っています.

「楽しく」というのは, 新しい知識を得たり, 上手な例を聞いて関心するなどの学問的な楽しさのことを言います.

そして, その時間を有意義にするには, 単にテキストを読めば分かることを喋るだけではだめなのです. それでは自習となんら変わりません. 自分の言葉での説明, 自分なりの解釈, そして自分で考えた話の構成で喋る必要があります. 決してテキストに喋らされてはいけません. そうやってテキストの内容を自分の色に変えて発表することで, 聞き手は2つの視点で内容を眺めることができ理解が深まります. 何より発表準備をした本人が理解が最も深まっているはずです.

「楽しくさせる」をゼミ準備の指標にすることで,「発表者の理解が深まる」「聞き手が新たな視点での物の見方が得られ刺激になる」というメリットを引き出すことができるのです.

キモを押さえる

これは, 結論を固定してから発表の構成を考えなさい, ということです. これ自体は色んなところで言われているので, 数学の場合について話したいと思います. もしかしたら, 別の分野での理論的なお話にも通じるのかも知れませんが, ほとんど知らないのでそこは想定に入れません.

数学ではたいていのテキストが, 定義 (Definition), 補題 (Lemma), 命題 (Proposition), 定理 (Theorem) とその証明 (Proof), 系 (Corollary) というパーツの集まりで, 依存関係を持ちつつ配置されています. この中でも「定理」が最も華々しい数学理論の成果なわけですが, その定理が成立するための最も重要なパーツがどこかにあるはずです. それがこの定理, ひいては理論のキモになります. 定義や定理の羅列の中に理論の流れを読んで, このキモを見付けるのが重要なのです.

どんな数学理論でも, その発端となる発想があるはずで, そこさえ押さえてしまえば後は芋づる式に示すべき命題や補題が出てくるものです. 例えば, 今回扱っているガロア理論では「多項式の根の取り替えを考えると, 体についての情報が分かる」という感覚がキモになっています. この感覚を正確に述べようとすると, 色んな用語の定義が必要になって, 定理を示すまでのステップを刻むために補題や命題が必要になってきます. これをまとめれば1つの数学理論になるはずです.

ゼミ発表においては発表する部分だけで構わないので, 話のキモを考え, それが良く伝わるような例えを出したり, 比喩の話をしたりすると良い発表になると思います.

まとめ

今回はガロア理論で必要な前提知識や用語の定義とその意味を押さえました. 次回からは体の拡大の種類を具体的に見ていきます.

またこの記事の後半では, 数学のゼミ発表について大事にしていることを書きました. もちろん私が常にできているかと言えば No なのですが, 常にこれを目指していることは確かです.

それでは.

スタート幾何 第 2 回

スタート幾何 #2 というものに参加してきました.

http://partake.in/events/eb51cfab-184e-4c79-a08d-2c148451ffa8

今回は会場係もやっていたのですが, 諸々の私の手落ちにより開始時刻が非常に遅れてしまいました. ご迷惑をお掛けしました.

内容

教科書は松本幸夫先生の「多様体の基礎」を使っていました. すごく丁寧に書いてあってギャップや読者への宿題がほとんど無い本なのですが, それが良かったみたいでした.

今日は第 2 章から始めて, 例 2 のところまで行きました. 細かく突っ込んでいってしまったので, 速度としてはこんなものになってしまいました. 私としては, 定義の気持ちや証明のポイントなどを突っ込んで, どこがキモなのか伝えられたので満足しています.

懇親会

みんなの分のお菓子を買っていただいた方がいらっしゃって, 勉強会後にその場でプチ懇親会みたいになりました.

参加者に教師の方もいらっしゃったようで, 大学入試で使う数学と高校までで教える数学のギャップの話を主にしていました. 自分もすごく興味があり, また問題を抱えているな, と思っているところなので, 現場の方と話せて非常に有意義な時間になりました.

参加者

基本的にみな数学好きな感じでしたが, 年齢の幅が広かったり IT 関係以外の人も来ていたりして驚きました. ご高齢な方は数学を学ぼうという意欲はかなり強い方で, 非常に自分への刺激になりました.

数学への理解を広めたいなぁ, と思っている身としては, 自信を付けていただいた感じです.

逆にそういう方が勉強会を知るのに, 実質 Twitter が必須になってる PARTAKE を使うのは障壁にもなるんだなぁ, と実感しました. (だったら, オープンソースなんだからお前がなんとかせい, という話ですが :P)

まとめ

数学をやる立場としても, 数学を教える立場としても非常に充実した会でした. 次回も是非参加したいと思います. (もちろん家族との時間も大事にね. YAuth ポイント収集頑張れ!! > 俺.)

スタート代数 第1回

今日はスタート代数という勉強会を開催してきました. http://partake.in/events/989bf10a-d5f0-4fcc-ba1f-f152fe2f7072

「スタート」と頭に付いていますが, 懇切丁寧に教えるのではなく懇切丁寧にツッコミを入れる大学のゼミ形式でやってきました. 初めてこの形式に触れた人は驚いたかもしれませんが, ゼミ形式では発表者が理解を深めるのが目的となっています. ソースコードレビューを思い浮かべてもらえると感覚は理解できると思います.

なぜ体論からか?

通常, 代数を学ぶ際には「群」→「環」→「体」と進むのが普通です. でもそこで敢えて体論から始めるのには訳があります.

まず, 体が代数的対象の中で一番身近なこと. もちろん自然数や整数も使っていますが, 割り算が許されない数を扱う場面は少ないと思います.

第2に具体例が分かりやすいこと. 群の例として剰余群が出てきたり, 環の例として多項式環が出てきたりしますが,「これ使ってすごいことができるぜ」感が足りないのです. それに比べてガロア理論での「方程式の根の様子が分かっちまうぜ」の方が印象が強いと考えました.

もちろん群や環のことも少しは知らないと体の話ができないので, その部分については全力でバックアップしていってます.

結果報告

今回は3ページまで進み, 多項式とその根について語り始めるあたりで時間切れとなりました. 遅いように感じると思いますが, 確実な理解を得るためにはこれくらいのスピードになってしまうものです.

「抽象代数を理解するとは?」や「数学のゼミってどんなふうにやるの?」という, あまり知られていない (と思われる) ところが, 体験できたのではないでしょうか?

こちらに参加者の方の板書ノートが公開されています. http://lockerz.com/s/135335969

宿題

今日は宿題がいくつか出ていました.

  • 1のある可換環 R に対し, ∀a ∈ R, a0 = 0
  • 四元数体の逆元を計算せよ
  • ある可換とは限らない群において, ある元の逆元が1つしか存在しないことを示せ

どれもそう難しくないので挑戦してみてください. 1つ目の問題などは「R が可換で無かったらどうなるか?」「R に1が無かったらどうなるか?」「0の公理を削ってみたらどうなるか?」と色々といじってみると, 公理の必要性が分かると思います. (自分はこんなふうにして数学の抽象概念を理解していました.)

まとめ

内容はけっこうガチでやってしまったので, 次回何人参加するのか不安ではあります. また, 元々数学ができる人しか参加しないんじゃないか? という指摘もあると思います. しかし,「数学の抽象的な思考を知った上でプログラミングをする方が幸せになれる」と確信しているので, 今後も様々な方法で数学について知ってもらえるよう活動をしていきます.

  • Java 使いのための数学入門
  • Coq を使って知る数学

などなどできたら良いな, と思っています. だいぶ先の話ですが :P

素因数分解の暗算高速化

誰の役に立つのか, 何の役に立つのか良く分からないが, 中学生くらいのときから数字を見るたびに素因数分解に挑んできた俺が使っている, 暗算で素因数分解をする方法を紹介します.

方針

簡単に計算できるように, 1桁の掛け算と2桁の足し算くらいしか使わないことにします.

11で割る

まず, 一番簡単な11から.

11 = 10 + 1 を利用して, 11の倍数をどんどん引いていきます. 残りが0になったら11の倍数, そうでなかったら11の倍数でない, と分かります.

具体例

135 から始めます.

  1. 135 を 13 と 5 に分解.
  2. 13 - 5 を計算して 8.
  3. 11 で割れないので終了.

簡単ですね.

7で割る

7 * 3 = 21 を利用します.

具体例

1113 から始めます.

  1. 1113 を 111 と 3 に分解.
  2. 111 - 3 * 2 = 105.
  3. 105 を 10 と 5 に分解.
  4. 10 - 5 * 2 = 0. よって7で割り切れる.

色んな数で割る

せっかくなので, 41 くらいまでは揃えてみましょう. そうしておけば, 42^2 = 1764 までの数に出会ったときに素因数分解で困ることは無いです(誰得

3で割る

各桁の数字を足す. 有名なのですぐ分かる.

5で割る

下1桁見れ.

7で割る

既出

11で割る

既出

13で割る

13 * 3 = 39 を利用して,

  1. 下1桁と上の残りに分解
  2. 上の残りに下1桁の4倍を足す

で, 13で割った余りを変えずに数を小さくできる.

17で割る

17 * 3 = 51 を利用して, 下1桁の5倍を上の残りから引けば良い.

19で割る

下1桁の2倍を上の残りに足せば良い.

23で割る

23 * 3 = 69 なので, 下1桁の7倍を上の残りに足す.

29で割る

3倍を足す.

31で割る

3倍を引く.

37で割る

37 * 3 = 111 なので, 11倍を引く. 37の倍数で2桁のものは, 37 と 74 しかないので覚える.

41で割る

4倍を引く.

まとめ

非常に誰得なエントリですが, こういうネタが好きな人が居れば嬉しいです. というか変態です.

43 は素直にやると13倍を足さなきゃいけないので面倒です. 誰かもっと良い方法教えて.

それでは.

Licenses