慶ドミのぼっちでもドミニオン

基本ドミニオンのことについて書きたいな〜って。

My素数表を作ろう!Let's make prime table! 〜素数大富豪 Advent Calendar 2018 1日目〜

はいどうも〜。世界初 素数大富豪研究家のゆぅくりっどです。よろしくお願いします。

あんまりこういうトップバッターを務めるタイプではないのですが、これから始まる25日のなが〜い楽しみを皆で分かち合うために、あえて最初のほうに入れさせていただきました。今回プレゼンする『My素数表』と照らし合わせて今後のアドベントカレンダーを見ることで、より盛り上げられればと考えています。最後には少し早いクリスマスプレゼントもあるよ!

では早速作っていきましょう!とその前に用意していただきたいものが3つあります。

1、Excel

2、素数一覧(〜1000万) ※以下便宜上「一覧」と表記

http://www.ysr.net.it-chiba.ac.jp/yashiro/sosu/

3(詳しい素数をまとめたい方用に)nishimuraさん(@icqk3)の素数大富豪ソフト(探索用) 

http://searial.web.fc2.com/tools/somake.html

え?2だけで完結してるじゃないかって?せやな、2~1000万までの素数を全部覚えられればな!ということで自分のような一般人にも分かりやす〜く数を減らしてまとめようという魂胆なのです。では今度こそ作っていきましょう!

 

※以下の記事内容にはExcelの操作を事細かに書いていますので「んなこったあ知ってるよ!」という方は軽く流し読みする感じでご覧ください。ぶっちゃけプログラムが書ける人はそっちのほうが早いです。あくまでも「ふぇぇ、プログラムむずかしいよぅ>_<」という人を対象としています。

 

Step1:素数を持ってこよう

最もスタンダードな5枚出し5桁を例にExcelでまとめていきたいと思います。

まずは基となる5桁の素数を一覧からコピペしてきましょう。10007〜99991までの素数をコピーしてA1のセルに貼付けます。このあたりはまだ素数の個数が多いので1万ごとに区切ってB1,C1……に貼付けることをお勧めします。

f:id:akatanana-818ubugqm:20181030101515p:plain

 

ではこれらの素数を1つ1つセルに入れていきます。まずA列全体を選択し、[データ]から[区切り位置]を選択します。

f:id:akatanana-818ubugqm:20181030102953p:plain

 

すると区切り記号や区切り位置について聞かれるので、

 [区切り記号付き]にチェックを入れて[次へ]

→区切り文字の[スペース]にチェックを入れて[完了]を押して下さい。

f:id:akatanana-818ubugqm:20181030105205p:plain

 

すると1つ1つのセルに素数が入った表が出来上がります。

f:id:akatanana-818ubugqm:20181030105206p:plain

 

出来上がったデータを活用しやすくするために縦一列に素数を並べ替えてあげましょう。1行目のデータを全選択した後、別シートへコピーするのが一番分かりやすいかと思います。このときに[ホーム]→[ペースト]の[行列を入れ替える]を活用することでコピーが出来ます。

f:id:akatanana-818ubugqm:20181030112158p:plain

f:id:akatanana-818ubugqm:20181030112441p:plain

 

これを繰り返して全データを縦に並べると下ごしらえの段階です。文字に起こすと長いですが、慣れると10数分で出来る単純作業になります。

f:id:akatanana-818ubugqm:20181030112442p:plain

 

STEP2:データを分類しよう

今回まとめるにあたって省きたいものは

・0を含む(ジョーカーを使う必要がある)

・下位互換である(これを除くことで覚える個数が90%以上も減る)

の2点です。今まとめた5桁の素数は8363個もあり、これを全て覚えるには一苦労します。それでは選り分けをしていきましょう。

 

まず使われている数字ごとに分類をしていきます。こんなときに便利なのがMID関数と呼ばれる関数です。Excelでは

=MID(選択したセル,n文字目,m文字)と入力する(MIDは小文字でも可、以下同様)ことで選択したセルの文字列の上からn文字目からm文字を値として返します。先ほど作った素数表の素数をMID関数を利用して分解しましょう。B1に=MID(A1,1,1)と入力することでA1の上から1文字目から1文字、つまり一万の位の「1」がB1に出力されます。同様に

C1には=mid(A1,2,1)と記入することで千の位の「0」が、

D1には=mid(A1,3,1)と記入することで百の位の「0」が、

E1には=mid(A1,4,1)と記入することで十の位の「0」が、

F1には=mid(A1,5,1)と記入することで一の位の「7」が出力されます。

f:id:akatanana-818ubugqm:20181030124002p:plain

 

