【群論】有限体の乗法群が巡回群になることの証明

問題

有限体Kの乗法群K*が巡回群になることを示せ。

証明の流れ

補題「位数nの群Gがある。nの約数dに対して、xd=1となる元がd個以下なら、Gは巡回群」を示す。

補題は、「群の元を元の位数で分類するとき、位数dのグループには、φ(d)個の元が存在する。」ことから示せる。

体の性質と補題より示せる。

補題の証明

補題「位数nの群Gがある。nの約数dに対して、xd=1となる元がd個以下なら、Gは巡回群」を示す。

位数dとなるGの元xが存在するなら、xで生成される巡回群<x>の位数はdであり、<x>のd個の元はxd=1を満たす。仮定より、xd=1となる元はd個以下なので、任意の位数dの元は<x>を生成する。<x>の生成元は、「1≦x≦dの中で、dと互いに素である自然数xの数」個ある。これをφ(d)と置く。

φ(d)は、1≦x≦nの中で、nとの最大公約数がn/dである自然数の数と等しい。1からnまでの整数は、最大公約数によって分類されるので、nの約数dに対するφ(d)の和はnとなる。

以上より、nの元を元の位数で分類すると、位数dのグループの元は、存在すればφ(d)個となる。もし、位数dの元が存在しなければ、nの約数dに対するφ(d)の和がnとなることに反する。d=nの場合を考えると、Gが巡回群であることが分かる。

証明

Kを有限体とし、K*をKの乗法群とする。

Kは体なので、方程式Xd=1のK上の解の数はd以下であり、それらは全てK*の元である。よって、補題より、K*は巡回群となる。

捕捉

φ(d)は、オイラー関数と呼ばれる有名な関数です。

証明の流れ(誤り)

NをK*の元が取る最大の位数としたとき、K*の任意の元のN乗が1であることを示す。

N<#K*なら矛盾するので、N=#K*が示される。

証明(誤り)

Kを有限体とし、K*をKの乗法群とする。

K*の元の内、最大の位数を取る元をx、その位数をNとおく。y∈K*に対して、xyの位数がmであるとする。mがNの約数なら、(xy)N=1であり、yN=1。mがNの約数でないなら、x-mの位数はNになるので、yの位数はNになる。yで生成される巡回群は、yで生成される巡回群の部分群なので、yの位数はNとなる。つまり、yN=1。

Kは体なので、方程式XN=1のK上の解の数はN以下であるが、K*の任意の元がXN=1の解となるので、#K*≦Nとなる。#K*≧Nは自明なので、N=#K*

以上より、K*はxで生成される巡回群となる。

補足(誤り)

なぜN=#K*を示すのか?:N=#Kなら、xの巡回群の位数が#K*となり、(xの巡回群)=#Kとなるから。

mがNの約数でないなら、x-mの位数はNになる:x-mの位数がk(≠N)なら、x-mk=1となるが、-mkがNの倍数でないのでおかしい。

yで生成される巡回群は、yで生成される巡回群の部分群なので、yの位数はNとなる:ラグランジュの定理(「部分群の位数は、それを含む群の位数の約数になる」)より、yの位数はNの倍数となるが、K*の元が取る最大の位数はNなので、yの位数はNとなる。

#K*≧Nは自明:位数が、その集合の要素数を超えることはない。もし、N>#K*となるなら、xの巡回群の要素数は#K*を上回るので、おかしい。

【証明付き】素数に関する定理まとめ

導入

素数に関するまとめサイトが無かったので作りました。

証明されているものに限り記載しています。

目次

  • 弱いゴールドバッハ予想
  • ベルトラン・チェビシェフの定理
  • 素数定理
  • オイラー積
  • 素数の間隔に関する事実
  • 立方数に関する事実
  • ウィルソンの定理
  • グリーン・タオの定理
  • 算術級数定理

弱いゴールドバッハ予想

7 より大きい奇数は 3 個の素数の和で表せる。3 個の素数は同じ数であってもよい。

