2016年2月1日月曜日

Ubuntu 同人誌「うぶんちゅ! まがじん ざっぱ~ん♪ vol.4」がリリースされました

みなさん、こんばんは。

夏や冬とは関係ない、謎のタイムラインで書かれている Ubuntu 同人誌の「うぶんちゅ! まがじん ざっぱ~ん♪」の vol.4 がリリース・発売開始となりました。関係者のみなさま特に編集長のいくやさんのご尽力にはいつも頭が下がるところです。

今回のお題はネットワークということでしたが、無料で(もしくは可能なかぎり安く)Webサーバ向けのSSL証明書を取得するお話を特集記事として書きました。ぜんぜんゲストじゃないゲストページまでは個人的に手がだせませんでしたが、それでも70ページの分量となりました。内容についても、同人誌っぽい話題のではありますが、みなさん真剣に執筆されて、読み応えのあるものになったと思います。個人的には編集長のいくやさんのあとがきがグッときました。あとがきが面白いのってまるでライトノベルみたいですよね!

販売はGumloadさんで(現在期間限定特価です)、あるいは編集長Amazonギフト券決済が用意されています(DLsite.comでの販売も準備中です)。

昨年は諸般の事情で自分は商業誌に登場する機会がなかったのですが、今年は今回のざっぱ〜んを契機に色々なところで書きたいなと思っています。

2016年1月22日金曜日

現代にオカルトを活かす(?)には

みなさんこんばんは。

今日は勝手(?)に黒猫魔術店さんの「毒林檎」を紹介したいと思います。

黒猫魔術店さんは私の実家に近い、山形県酒田市にあるリアル店舗のオカルトショップさんで、この年末年始に帰省したときに襲撃(?)してきました。

すでにいろんなメディアでも紹介されていますが、この「毒林檎」は地元山形県庄内地方産の林檎と趣向を凝らした願掛けの方法のセット商品です。

「願掛け」もよくある子供だましのものではなく、月が満ちゆく期間でかつボイドタイム(占星術上の概念で月が他の天体と特定の角度を形成しなくなってから次のサイン入りをするまでの期間)を避けて日取りを決めるところから始まるなど、手加減なしの内容となっています。林檎もただの林檎ではなく地元で黒猫魔術店が監修し丹精こめて育てられ、火を通して食べることを前提にした一級品で、経験や体験をまるごとラッピングしています。

この商品企画の凄いところは、農産物とオカルトをうまく組み合わせて体験型の商品として高い付加価値をつけることに成功したところです。食べ物を無駄にせずに「最後に食べる」ことを指示しているのも高ポイント。「魔女術」を示す Witchcraft の単語に「手芸・工芸」を意味する craft が含まれているところをよく理解し、そしてこのように商品企画をすることで実践しているのが素晴らしいと思います。

地方の物産をアピールする方法としては「萌えおこし」や「ゆるキャラ」といったムーブメントがありましたが、表面的なスタイルを真似るだけではもうアピールできない時代になっている気がします。

単に品質の高い農産物というだけではアピールポイントとしては弱いうえに大消費地向けに出荷されるものが大多数で地元よりも東京のほうが特産品の入手性が良かったりすることもよくあります( 事実、山形県産の農産物は銀座のアンテナショップが山形県内のどのショップよりもバランスが良いと思っています )。

もちろん通販で「お取り寄せ」すれば大抵のものは手に入る時代になったというのも大きいところでしょう。

単に珍しいだけでは見向きもされず、「体験」までうまくプロデュースするような仕掛けが求められていると感じます。

オカルトな要素を見ても、昨今は質が悪く単なるいかがわしいものが世にはびこり、法外な金額をとるものや、人を騙すことを目的とした何かが多い一方で、グッズそのものはネット通販で手に入る時代( 海外メーカーのタロットデッキなんて最小の英語力があれば簡単に買えてしまいます。ものによっては Amazon.com でポチるだけです )、本質は何かということに真摯に向き合うべきなのかもしれません。

オカルトというか魔術はこうあるべきだと感じました。きっと一般の方にはオカルトと同じように見えるITの世界にいる私も見習いたいところです。

今後も黒猫魔術店さんのご活躍を期待いたします。

2016年1月14日木曜日

【POH7】パターンマッチング(「めがね」)

みなさんこんばんは。

昨年12月に開催されたPaizaさんのPOH7の解説、第2回で「めがね」の問題を解説します。その他の問題は難しくないのでこれで最終回(笑)です。

さて、「めがね」の問題ですが、これは白黒画像のパターンマッチングの問題で、たとえば、
0 0 1 0
0 1 1 0
0 1 0 1
1 1 1 0
 という全体画像(0と1のどちらが黒でも白でも問題の本質には変わりないのですが、問題ページの説明では、1が黒で表現されていました)の中から
