Pythonプログラミング(番外編・Pythonコード集)
このページには、参考書『コンピュテーショナル・シンキング』 に掲載されているアルゴリズムをPythonコードで表現した例をいくつか掲載しておく
2章 プログラミングの基礎知識
Algorithm 5 回文数の判定アルゴリズム
Algorithm 5: 回文数の判定
# Algorithm 5
# coding: utf-8
import math
def kaibun(n):
if n<9:
print("YES")
return
lsd=n%10
d=int(math.log10(n)) # nの桁数-1
k=n%(10**d)
msd=(n-k)//(10**d)
if lsd!=msd:
print("NO")
return
m=k//10
kaibun(m)
# メイン部
n=int(input("自然数:"))
kaibun(n)
3章 問題解決事例演習・基本編
Algorithm 6 A君へ渡すコインの枚数を求める
Algorithm 6: コインの枚数
# Algorithm 6
# coding: utf-8
n = int(input("n= "))
p = float(input("p= "))
q = 1.0-p
V=0
W=0
k=1
while True:
W = (1.0-(q/p)**k)/(1.0-(q/p)**n)
if W>=0.5:
break
V = W
k = k+1
if 1/2-V < W-1/2:
print(k-1)
else:
print(k)
Algorithm 7 拡張互除法
Algorithm 7: 拡張互除法
# Algorithm 7
# coding: utf-8
def egcd(a,b):
if b==0:
return 1,0
r0=a
r1=b
P=[[1,0],
[0,1]]
while r1!=0:
r2=r0%r1
q1=r0//r1
P1=[[q1,1],
[1,0]]
p00 = P[0][0]*P1[0][0] + P[0][1]*P1[1][0]
p01 = P[0][0]*P1[0][1] + P[0][1]*P1[1][1]
p10 = P[1][0]*P1[0][0] + P[1][1]*P1[1][0]
p11 = P[1][0]*P1[0][1] + P[1][1]*P1[1][1]
P[0][0]=p00
P[0][1]=p01
P[1][0]=p10
P[1][1]=p11
r0 = r1
r1 = r2
det = P[0][0]*P[1][1] - P[0][1]*P[1][0]
x = P[1][1]//det
y = -P[0][1]//det
return x,y
# メイン部
print(egcd(120,88))
Algorithm 8 拡張互除法(再帰版)
Algorithm 8: 拡張互除法(再帰版)
# Algorithm 8 (p.71)
# coding: utf-8
def gcd(a,b):
if b==0:
return a
else:
return gcd(b,a%b)
def egcd(a,b):
if b==0:
return 1,0
q=a//b
r=a%b
x,y=egcd(b,r)
return y,x-q*y
# メイン部
print(egcd(120,88))
Algorithm 13 ピボット操作 および Algorithm 14 ブレンドコーヒーの作り方
円による縄張り問題(線形計画法による最適化)の simplex.pyを参照のこと
Algorithm 15 マフィンとクッキーを作る個数とその売り上げ
Algorithm 15: マフィンとクッキー
# coding: utf-8
a=60 # マフィンの価格
b=15 # クッキーの価格
A=3000 # 小麦粉の量
B=1600 # 砂糖の量
x0=0
y0=0
z0=0
x=0
y=0
z=0
while 25*x <= A and 15*x <=B:
y = min( round((A-25*x)/7) , round((B-15*x)/3) )
z = a*x + b*y
if z>z0:
x0=x
y0=y
z0=z
x=x+1
print("マフィンの個数:",x0," クッキーの個数:",y0," 売上げ:",z0)
4章 問題解決事例演習・発展編
Algorithm 16 巡回置換分解を求める
辞書と集合のページを参照のこと
Algorithm 18 Dijkstraの方法
最短経路探索のページを参照のこと
Algorithm 19 配属問題を解く
2部グラフのマッチングのページを参照のこと
ディジタルの傷を癒やす
アルゴリズムとしては記載されていないが、参考書で例示されているハミング符号についての検証用のコード例を示しておく。
# 『コンピュテーショナル・シンキング』p.149-
# coding: utf-8
def mul(a,A):
ncol=len(A[0])
nrow=len(A)
r=[0]*ncol
for j in range(ncol):
for i in range(nrow):
r[j] = (r[j] + a[i]*A[i][j])%2
return r
def add(a,b):
ncol=len(a)
r=[0]*ncol
for j in range(ncol):
r[j]=(a[j]+b[j])%2
return r
def distance(a,b):
ncol=len(a)
d=0
for j in range(ncol):
if a[j]!=b[j]:
d=d+1
return d
# 符号化行列
G = [
[1,0,0,1,1,1,0,0],
[0,1,0,0,1,1,1,1],
[0,0,1,1,0,0,1,1]
]
# 検査行列
H = [
[1,1,1,0,0],
[0,1,1,1,1],
[1,0,0,1,1],
[1,0,0,0,0],
[0,1,0,0,0],
[0,0,1,0,0],
[0,0,0,1,0],
[0,0,0,0,1],
]
# 符号語のハミング距離
dmin=10000
for i in range(2**3):
i0=i%2
i1=(i>>1)%2
i2=(i>>2)%2
for j in range (2**3):
if i==j:
continue
j0=j%2
j1=(j>>1)%2
j2=(j>>2)%2
d = distance(mul([i2,i1,i0],G),mul([j2,j1,j0],G))
if d<dmin:
dmin=d
print("最小距離=",dmin)
# 送信データ
x = [1,0,0]
print(x)
# 送信符号
xp=mul(x,G)
print(xp)
# ノイズ付加
xpp=add(xp,[1,0,0,0,0,0,0,0])
print(xpp)
# シンドローム
r=mul(xpp,H)
print(r)
Algorithm 20 加算分割問題を解く
Algorithm 20: 加算分割問題を解く
# Algorithm 20: 加算分割問題を解く
# coding: utf-8
def cross_sum(n, k, d):
if n<1:
return [ ],0
if d<k:
return [ ],0
if k==1:
if n<=d:
return [[n]],1
else:
return [ ],0
ell = [ ]
c = 0
t = min(d, n-k*(k-1)//2)
while True:
ellprime,cprime = cross_sum(n-t,k-1,t-1)
for g in ellprime:
ell.append(g + [t])
c = c + cprime
t = t - 1
if k*t < n + k*(k-1)//2:
break
return ell,c
ell,c = cross_sum(21,4,12)
print(c)
for x in ell:
print(x)
5章 情報の表現と文字列の操作
Algorithm 21 UTF-8からコードポイントを抽出する
Algorithm 21: UTF-8コードポイント
# Algorithm 21
# coding: utf-8
# Python 3 version
def codepoint(s):
b = s.encode('utf-8')
code = [ ]
k=0
while k < len(b):
c0 = b[k]
if c0 is None:
break
elif (c0 & 0b10000000) == 0 :
code.append(c0)
k=k+1
elif (c0 & 0b11110000) == 0b11100000:
c1 = b[k+1]
c2 = b[k+2]
code.append((c0 & 0x0F) * 2**12 + (c1 & 0x3F) * 2**6 + (c2 & 0x3F))
k=k+3
elif (c0 & 0b11111000) == 0b11110000:
c1 = b[k+1]
c2 = b[k+2]
c3 = b[k+3]
code.append((c0 & 0x07) * 2**18 + (c1 & 0x3F) * 2**12 + (c2 & 0x3F) * 2**6 + (c3 & 0x3F))
k=k+4
return code
# メイン部
res = codepoint("東北大学")
for c in res:
print("u{:x}".format(c))
Algorithm 22 簡易版ボイヤー・ムーア法
Algorithm 22: 簡易版ボイヤー・ムーア法
Pythonではリストの添字が0から始まることから、リストcとsの添字が参考書とは1だけずれている
# Algorithm 22
# coding: utf-8
def search(c, s):
n=len(c)
m=len(s)
i=0
while i<=n-m+1:
redo=False
for j in range(1,m+1,1):
if c[i+m-j-1] != s[m-j]:
ell=0
for k in range(m-j,0,-1):
if c[i+m-j-1]==s[k-1]:
ell=k
break
i = i+m-j+1-ell
redo=True
break
if not redo:
return i
return -1
# メイン部
c='PINEAPPLEJUICE'
s='APPLE'
pos=search(c,s)
if pos>=0:
print(pos)
else:
print('不一致')