ハラルド・ヘルフゴットによる証明

ベルトラン・チェビシェフの定理

任意の自然数 n に対して、n < p ≤ 2n を満たす素数 p が存在する。

エルデシュによる初等的な証明

素数定理

π(x) ~ Li x

素数定理 – Wikipedia

ポール・エルデシュによる証明

ニューマンによる短い証明

ゴールドフェルドによる初等的な証明

アヴィガドと他3人による証明

素数定理の証明と歴史

オイラー積

ディリクレ級数を素数に関する総乗の形で表した無限積。

オイラー積 – Wikipedia

素数の間隔に関する事実

間隔が246以下の2つの素数の組は無限に存在する。

D.H.J. Polymath による証明

立方数に関する事実

n が十分大きければ n3 と (n + 1)3 の間には必ず素数が存在する。

アルバート・イングハムによる証明

ウィルソンの定理

p が素数ならば (p − 1)! ≡ −1 (mod p) が成り立つ。
逆に、整数 p > 1 に対し、(p − 1)! ≡ −1 (mod p) ならば、p は素数である。

ウィルソンの定理 – Wikipedia (証明付き)

グリーン・タオの定理

素数の列は、任意の長さの等差数列を含んでいる。

テレンス・タオと他2人による証明

算術級数定理

初項と公差が互いに素である等差数列には無限に素数が存在する。

算術級数定理 – Wikipedia (証明付き)

【GameMaker Studio 2】サブスクしたのに反映されない?原因と解決策を解説

導入

GameMaker Studio 2では、WindowsやMas OS、Androidなど外部向けにコンパイルする際、自身のアカウントでサブスクリプションする必要があります。

大抵の場合、サブスクリプションが完了したあと、GameMaker Studioを再度開くと、直ぐに外部向けのコンパイルができるようになります。…しかし、自分の場合、同じ手順を行ってもサブスクが反映されませんでした。

最近(2021/8)になって、GameMaker Studio 2の購入システムが大きく変化したこともあり、昔のエラー情報を頼ることはできませんでした。また、GameMaker Communityに相談しても原因を突き止めることはできませんでした。

解決は困難を極めましたが、カスタマーサポートが遂に原因を突き止めてくれました。

原因を探すのが難しいにも関わらず、原因は多くの人にも当てはまる罠だった(コミュニティフォーラムに同じ問題を抱えていた人がいた)ので、これは絶対に共有すべきだと思い、この記事を書きました。

サブスクが反映されたか確かめる方法

自分が制作したゲームプロジェクトを開き、右上を見ます。「Test | Local | VM | Default | Default」などと書いてあると思いますが、一番左にある「Test」が「どのプラットフォームに向けてコンパイルするか」を表しています。

プラットフォームに「Test」があればサブスクは反映されておらず、逆に「Windows」や「Mac OS」、「Android」などがあればサブスクは反映されています。

解決策①

「File > Log out」を選択してログアウトし、そのあと再びログインする。

GameMakerを開いたままサブスクをした場合、サブスクの更新が行われていない恐れがある為です。

このサイトに同じことが書いてあります。

https://help.yoyogames.com/hc/en-us/articles/115001219911-How-To-Update-Your-License-To-See-Your-New-Purchase

解決策②

YoyoAccountの2段階認証を解除する。

これは私が陥っていた罠です。2段階認証を設定していると、サブスクが反映されなくなります。2段階認証を再設定すると、また使えなくなるので、2段階認証はバグが解消されるまでオフにしていた方がよさそうです。

解決策③

セキュリティがサブスクの更新を阻害している可能性があります。

https://help.yoyogames.com/hc/en-us/articles/360022953052-User-Permissions-and-Internet-Access-Required-by-GMS2

このサイトからいくつか分かりやすい例を挙げると、

  • ファイアーウォールが悪さをしている
  • ポート80と443が開いていない
  • クラウドのファイル同期によってファイルがロックされている
  • インターネットに繋がっていない
  • ファイルウォッチャーの不具合