0 1 1
0 1 0
1 1 1
のパターン画像に一致する場所を調べて、その位置を出力する問題です。この例の場合で全体画像のうち最初の行を0行目、最初の文字を0文字目として数えると、1行0文字目からの3文字3行分が一致するので、
1 0
と出力をするようなプログラムを書く問題です。

【POH7】階乗 n! の最下位から続く0を除いた値の下9けたの出力

みなさんこんにちは。

去年12月に Paiza さんの POH7 に参加して、Gigazine さんに捕捉されて「猛者」認定されてしまったエントリを書きましたが、イベントのAmazonギフト券応募期間が終わったので解説を書いてみたいと思います。今回取り上げるのは「水着」の問題
入力された自然数 n (最大1000000)の階乗 n! での、最下位から続く0を除いた値の下9けたを出力せよ
という問題です。「nの階乗」というのは
n! = 1 x 2 x 3 x ... x n
で計算できる数です。プログラミングでは一般的に32ビットや64ビットのメモリでの表現を整数型として計算することが多いのですが、階乗を真面目に計算していくとすぐに表現できなくなります。
21! = 51090942171709440000 > 2^64
複数の整数型をまとめて、より大きな数を多倍長整数として表現し計算することも可能ですが、最大で 1000000!を計算する必要があり、ひたすら大きい数に対してひたすら掛け算しないといけません。桁数が大きくなればなるほど、かけ算の計算量も増えるわけですが、この問題ではそれだけ大きい数を正直に計算する必要はなく「最下位けたから続く0を除き、その数の下位9けた」を出力すればよいとされています。

「最下位けたから続く0を除く」というのは「10で割った余りが0であるかぎり10で割り算する」ということで、「下位9けた」というのは「10^9で割った余り」なので、新しい数をかけ末尾の0を削り10^9で割った余り求めるということを1〜nまで繰り返せば計算できそうです。Python2で書くなら

#! /usr/bin/env python2
n = int(raw_input())
r = 1
for i in xrange(1,n+1):
    r *= i
    while r % 10 == 0:
        r /= 10
    r %= pow(10,9)
print r

といった形で計算できそうです。がしかし、実はこれでは正しく計算できません。例えば n=25 の場合を考えると、 
24! = 620448401733239439360000
この問題での出力: 323943936
25! = 15511210043330985984000000
この問題での出力: 330985984 
ということになるのですが、n=24での出力に25をかけると
323943936 x 25 = 8098598400
と、除外しないといけない最下位の0が出てきてしまいます。n=24のときの結果に対して9桁よりも多くの桁を準備しないと正しい数値が計算できません。
323943936 x 25 = 8098598400 ... NG
3323943936 x 25 = 83098598400 ... NG
73323943936 x 25 = 1833098598400 ... OK
実践的に考えると、n の数に応じて「下位9けたよりも多く」の数字を準備しておくのが、とりあえずは現実的なところかと思います。なんとなく、log10(n)+1桁分を9桁に加えて準備しておけばよさそうですが、証明したわけではありません。

この問題を真面目に解くためには「ルジャンドルの定理」というのを使うことができます。アイディアとしては、階乗の数を素因数分解するというものです。

定理の説明はこちらこちらを見ていただくとして、25! を素因数分解した時に出てくる 2 の個数で考えると、 floor(25/2) = 12, floor(25/4) = 6, floor(25/8) = 3, floor(25/16) = 1 の総計22個となります。事前にnまでの素数列を準備しておけば素因数分解をするのはそれほど大変な計算とはなりません。

与えられた n について n! を素因数分解の形で表現することができたら、「最下位けたから続く0を除き、その数の下位9けた」を求めることになりますが、いうまでもなく 2 x 5 = 10 ですから、素因数分解した結果の2と5の個数を調整(2の個数と5の個数のうち少ない方を調べて、2と5の個数それぞれから引く)すれば最下位けたの連続する0を取り除くことができます。

残ったものを素因数分解の形式から数字に戻せばよいのですが、0が最下位に出る可能性は排除できているので、順次掛け算をして10^9 で割った剰余を計算することでほしい結果を得ることができます。

#! /usr/bin/env python2

def primes(n):
    # n までの素数列を返す関数を実装(記述は省略します)

n = int(raw_input())

ps = primes(n)
idx = []

for p in ps:
    m = p
    e = 0
    while m<=n:
        e+=int(n/m)
        m*=p
    idx.append(e)

if len(idx)<3:
    idx.extend([0,0,0])

ten = min(idx[0],idx[2])
idx[0] -= ten
idx[2] -= ten

mi = map(lambda (a,b):pow(a,b,pow(10,9)),zip(ps,idx))
print reduce(lambda a,b:a*b%pow(10,9),mi)

POH7 での問題ではnの上限(最大1000000)が決まっているので、ここまでやる必要はかならずしもないのですが、こういったアプローチを論理的に展開できるようになりたいものだと思いました。