次に分割した数字が0を含むかどうかを判定します。こちらはCOUNTIF関数を用いて分類します。COUNTIF関数は

=COUNTIF(指定した範囲,数値や文字列)と入力することで指定した範囲に検索したい数値や文字列が何個存在しているかの個数を値として返します。G1に=COUNTIF(B1:F1,0)と入力することでB1からF1までに0を何個含むか、つまり今回の場合3個0があるので「3」がG1に出力されます。 

f:id:akatanana-818ubugqm:20181128092207p:plain

 

そして0と同様にどの数字を何回使うかリストアップします。G1の関数をH1からP1までコピーして、0を1〜9までに変えていきます。こうすることでA1の素数が0を何回使い、1を何回使い、2を何回……9を何回使っているかが分かりやすくなります。

f:id:akatanana-818ubugqm:20181122104403p:plain

 

ついでにココで素数をアドレス化して検索しやすくします。Q1に

=G1&H1&I1&J1&K1&L1&M1&N1&O1&P1

と入力するとG1からP1までの文字列を全てくっつけた文字列が出てきます。この場合ですと「3100000100」という10桁のシリアルナンバーのようなものが完成します。

f:id:akatanana-818ubugqm:20181128092208p:plain

f:id:akatanana-818ubugqm:20181128092209p:plain

 

これを8363回も繰り返すのは大変なのでコピーをしてあげましょう。B1のセルからQ1のセルまでを選択し、右下の正方形をダブルクリックします。すると1行目で行ったMID関数・COUNTIF関数の演算を全ての行で同様に出力してくれます。

f:id:akatanana-818ubugqm:20181128092210p:plain

f:id:akatanana-818ubugqm:20181128092211p:plain

 

道具は揃いました、ここからが選別作業です。まず0を含む素数を消していきます。G列にはそれぞれの「0が使われている個数」が出力されているので、この列に1以上の数値が出力されている素数を消します。そこで役に立つのが昇降順による並べ替えです。まずG列全体を選択し、[データ]から[並び替え]を選択します。

f:id:akatanana-818ubugqm:20181128092212p:plain

 

並べ替え方について聞かれますので、[降順]を選択します。このときに操作方法について聞かれるので、[選択範囲を拡張する]にチェックをしてから並べ替えを実行します(これをすることで同じ行のデータも同様に並べ替えてもらえる)。

f:id:akatanana-818ubugqm:20181128092213p:plain

f:id:akatanana-818ubugqm:20181128092214p:plain

 

すると若い番号の行に0を含む素数(2251個)が集まります。いらない部分を全選択して削除しましょう(Shiftを押しながら選択するとラク)。

f:id:akatanana-818ubugqm:20181130091717p:plain

 

次に上位互換素数の被りを減らしていきます。同じ数字を使う素数はQ列でまとめたアドレスが一致するので、その部分で判定して選別します。先ほど行った昇順の並べ替えを行うのですが、A列の順序を正してから行わないと上位互換素数が上手く選別されない可能性があるのでそこに注意しましょう。A列で[昇順]の並べ替え→Q列で[昇順]の並べ替えを行います。このような順になるはずです。

f:id:akatanana-818ubugqm:20181130091718p:plain

 

ここでIF関数を用いて選別をしましょう。A列で昇順の並べ替えを行ったので同じアドレス内で一番下にある素数が上位互換素数となります。なのでR1に

=IF(Q1=Q2,0,A1)

と入力しましょう。この関数では左のアドレス(Q1)と次のアドレス(Q2)を比較し、そのアドレスが同じなら0を、違う場合(つまり下に同じアドレスがない場合)は素数を出力する演算を行います。これをコピーしてあげると上位互換だけが振るい出されます。

f:id:akatanana-818ubugqm:20181130104456p:plain

f:id:akatanana-818ubugqm:20181130104457p:plain

 

最後にR列で0が出力された下位互換素数を消してあげましょう。しかし、このままR列で[昇順]に並べ替えても、Excelが数値としての文字列ではなく関数として扱ってしまうので、並べ替えたあとも関数の処理を行ってしまいます。なので数値として認識してもらうようにしましょう。

まずR列全体を選択してコピーし、[ホーム]から[ペースト]を選択します。このときに[値]を選択すると、関数で出力された数値や文字列を値としてキチンと認識できるようになります。

f:id:akatanana-818ubugqm:20181130104458p:plain

f:id:akatanana-818ubugqm:20181130113244p:plain

 

これでR列を[昇順]で並べ替えてあげれば下位互換素数(5367個)が上に集まります。削除してあげましょう。