解決策④

「他人を頼る」。筆者もこれによって解決することができました。

ゲームメーカーコミュニティーフォーラムを利用する。

アカウントを作成し、質問を投稿すると、皆が集まって解決策を提案してくれます。

https://forum.yoyogames.com/index.php

カスタマーサポートを利用する。

YoyoAccountにログインしてから以下のリンクを開いてください。開いたら、問題のカテゴリーを入力し、その問題が「すでに報告された問題」に含まれていないなら、「I STILL NEED TO REPORT A BUG」をクリック。その後、必要事項を記入。すると、アカウントのメールアドレスに「整理券が割り振られたので、問題の内容をメールに書いて送って下さい」という内容のメールが届きます。書いたメールを送ると、数時間後にカスタマーサポートが返信してくれます。私は最大で9時間待たされたので、中々返信が来なくてもめげないようにしましょう。

https://accounts.yoyogames.com/contact-us

【GameMaker Studio 2】直線と最初に衝突する物体を取得する

導入

collision_lineは(x1, y1)と(x2, y2)を結ぶ直線と衝突する物体のIDを返してくれますが、(x1, y1)に最も近い物体のIDを返すわけではありません。

「視点」の概念を導入するとき、(x1, y1)に最も近い物体のIDを返してくれたら便利です。悩んでいる人の為にも、その関数を作ることにしました。

※海外の人が既に同じ関数を作っていましたが、バージョンが異なっているし、コードが長めだったので、新規に作ることにしました。

コード

以下のコードを、「スクリプト」に突っ込んでおけば動きます。

(x1, y1)と(x2, y2)を結ぶ直線上にある全てのobjの内、(x1, y1)に最も近いobjのインスタンスIDを返します。

function collision_line_first(x1, y1, x2, y2, obj)
{
	var list_ = ds_list_create();
	
	collision_line_list(x1, y1, x2, y2, obj, false, true, list_, true);
	if (ds_list_size(list_) >= 1)
	{
		list_0 = list_[| 0];
		ds_list_destroy(list_)
		return list_0;
		
	}
	ds_list_destroy(list_);
	return noone;
}

※データリストがインスタンスであることに注意

使わなくなったds_listは自動的に捨てられるわけではないので、ds_list_createをしたあと、ds_list_destroyで必ずインスタンスを捨てる必要があります。

自分はその失敗をしてメモリを一瞬で喰われました…。

【GameMaker Studio 2】親オブジェクトの変数や関数を子オブジェクトで継承する方法

導入

オブジェクトの親オブジェクトを設定したとき、子オブジェクトの「Create」や「Step」は親オブジェクトと同じものに設定されます。

子オブジェクトの「Create」や「Step」を新たに作成すると、親オブジェクトの「Create」や「Step」は消えてしまい、変数や関数を継承できません。

じゃあどうすれば良いか?…その答えが見つかったので、それを共有したいと思います。

前提として

オブジェクトの「Parent」という欄でオブジェクトの親オブジェクトを設定することができます。

方法①(関数と変数を継承)

例えば「Create」に書かれている関数を継承したい場合、子オブジェクトに新しく「Create」を作り、その一行目に以下のコードを挿入する。

// 子オブジェクトの「Create」
event_perform_object(object_get_parent(object_index), ev_create, 0);

このコードは、親オブジェクトの「Create」を呼ぶコードです。このコードの下に処理を書いていけば、任意の変数や関数を変更することができます。

また、親オブジェクトの「Step」を呼びたいときは、ev_createをev_stepに変更すると良いです。

方法②(変数のみを継承)

親オブジェクトを開き、「VariableDefinition」を開きます。そして、「Name」 に変数の名前、「Type」に変数の型、「Default」に初期値を入れます。

次に、子オブジェクトの「VariableDefinition」を開き、変数の右にある「鉛筆マーク」をクリックすると、変数はオーバーライドされます。このとき、変数を初期値を独自に変更できるようになります。

