トップ Team(・∀・)2ch 新規 一覧 検索 ヘルプ RSS ログイン

問題集の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!! 問題集

{{outline}}

!! Simple

変数、リスト、辞書などの定義、if elif else、for・・・くらいの知識で解けるもの。

! Hello, world!

 print 'Hello, world!'

! 1から50までの和を計算して表示

 #普通の方法
 s = 0
 for x in range(1,51):
     s += x
 print s
 
 #sumを使う
 print sum(range(1,51))
 
 #generator式を使う
 print sum(x for x in range(1,51))
 
 #reduceを使う
 print reduce(lambda x,y: x+y, range(1,51))
 
 #頭を使う
 print 50*51/2

! 2つの自然数の最大公約数を求める(ユークリッドの互除法)

 a,b = input(), input()
 
 #再帰関数
 def gcd(a, b):
     if b == 0:
         return a
     else:
         return gcd(b, a%b)
 print gcd(a,b)

! 2つの自然数の最小公倍数を求める。

 #上のgcdを用いて
 print a*b/gcd(a,b)

! 10000以下の素数を表示する。

 # 怠惰な方法
 for i in range(2,10000):
     if 0 not in [i%j for j in range(2,i/2+1)]:
         print i
 
 # 少しちゃんとした方法
 from math import sqrt
 for i in range(2,10000):
     if 0 not in [i%j for j in range(2, int(sqrt(i))+1)]:
         print i
  
 #上のよりもっと速い方法
 # 2に対して2より大きい偶数を削除し、3に対して3より大きく3で割れる数を排除し・・・
 # としていくので無駄なチェックが減っている
 MAX = 10000
 LIST = range(2, MAX + 1)
 for i in range(2, int(MAX ** 0.5)):
      LIST = [x for x in LIST if (x == i or x % i != 0)]
 for j in LIST:
      print j
 
 
 #エラトステネスの篩
 #(コードは煩雑そうに見えるが、速度が圧倒的に速い。
 # 大きな数までの素数表が必要な場合に必要な方法。)
 a = range(10000)
 a[1] = 0 # 1 は素数ではない
 for p in a:
     if not p:
         continue
     elif p > 100: # 100 = sqrt(10000)
         break
     else:
         for multi in xrange(p+p, 10000, p):
             a[multi] = 0
 
 # この時点で、aは、素数p番目にはpが、それ以外には0が入ったリストになっている。
 a = [x for x in a if x]
 for x in a: print x
 
 
 # listを生成せずにgeneratorで無限に出力
 # (エラトステネスの篩とほぼ等価で高速)
 from itertools import ifilter, count
 def primes():
   g = count(2)
   while True:
     p = g.next()
     yield p
     g = ifilter(lambda n, p=p: n % p, g)
 
 >>> for i, p in enumerate(primes()):
 ...  print '(%d:%d)' % (i, p)
 ...  raw_input()
 ...
 (0:2)
 (1:3)
 (2:5)


! フィボナッチ数(1,1,2,3,5,8,13,...)を2**31より小さい範囲まで表示する。

 a=b=1
 while a < 2**31:
     print a
     a, b = b, a+b

! 無限にフィボナッチ級数を返し続けるgenerator。

 def fib():
   a = b = 1
   while True:
     yield a
     a, b = b, a+b
 
 >>> f = fib()
 >>> for t in xrange(15):
 >>>   print f.next(),
 >>> 1 1 2 3 5 8 13 21 34 55 89 144 233 377

# generatorを使わずに
 a = b = 1
 c = 2
 while a < c:
	 print a,
	 a, b = b, a + b
	 c += a

! n**(n**n) の一の位の数字を表示する。(nが1000程度でもそれなりの速度で動作しますが、nの剰余と合同を使えばpow使わずに済みます。下記参照)

 pow(n, pow(n, n), 10)

! n**(n**n) の一の位の数字を表示する。(pow不使用)

 >>> c=[(0,), (1,), (2,4,8,6,), (3,9,7,1,), (4,6,), (5,), (6,), (7,9,3,1,), (8,4,2,6,), (9,1,)]
 >>> [c[n%10][(n%2)*n%len(c[n%10])-1] for n in xrange(20)]
 [0, 1, 6, 7, 6, 5, 6, 3, 6, 9, 0, 1, 6, 3, 6, 5, 6, 7, 6, 9]


!! Normal

文字列やリストのメソッド、関数定義、イテレータ、ファイル入出力、基本的な正規表現などが使える人向け。

