Piで人を検索する方法とPythonがそれとどう関係するか

同僚、こんにちは! 最近、Python開発コースで自由な場所を描くという課題に直面しました。 一般的に、無料のスポットをいくつかプレイするのは簡単です。 参加者のリストがすでに用意されている場合は、文字通り2行で実行できます。



emails = pandas.read_csv("emails.csv") emails.sample(NUM_WINNERS, random_state=SEED)
      
      





そして、それはうまくいきます。 はい、Occamのカミソリは、必要なくエッセンスを生成する価値はないと言います。 しかし、問題があります-これは楽しくありません。 さらに、 Javaコースの受賞者をすでに選択しています 。 もちろん、2行で行うのではなく、抽象クラスのファクトリのファクトリが必要です。それだけです。 とにかく繰り返すつもりはありません。



バスケットから実際のボールを選択し、数字を認識し、APIを使用してチャットに送信するロボットを作成したいと思います(これは楽しいです!)、しかしそれは非常に高速ではありません。 決定は無意味で無慈悲で、特に時間がかかるものではありません。 そこで、Piという数字が思い浮かびました。 一般に、同僚と私は理想的なPiアーカイバーについて冗談を言っています。 一番下の行は簡単です。データを圧縮するには、番号Piでそれらが開始する場所を見つけて、位置を覚えるだけです(もちろん、長さ)。



比類のない圧縮! また、ustanik、特にPiのemai'yを探し、最初の人の勝者を検討することができます。 ポイントを正しく取得したい場合は、すぐにノートブックに移動できます。



インターネットでの短い検索により、Pythonを含むPi番号の数字を生成するための多くのソリューションが生成されました(この素晴らしいリソースも処理中です: www.angio.net/pi 、私は助けるしかありません)。 私は正直、人類がこの問題をとても心配していることを知りませんでした。 最も一般的なソリューション: Gauss – LegendreアルゴリズムChudnovskyアルゴリズムBBP式



数字の桁を無限に生成でき、事前に決められた桁数を生成しないオプションを選択しました。



 def pi_digits(): """generator for digits of pi""" q, r, t, k, n, l = 1, 0, 1, 1, 3, 3 while True: if 4 * q + r - t < n * t: yield n q, r, t, k, n, l = (10*q, 10*(rn*t), t, k, (10*(3*q+r))/t-10*n, l) else: q, r, t, k, n, l = (q*k, (2*q+r)*l, t*l, k+1, (q*(7*k+2)+r*l)/(t*l), l+2)
      
      





これは、同志ギボンズのスピゴットアルゴリズムで、ストリーミングモードでPi番号の桁を計算します。 すべての詳細は、Haskellファンに特にアピールする研究論文に記載されています。



参加者のメールをいくつかの番号に関連付けるだけです。 最初は、メールからmd5を取り出し、モジュロを除算して、指定された長さ以下の数値を取得したかったのです。 しかし、これはどういうわけかそれほどランダムではありません。特に、Pi番号の先頭に十分近いメールをピックアップして登録できるためです。 したがって、古き良きPSHCHを明らかにします。



 np.random.seed(SEED) emails["num"] = np.random.randint(10 ** (NUM_DIGITS - 1), 10 ** NUM_DIGITS - 1, size=len(emails))
      
      





数字の長さは事前に設定され、数字が長いほど、Piで数字を見つけるのが難しくなります。 検索機能を書くためだけに残っています。



 class _Num(object): def __init__(self, n): self.n = n self.s = str(n) self.p = 0 # pointer in number string representation self.l = len(self.s) def move_p(self, d): if self.p >= self.l: return if d == self.s[self.p]: self.p += 1 else: # find largerst prefix in num that is suffix in current part of Pi (dumb algorithm) pi_part = self.s[:self.p] + d self.p = 0 for i in xrange(1, len(pi_part)): if self.s[:i] == pi_part[-i:]: self.p = i def find_nums_in_pi(nums, first_n=None): MAX_POS = 10 ** 6 pi_gen = pi_digits() first_n = first_n if first_n is not None else len(nums) _nums = [_Num(n) for n in nums] nums_pos = {} for pos in itertools.count(): if pos % 1000 == 0: print "Current Pi position: %s. Nums found: %s" % (pos, len(nums_pos)) if pos == MAX_POS: raise RuntimeError("Circuit breaker!") d = str(pi_gen.next()) found_num = None for cur_num in _nums: cur_num.move_p(d) # whole number found if cur_num.p == cur_num.l: nums_pos[cur_num.n] = pos - cur_num.l + 1 # found enough numbers if len(nums_pos) == first_n: return nums_pos found_num = cur_num.n # create new search array without found number if found_num: _nums = [num for num in _nums if num.n != found_num]
      
      





行に番号を入れ、それらを先頭に設定し、Pi番号を生成し、この番号が指定された番号にある場合は、ポインターを前方に移動し、そうでない場合は、Pi番号の現在の部分の最大のサフィックスを探します。 番号が見つかったら、その番号と位置を覚えて、検索配列から削除します。 念のため、100万桁を超えないようにリミッターを追加し、進行状況の何らかのログを記録します。 ( 一部の境界の場合の検索は正しく機能しない場合がありますが、幸いなことに、これは私たちの目的にとって特に重要ではありません



電子メールが6桁の数字と一致した2人の勝者を見つけるのに約1分かかりました。 利益!



いつものように、「戦闘中」はすべて順調に進みませんでした。 描画はライブモードで開始され、ビデオはコンピューターから同時にブロードキャストされました。少し緊張し、1分ではなく5分かかりました。 しかし、状況をさらに強化するために、私はうっかり(正直に!)ノートブックでセルの実行を再起動しました。 そして、ノートブックは間違いを許さず、古い値を覚えておらず、セルを同期的に実行します。 ロープのように緊張した神経。 幸いなことに、すべてが順調に終了し、勝者が明らかにされ、授与され、正義が勝利しました。 ロボットに栄光を、Piに栄光を!



ちなみに、7月5日20時から2時までのコースには、さらに別の場所があります。 美しいに触れたいですか? テストを受けてOpen Dayに登録してください。時間があります!



All Articles