また、オーバーライドを解除したいときは同じ場所を再度クリックすると良いです。

【Quaver】初心者の為の基本操作まとめ

導入

Quaverという音ゲーの基本操作を解説します。

目次

曲のダウンロード

一番左上にあるメニューの「MAPS」というところをクリックすると、公開されている曲の一覧を見ることができます。

引きたい曲を2回クリックすると、曲のダウンロードが始まります。その後、「HOME」→「SINGLE PLAYER」を選択するとその曲を弾くことができます。

演奏設定

画面下のメニューにある「MODIFIERS」をクリックすると、曲の演奏設定を開くことができます。

SPEEDは0.05倍刻みに0.5倍から2倍まで曲の速度を変更することができます。(太鼓の達人などの倍速と違い、譜面の速度だけでなく、曲の速度も変更されます)

JUDGEMENT WINDOWSノーツの判定の範囲を変更できます。(ただし、判定を「Standard」以外にすると、ランクスコアの提出ができなくなります)

AUTO PLAYをONにすると、自動演奏してくれます。

NO FAILをONにすると、曲の途中でHealthが0になっても、曲が中断されなくなります。(Quaverではノーツを叩き損ねるとHealthが減少し、0になると曲が中断されるというシステムになっています)

INVERSEは空白をノーツにして、ノーツを空白にします。

RANDAMIZEはノーツの位置がランダムで横に移動します。

曲のオフセット調整

曲を演奏し終えたあと、左下のメニューのFIX OFFSETをクリックして曲のオフセットを調節することができます。直前に自分がプレイした演奏に基づいて、オフセットを自動で調節してくれます。

「+5ms」は「ノーツの流れてくるタイミングを5ミリ秒遅らす」、「-5ms」は「ノーツの流れてくるタイミング5ミリ秒早める」という意味です。

キー設定

OPTIONS」→「INPUT」からどのキーでノーツを叩くかを設定することができます。

【Unity】Cinemachineのカメラの向きをスクリプトで取得する方法

導入

CinemachineVirtualCameraの垂直方向の向き(VericalAxis.Value)を

this.gameObject.GetComponent<CinemachineVirtualCamera>().Aim.VerticalAxis.Value

で取得しようとしたところ、「CinemachineVirtualCameraにはAimという名前のプロパティはありません」というエラーが発生。

じゃあどうすれば取得できるのか、Unity公式リファレンスを当たったところ、なんとか正答に到達。その正答にたどり着く作業は意外と大変だったので、ここで共有しておこうと思います。

コード

これがCinemchineVirtualCameraの垂直方向の角度の値を取得するのに必要なコードです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;

public class LESSON : MonoBehaviour
{
    CinemachineVirtualCamera camera;

    // Start is called before the first frame update
    void Start()
    {
        camera = this.gameObject.GetComponent<CinemachineVirtualCamera>();
        
    }

    public float GetVerticalAngle()
    {
        return camera.GetCinemachineComponent(CinemachineCore.Stage.Aim).GetComponent<CinemachinePOV>().m_VerticalAxis.Value;
    }
 
}

補足

GetCinemachineComponent とは

定義は

public CinemachineComponentBase GetCinemachineComponent(CinemachineCore.Stage stage)

「CinemachineCore.Stage」に応じた「CinemachineComponentBase」を返します。

CinemachineCore.Stage とは

CinemachineVirtualCameraコンポーネントにある、「Aim」「Body」「Noise」などを含む列挙型メンバーです。

CinemachinePOV とは

CinemachineComponentBaseの継承クラスの一つ。Aimの項目を「POV」に設定したときに継承されます。

水平方向の場合

m_VerticalAxisのところをm_HorizontalAxisに変えればOKです。

参考文献

Unity公式ドキュメント – ChinemachineCore.Stage

Unity公式ドキュメント – CinemachinePOV

Unity公式ドキュメント – CinemachineVirtualCamera

Unity公式ドキュメント – CinemachineComponentBase