f:id:akatanana-818ubugqm:20181130113245p:plain

 

これで5枚出し5桁のまとめ終わりました。あとはA列の素数だけとっておくもよし、Q列のアドレスと一緒にとっておくもよし。

 

〜ここから先は応用編になります〜

まとめの段階で使わなかった素数大富豪ソフト(探索用)の使い方を紹介したいと思います。このソフトは任意の手札を入れると、出すことが出来る素数合成数出しを検索してくれる優れものです。なので絵札16枚の手札を入力することで5枚だし10桁の検索が可能ということです。この手札+1桁を1枚入力して検索すれば5枚出し9桁が、2枚入力して検索すれば5枚出し8桁の検索ができます。

f:id:akatanana-818ubugqm:20181130113246p:plain

 

この使い方は誰もが思いつくでしょう。では、これを応用して初めの[10]を[910]とするとどうでしょうか?

f:id:akatanana-818ubugqm:20181130131400p:plain

 

赤線を引いた部分に注目してみましょう。この機能を使うことで6枚出し11桁の検索をすることが出来ます(910,109,911,119,912,129,913,139の8通り検索する必要があるけど)。この手札+1桁を入力して検索すれば6枚出し10桁の検索も簡単です。

 

3:活用しやすくしよう

そのまま眺めても楽しい素数表ですが、せっかくアドレスがあるので検索しやすいように一工夫してあげましょう。まず先ほど作った素数表をアドレスと素数のみにします(検索するためのアドレスを左に置くのがポイント)。

f:id:akatanana-818ubugqm:20181130140204p:plain

まず検索をするときの前段階としてこのようなフォーマットを作ってみましょう。

f:id:akatanana-818ubugqm:20181130140205p:plain

 

D1からH1までには調べたい5枚の組み合わせを入れられるようにします。4行目にはその5枚に指定した数字がいくつ含まれるかを、先ほどの分類で用いたCOUNTIF関数で判定します。D4のセルに

=COUNTIF(D1:H1,1)

と入力しましょう。E4には1の代わりに2を、F4には3を……、L4には9を入力することでそれぞれの数字の個数を数えてくれます。下の場合は1が1個、2が1個、3が1個、4が1個、6が1個あることがキチンと表示されていますね。

f:id:akatanana-818ubugqm:20181130140206p:plain

 

そしてこれをアドレス化して検索しやすくしていきます。といっても先ほどのアドレス化とあまり変わりません。D7に

=0&D4&E4&F4&G4&H4&I4&J4&K4&L4

と入力しましょう。先頭の0は0の個数を検索した名残なのでより見やすくしたい場合はアドレスの0を全て切り取ることで、先頭の0を省くことも可能です。

f:id:akatanana-818ubugqm:20181130140207p:plain

 

最後にこのアドレスを素数群から検索が出来るようにしていきましょう。そんなときにめちゃくちゃ便利なのがVLOOKUP関数です。縦の列にデータをまとめているときに検索が出来るようになるので凄い活躍します。VLOOKUP関数は

=VLOOKUP(調べたい値,検索したい表の範囲,出力したい列,FALSE)

と入力することで調べたい値検索したい表の一番左から検索してその値が存在した場合、設定した同じ行の出力したい列の値を返す関数です(ムズカシイネ)。E7に

=VLOOKUP(D7,A:B,2,FALSE)

と入力することでD7のアドレスをA列~B列の範囲の一番左(今回の場合A列)から検索し、アドレスがあったら2列目の値である素数を出力してくれます。これで「この札持ってたら何が出せるかな……」とか知りたいときにすぐに検索できますね!

f:id:akatanana-818ubugqm:20181130140208p:plain

 

今回の発表は以上になりますが、最後に少し早いクリスマスプレゼントを。今回まとめたのは5枚出し5桁の表でしたが、5枚出し全ての上位互換一覧と表してスプレッドシートでまとめました!お使いになりたい方はご自身のExcelに各自コピーして御使い下さい。なお関数(COUNTIF関数とVLOOKUP関数)はコピーできないようですので、お手数ですがスプレッドシートに入力されている関数を見ながら各自で作成していただければと思います。誠に申し訳ございません。

https://docs.google.com/spreadsheets/d/1WXI4cYK5_kw-LtVb_vH132rGrMLvNt3ypdFpRf8fIq4/edit#gid=0

明日は素数大富豪大会で連続優勝を成し遂げた覇者もりしーさん(@9973_prm)による「二連覇への道のり/35億素数について」です。自分は巨大素数よりも確実な枚数出しを重視する研究タイプなので、別視点から見た素数大富豪が学べると期待しております。