! テキストファイル'text.txt'から数字を読み込み大きい数から順に並べて画面に表示する

 a = open('text.txt').read().split()
 a.sort()
 for i in a[::-1]: print i
 #別解
 print sorted(open('text.txt').read().split(), key = int, reverse = True)
 #sorted関数を使うと、ソートのための一時的なリストを作る必要が無くなるので便利

! 標準ライブラリを使ってsin 60°を求める

 from math import sin, pi
 print sin(pi/3)

! 摂氏を入力すると、華氏で出力。華氏を入力すると、摂氏で出力。動作例: "41F"を入力すると"5C"、"5C"を入力すると"41F"と表示する

 >>> def convt():
 ...  import re
 ...  r = re.compile(r'^([\.\d]+)(C|F)$', re.I)
 ...  t = raw_input('temperature(C or F)= (ex 5C, 41F, etc)? ')
 ...  q = r.match(t)
 ...  if q:
 ...   if q.group(2).upper() == 'C':
 ...    print '%fF' % (float(q.group(1)) * 9 / 5 + 32)
 ...   if q.group(2).upper() == 'F':
 ...    print '%fC' % ((float(q.group(1)) - 32) * 5 / 9)
 ...
 >>> convt()
 temperature(C or F)= (ex 5C, 41F, etc)? 5c
 41.000000F
 >>> convt()
 temperature(C or F)= (ex 5C, 41F, etc)? 41f
 5.000000C
 >>> convt()
 temperature(C or F)= (ex 5C, 41F, etc)? 2.5c
 36.500000F
 >>> convt()
 temperature(C or F)= (ex 5C, 41F, etc)? 20.5f
 -6.388889C

! 16進数ダンプを行う

 print ''.join('%02x '%ord(x) for x in given_string)

! テキストファイル'text.txt'の中にPythonと言う文字がいくつ含まれるか調べる

 print open('text.txt').read().count('Python')

! パスワード生成する

 import string
 import random
 
 print ''.join([string.printable[n] for n in [
  random.randint(0, len(string.printable) - 1) for r in xrange(20)]])

!文字候補'python'からn文字の文字列を生成する(重複なしの場合)

 >>> def perm(n, m):
 ...  if m<1:
 ...   yield()
 ...  else:
 ...   for r in perm(n, m-1):
 ...    for x in xrange(n):
 ...     if x not in r:
 ...      yield r + (x,)
 ...
 >>> def create_word_list_p(n, s):
 ...  return [''.join(s[i] for i in t) for t in perm(len(s), n)]
 ...
 >>> create_word_list_p(3, 'python')
 ['pyt', 'pyh', 'pyo', 'pyn', 'pty', 'pth', 'pto', 'ptn', 'phy', 'pht',
  'pho', 'phn', 'poy', 'pot', 'poh', 'pon', 'pny', 'pnt', 'pnh', 'pno',
  (省略)
  'npy', 'npt', 'nph', 'npo', 'nyp', 'nyt', 'nyh', 'nyo', 'ntp', 'nty',
  'nth', 'nto', 'nhp', 'nhy', 'nht', 'nho', 'nop', 'noy', 'not', 'noh']

!文字候補'python'からn文字の文字列を生成する(重複ありの場合)

 >>> def combi(a, b):
 ...  if isinstance(a[0], tuple):
 ...   return [x + (y,) for x in a for y in b]
 ...  else:
 ...   return [(x, y) for x in a for y in b]
 ...
 >>> def combination(*l):
 ...  return reduce(combi, l)
 ...
 >>> combination([1,2,3],[4,5],[6,7])
 [(1, 4, 6), (1, 4, 7), (1, 5, 6), (1, 5, 7),
  (2, 4, 6), (2, 4, 7), (2, 5, 6), (2, 5, 7),
  (3, 4, 6), (3, 4, 7), (3, 5, 6), (3, 5, 7)]
 >>> def create_word_list(n, s):
 ...  return [''.join(s[i] for i in t) for t in combination(*[xrange(len(s)) for j in xrange(n)])]
 ...
 >>> create_word_list(3, 'python')
 ['ppp', 'ppy', 'ppt', 'pph', 'ppo', 'ppn',
  'pyp', 'pyy', 'pyt', 'pyh', 'pyo', 'pyn',
  'ptp', 'pty', 'ptt', 'pth', 'pto', 'ptn',
  'php', 'phy', 'pht', 'phh', 'pho', 'phn',
  'pop', 'poy', 'pot', 'poh', 'poo', 'pon',
  'pnp', 'pny', 'pnt', 'pnh', 'pno', 'pnn',
  (省略)
  'npp', 'npy', 'npt', 'nph', 'npo', 'npn',
  'nyp', 'nyy', 'nyt', 'nyh', 'nyo', 'nyn',
  'ntp', 'nty', 'ntt', 'nth', 'nto', 'ntn',
  'nhp', 'nhy', 'nht', 'nhh', 'nho', 'nhn',
  'nop', 'noy', 'not', 'noh', 'noo', 'non',
  'nnp', 'nny', 'nnt', 'nnh', 'nno', 'nnn']