【思考力を鍛える論理講座】第一回「隠れた論理」

本講義の目的

本講義の目的は、一般社会の議論で扱われる論理の質を高めることです。一般社会に少しでもより洗練された論理が広まってほしいという想いからも来ています。

「隠れた論理」とは

AC間に因果関係はなく、AB間、BC間に因果関係があるとする。このとき、「AならばC」という事実に対するAB間やBC間の因果関係を「隠れた論理」と呼ぶ。

これだけでは分かりにくいので、例を用いて説明します。以下の例では、「隠れた論理が存在するなら」という前提の下、考え得る隠れた論理の内の一つを紹介しています。

「早起きな人の6割は、健康である」

これは、「早起き」自体が直接「健康」を導くのではない。隠れた論理が存在するなら、「早起きな人は、生活習慣が良い場合が多く」、「生活習慣が良いから、健康である」。「早起き」自体に健康作用がある訳ではなく、「早起き」によって、「早寝」が促進され、「生活習慣」が改善されるというような場合になる確率が高いから、この事実が成立している。

「なぜナビ大学に入った人の8割は、染色体がXXである」

これは非常に分かりやすい例である。「なぜナビ大学に入ることで、高い確率で染色体がXXになる」わけではない。そりゃ当たり前である。なぜナビ大学は入学するだけで性転換させられる大学ではない。隠れた論理を補うと、「なぜナビ大学に入学した人の8割は女性であり」、「女性は染色体がXXである」となるので、この事実が成立する。

「このサプリを飲んだ人は、平均して、平均寿命よりも5歳寿命が長い」

これは怪しい広告文言でも使われそうな巧妙な文である。隠れた論理が存在するなら、「このサプリを飲んだ人は、健康志向の人が多い為、生活習慣が平均よりも良い傾向にあり」、「生活習慣が平均よりも良い人は、平均寿命よりも寿命が長い可能性が高い」から、この事実が成立している。

「なぜナビ湾周辺の土地の購入者の多くは、2年以内に収入が1000万円増えている」

これも少し怪しげな匂いのする文である。隠れた論理が存在するなら、「この土地は高額で、この土地を買う余裕があるのは大富豪の中の上位層のみであり」、「この高額な土地を買えるだけの金銭を有する富豪は、相当なやり手で、平均して毎年800万の収入が増え続けている」ので、この事実が成立するのである。その為、「高確率で2年以内に収入を1000万円増やす」為の投資として、貧乏人がお金をかき集めてその土地を購入したとしても、収入には何の変化もない。

注意

先の例で、「隠れた論理が存在するなら」とわざわざ書いているのは、隠れた論理が存在しない場合もあるから。

例えば、サプリに本当に寿命を伸ばす成分が入っているとしたら、「サプリを飲むこと」と「平均寿命よりも寿命が長いこと」に因果関係が存在するので、「このサプリを飲んだ人は、平均して、平均寿命よりも5歳寿命が長い」には隠れた論理は存在しない。

また、隠れた論理は複数存在する場合もある。例において「隠れた論理が存在するなら~」のあとに示した「隠れた論理」以外にも考えられる論理はいくつもある。

日常への応用

普段の生活では、主に「Pは大抵Qになる」という表現に注意すれば良い。「Pは大抵Qになる」という表現から、「Qにならない為にPをしない」「Qになる為にPをする」というように派生するのは、必ずしも正しいとはいえないこと」に注意すれば良い。

【Unity】Unityで作ったゲームをandroid端末で実行する手順を紹介

導入

Unityで作ったゲームをandroid端末向けにビルドしようとしたとき、「CommandInvokationFailure: Gradle build failed.」や「UnityEditor.BuildPlayerWindow+BuildMethodException」などのエラーが発生し、ビルドが途中で中断してしまった。その原因を調べては試し、また調べては.試したが、正解は中々見つからなかった。そんなとき、「unityでエクスポートして、それをandroid studioでビルドすれば出来ました。」という文章を発見。自分もその方法を試したところ、見事に成功。

…というわけで、今回は、私もお世話になった、Unityで作ったゲームをandroid端末向けにビルドする方法を紹介します。

目次

今回使うもの

  • android studio
  • android 端末

流れ

①JDK、SDK、NDKをインストール → ②プロジェクトのエクスポート → ③Android studioで開く → ④android端末にビルド

①JDK、SDK、NDKをインストール

Unity2019以降のversionを使う場合

Unity Hub」(Unityのプロジェクト起動時に使うやつ)を開き、「インストール」タブを選択します。すると、Unityのマークと共に今までインストールしたUnityのversionが表示されます(2019.4.19f1 など)。

自分が使いたいUnityのversionを選び、「・・・」が縦に並んでいるボタンを押し、「モジュールを加える」を選択します。すると、モジュールがずらーっと出てくるので、「Android Build Support」と、その下の階層にある「Android SDK & NDK Tools」と「OpenJDK」にチェックを入れ、「次へ」を選択します。

そして、ライセンスの同意にチェックを入れ、「実行」します。すると、ダウンロードが始まるので、終了するまで待てばOKです。

Unity2018以前のversionを使う場合

JDK、SDK、NDKをそれぞれ特定の場所でインストールする必要があります。

>> JDK、SDK、NDKのインストール方法(公式ドキュメント)

②プロジェクトのエクスポート

UnityのProjectを開き、「File」→「Build Settings」を選択し、Build Settingsを開きます。Platformが「Android」になっていなければ、「Android」を選択した後、左下の「Switch Platform」を押します。すると、少し長いロードの後、PlatformがAndroidに切り替わります。

このとき、Platformの右に、「TextureCompression」や「ETC2fallback」など、沢山の項目が出てこない場合は、Unityを一回閉じて、開き直して下さい(①でインストールしたやつが反映されていないので)。

①が反映されていれば、「ExportProject」という項目にチェックを入れ、左下の「Export」を押して下さい。すると、エクスポート先のファイルを選択する画面が出てくるので、パスに日本語が使われていない階層のファイル内にエクスポートして下さい(もしエクスポート先のファイルパスに日本語が含まれている場合は、③でgradleの同期に失敗します。)。

これで、プロジェクトのエクスポートは完了です。

③Android Studioで開く

Android Studioを開き、「ファイル」→「開く」を選択します。そして、先ほどエクスポートしたプロジェクトの、一番上の階層のフォルダを開きます(このとき、先ほどのプロジェクトのエクスポートに成功していれば、プロジェクトのアイコンが「ドロイド君」の絵になっているので探しやすいです)。

プロジェクトを開いたとき、Android Studioで使用しているSDKとプロジェクトで使用しているSDKのパスが異なる場合、「どちらのSDKを使うか」問われることがありますが、プロジェクトの方を選択して下さい。

④android端末にビルド

USBケーブルでandroid端末とパソコンを繋ぎます。

端末側の準備

端末の開発者モードがONになっていない場合は、「設定」→「システム」→「端末情報」を開き、「ビルド番号」を7回タップして、開発者モードをONにします(端末によっては最初から開発者モードがONになっている場合があります)。開発者モードがONであれば、「設定」→「システム」→「開発者向けオプション」を開き、「USBデバッグ」をONにして下さい

ここで、端末とパソコンをUSBケーブルで繋ぎます。

ケーブルで繋ぐとすぐに、端末側に反応が現れます。パソコンからのアクセスを許可していない場合には、端末の方で「許可しますか」と問われることがあるので、許可して下さい。接続の用途を問われた場合は、「充電のみ」ではなく「ファイルを転送」を選択して下さい。

パソコン側の準備

Android Studioの上のツールバーにある「実行」(緑色の三角)を押すと、プロジェクトのビルドが始まります。ビルドが完了したら、端末側でプロジェクトのアプリケーションが作成されます。

これで、目的達成です!おめでとう!