! リスト A = ['AA', 'AB', 'AC'],B = ['BA', 'BB', 'BC'] から [('AA', 'BA'), ('AB', 'BA'), ... ,  ('AC', 'BB'), ('AC', 'BC')] のように,それぞれから1つづつ取ってきたリストを簡単に生成する
 C = reduce(lambda x, y: x+y,[[(x,y) for y in B] for x in A])

! リスト [ ['Py','PyA'],['Py','PyB'],['Py','PyC'],['Pe','PeA'],['Pe','PeC'] ] から、辞書 {'Py': ['PyA', 'PyB', 'PyC'], 'Pe': ['PeA', 'PeC']} を生成する

 a = [ ['Py','PyA'],['Py','PyB'],['Py','PyC'],['Pe','PeA'],['Pe','PeC'] ]
 t = {}
 for n in a:
     if n[0] in t: t[n[0]].append(n[1])
     else: t[n[0]] = [n[1]]
 # 別解
 t = {}
 for n in a:
     t.setdefault(n[0], []).append(n[1])

! n個の空リストを要素とするリスト [ [],[],・・・,[] ] を生成する。

 a = [[]] * n # 注意:浅いコピー
 a = [[] for x in range(n)]

!! Advanced

やや専門的なライブラリが使える。クラス定義してオブジェクト指向プログラミングができる。正規表現をけっこう使える。

! 2chのトリップを生成する。(旧)
2009-06-19より[新方式|http://qb5.2ch.net/operate/kako/1244/12449/1244993904.html]が採用されていますので一部結果が異なります。[12桁トリップ|http://d.hatena.ne.jp/itasuke/20120503/p1]

 import sys, re
 from string import maketrans
 if sys.platform == 'win32':
   from fcrypt import crypt
 else:
   from crypt import crypt
 def trip(key):
   salt = re.sub('[^\.-z]', '.', (key + 'H.')[1:3]).translate(
     maketrans(':;<=>?@[\\]^_`', 'ABCDEFGabcdef'))
   return crypt(key, salt)[-10:]

! 電話帳プログラムを作る。

 >>> phones = {}
 >>> def reg():
 ...  name = raw_input('name= ')
 ...  tel = raw_input('tel= ')
 ...  phones[name] = tel
 ...
 >>> reg()
 name= abc
 tel= 123-4567
 >>> reg()
 name= def
 tel= 890-1234
 >>> phones
 {'abc': '123-4567', 'def': '890-1234'}
 >>>

!! Maniac

問題読んだだけでは解法が思いつかない。あるいはすぐ思いつく方法が実は間違ってるようなもの。

! FizzBuzz

[解き方いろいろ|http://python.rdy.jp/wiki.cgi?page=FizzBuzz]

! 乱数を使って円周率の近似値を求める

 #!/usr/bin/python
 
 # モンテカルロ法による円周率の近似値の計算
 #
 # 1セットMAX_I回の試行をMAX_Jセット繰り返す。
 
 from random import *
 
 seed()
 MAX_J = 100
 MAX_I = 10000
 total = 0.0
 for j in range(MAX_J):
 	score = 0.0
 	for i in range(MAX_I):
 		x = random()
 		y = random()
 		r = x*x+y*y
 		if (r &lt; 1):
 			score += 1
 	score = 4*score/MAX_I
 	print score
 	total += score
 print
 print total/MAX_J

! Quine (自分自身のソースコードと同じ文を出力するプログラム)

 x='x=%s;print x%%`x`,';print x%`x`,

 x='x=%s\nprint x%%`x`'
 print x%`x`
 

 x='x=%s;print x%%`x`,;print';print x%`x`,;print 1729

! http://www.geocities.co.jp/SiliconValley-Cupertino/7896/software/turing.html みたいなチューリングマシン

! brainfuck interpreter

! bogoYAML parser