(Pywikibot 디렉토리)/scripts/userscripts에 다음 두 파일을 저장합니다.
createnumarticle.py[편집 | 원본 편집]
우선 각종 텍스트를 생성하는 코드인 createnumarticle.py입니다.
코드 보기
import re
import numpy as np
list_prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009]
list_irregular_prime = [37, 59, 67, 101, 103, 131, 149, 157, 233, 257, 263, 271, 283, 293, 307, 311, 347, 353, 379, 389, 401, 409, 421, 433, 461, 463, 467, 491, 523, 541, 547, 557, 577, 587, 593, 607, 613, 617, 619, 631, 647, 653, 659, 673, 677, 683, 691, 727, 751, 757, 761, 773, 797, 809, 811, 821, 827, 839, 877, 881, 887, 929, 953, 971]
list_highly_composite = [1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840]
list_pseudoprime = [341, 561, 645]
list_pseudoprime_3 = []
list_pseudoprime_5 = [4, 124, 217, 561, 781]
list_Carmichael = [561]
def checkprime(num): #check prime/composite and check completeness
if num in list_prime and num>2:
ind = list_prime.index(num)
res = '* {0}번째 소수이며, 이전 소수는 {1}, 다음 소수는 {2}이다.\n'.\
format(ind+1,list_prime[ind], list_prime[ind+2])
if num+2 in list_prime:
res += '* 2 큰 수인 {0}도 소수인 쌍둥이 소수(Twin Prime)이다. \n'.format(num+2)
elif num-2 in list_prime:
res += '* 2 작은 수인 {0}도 소수인 쌍둥이 소수(Twin Prime)이다. \n'.format(num-2)
if 2*num+1 in list_prime:
res += '* 소수 {0}에 대해 2n+1={1}도 소수인 소피 제르멩 소수이다. \n'.format(num, 2*num+1)
if num in list_irregular_prime:
res += "* 비정규 소수(Irregular Prime)로 베르누이 수 ''B<sub>k</sub>''에 대해 k≤{0}이면서 분모가 {1}을 나누는 k가 존재한다.".format(num-3, num)+'\n'
else:
res += "* 정규 소수(Regular Prime)로 베르누이 수 ''B<sub>k</sub>''에 대해 k≤{0}이면서 분모가 {1}을 나누는 k가 존재하지 않는다.".format(num-3, num)+'\n'
elif num>2:
res = '* {0}으로 소인수분해되며, 약수는 {1}로 모두 {2}개이다\n'.\
format(printfactor(num)[0],', '.join(l_int2str(printfactor(num)[3])), printfactor(num)[1])
res +='* 모든 약수의 합은 {0}이며, {1}이다.\n'.\
format(printfactor(num)[2], printiscomplete(num) )
if num in list_highly_composite:
res +='* 고등합성수(Highly composite number)로 자신보다 작은 어떤 수보다도 더 많은 약수를 가진 수이다.\n'
return res
def dropmulti(_lis): #remove redundant number
res = []
for i in _lis:
if i not in res:
res.append(i)
return res
def factor_prime(num): #return list of of prime factors
res = [] # empty list
a_prime = np.array(list_prime)
a_use = a_prime[a_prime<=np.sqrt(num)] #제곱근 이하 소수만...
for i in a_use:
if num%i == 0:
res = factor_prime(num//i) #recursive
res.insert(0, i) #append number at the beginning
break #escape loop
if len(res)<2: #if num is not composite
res = [num] #add num
return res
def printfactor(num): #factorization expression
if num ==1 :
return [1, 1, 1, [1], {}]
else: #num>1
factor_list = factor_prime(num)
factor_num = dropmulti(factor_list) #remove duplication
cnt_factor = {} #empty dict
res = ''
fcnt = 1 #number of factors
fsum = 1 #sum of factors
flist_pr = {} #prime factors dictionary
flist = np.array([1]) #factor list
for i in factor_num: #prime factor without duplication
cnt_factor[i] = factor_list.count(i)
res += str(i)+'<sup>'+str(cnt_factor[i])+'</sup>×'
flist_pr[i] = np.array([i**k for k in range(0, factor_list.count(i)+1)])
res = res[0:-1].replace('<sup>1</sup>', '') #remove last character × and replace i<sup>1</sup> to i
for i in factor_num: #i is prime factor
fcnt *= (cnt_factor[i]+1) #number of factors
fsum *= (i**(cnt_factor[i]+1)-1)//(i-1) #sum of factors
flist_fix = flist #flist를 재귀적으로 정의하기 위해서
for j in flist_pr[i]:
if j != 1:
flist = np.concatenate((flist, flist_fix*j), axis=None)
return [res, fcnt, fsum, sorted(flist.tolist()), flist_pr] #three results
def iscomplete(num): #완전수 판단.
fsum = printfactor(num)[2]
if fsum<num*2:
return ['부족수', []]
elif fsum == num*2:
return ['완전수', printfactor(num)[3][0:-1]] #자기 자신을 제외한 모든 숫자
else:
flist = printfactor(num)[3][0:-1] #무한루프 방지를 위해 자기 자신은 반드시 빼야한다!
for fac in flist:
if iscomplete(fac)[0] in ['완전수', '준완전수']:
res1 = np.array(iscomplete(fac)[1])*num//fac
return ['준완전수', res1.tolist()] #multiple of complete or semicomplete : semicomplete
else:
pass
fsublist = substrings(flist)
for fsub in fsublist:
if sum(fsub) == num:
return ['준완전수', fsub]
return ['괴짜수', []]
def substrings(_list): #substring list
if len(_list) == 1:
return [[], _list] #
else: #len(_list)>1
res = substrings(_list[0:-1])
res1 = []
for comp in res:
comp1 = comp+[_list[-1]]
res1.append(comp1)
return res+res1
def printiscomplete(num):
if iscomplete(num)[0] in ['부족수', '괴짜수']:
return iscomplete(num)[0]
else:
res_sq = '+'.join(l_int2str(iscomplete(num)[1]))
return '{0}이고, {1}={2}'.format(iscomplete(num)[0], num, res_sq)
def l_int2str(_list):
res = []
for i in _list:
res.append(str(i))
return res
def checkpower(num):
sq_num = [i**2 for i in range(2,101)] #square
cube_num = [i**3 for i in range(2,22)] #cubic
quad_num = [i**4 for i in range(2,11)] #quadruple
penta_num = [i**5 for i in range(2, 7)] #power of 5
power2 = [2**i for i in range(6,14)] #remainig power of 3
power3 = [3**i for i in range(6,9)] #remainig power of 3
sum_cube = [i**2*(i+1)**2//4 for i in range(2,14)] #sum of cubes from 1 to n^3
if num in power3:
i = power3.index(num)+6
res = '* 3의 {0}제곱수이다.'.format(i)
if i%6 == 0:
res += ' 따라서 제곱수이자 세제곱수이다.\n'
elif i%4 ==0:
res += ' 따라서 네제곱수이다.\n'
elif i%3 ==0:
res += ' 따라서 세제곱수이다.\n'
elif i%2 ==0:
res += ' 따라서 제곱수이다.\n'
else:
res +='\n'
return res
elif num in power2:
i = power2.index(num)+6
res='* 2의 {0}제곱수이다.'.format(i)
if i%6 == 0:
res += ' 따라서 [[제곱수]]이자 [[세제곱수]]이다.\n'
elif i%4 ==0:
res += ' 따라서 네제곱수이다.\n'
elif i%3 ==0:
res += ' 따라서 [[세제곱수]]이다.\n'
elif i%2 ==0:
res += ' 따라서 [[제곱수]]이다.\n'
else: return '\n'
return res
elif num in penta_num:
i = penta_num.index(num)+2
return '* {0}의 다섯제곱수다.\n'.format(i)
elif num in quad_num:
i = quad_num.index(num)+2
return '* {0}의 네제곱수이며, 따라서 [[제곱수]]다.\n'.format(i)
elif num in cube_num:
i = cube_num.index(num)+2
return '* {0}의 세제곱인 [[세제곱수]]다.\n'.format(i)
elif num in sq_num:
if num in sum_cube:
i = sum_cube.index(num)+2
return '* 1부터 {0}까지의 세제곱수(cubic number)의 합이다. 즉, {0}번째 삼각수 \'\'T<sub>{0}</sub>\'\'={1}의 제곱인 제곱수이다.\n'.format(i, i*(i+1)//2)
else:
i = sq_num.index(num)+2
return '* {0}의 제곱인 [[제곱수]]다.\n'.format(i)
else:
return ''
def checkpolygon(num):
res=''
tri_num = [i*(i+1)//2 for i in range(2,50)]
penta_num = [i*(3*i-1)//2 for i in range(2,28)]
hexa_num = tri_num[1::2] #every tri number with odd index is hexa num
hepta_num = [i*(5*i-3)//2 for i in range(2,24)]
octa_num = [3*i*i-2*i for i in range(2,20)]
if num in hexa_num:
i = hexa_num.index(num)+2
res+= '* {0}번째 육각수(hexagonal number)며, 따라서 {1}과 {2} 사이의 {3}번째 [[삼각수]]다\n'.\
format(i, (2*i-1)*(2*i-2)//2, (2*i)*(2*i+1)//2 , 2*i-1)
elif num in tri_num:
i = tri_num.index(num)+2
res+= '* {0}과 {1} 사이의 {2}번째 [[삼각수]]다.\n'.format(i*(i-1)//2, (i+1)*(i+2)//2, i)
if num in penta_num:
i = penta_num.index(num)+2
res+= '* {0}과 {1} 사이의 {2}번째 오각수(Pentagonal Number)다.\n'.format((i-1)*(3*i-4)//2, (i+1)*(3*i+2)//2, i)
if num in hepta_num:
i = hepta_num.index(num)+2
res+= '* {0}과 {1} 사이의 {2}번째 칠각수(Heptagonal Number)다.\n'.format((i-1)*(5*i-8)//2, (i+1)*(5*i+2)//2, i)
if num in octa_num:
i = octa_num.index(num)+2
res+= '* {0}과 {1} 사이의 {2}번째 팔각수(Heptagonal Number)다.\n'.format((i-1)*(3*i-5), (i+1)*(3*i+1), i)
return res
def fibonacci(num): # 피보나치 수열
if num ==0 : return 0
elif num == 1: return 1
else: return fibonacci(num-1)+fibonacci(num-2)
def checkfibonacci(num):
fibo_list = [fibonacci(i) for i in range(1, 30)]
if num in fibo_list:
i = fibo_list.index(num)+1
res = '* {0}과 {1} 사이의 {2}번째 [[피보나치 수]]다.\n'.format(fibonacci(i-1), fibonacci(i+1), i)
return res
else: return ''
def factorial(num): #팩토리얼
if num in [0,1]: return 1
else: return num*factorial(num-1)
def checkfactorial(num):
fact_list = [factorial(i) for i in range(1,8)]
if num in fact_list:
i = fact_list.index(num)+1
res = '* {0}={1}!으로 정의되는 [[계승]](Factorial)이다.\n'.format(num, i)
return res
else: return ''
def checktetrahedral(num):
tetra_list = [i*(i+1)*(i+2)//6 for i in range(1, 30)]
if num in tetra_list:
i = tetra_list.index(num)+1
res = '* {0}과 {1} 사이의 {2}번째 정사면체수(tetrahedral number)다.\n'.format(tetra_list[i-2],tetra_list[i], i)
return res
else: return ''
def checkoctahedral(num):
octa_list = [i*(2*i**2+1)//3 for i in range(1, 20)]
if num in octa_list:
i = octa_list.index(num)+1
res = '* {0}과 {1} 사이의 {2}번째 정팔면체수(octahedral number)다.\n'.format(octa_list[i-2],octa_list[i], i)
return res
else: return ''
def checkpalindromic(num): #반복수 체크
res =''
palind_list = [i for i in range(1,1000) if str(i) == str(i)[::-1] ] #대칭수 확인
rep_list = [i for i in range(1,10)]+[i*11 for i in range(1,10) ]+[i*111 for i in range(1,10)]+[i*1111 for i in range(1,10)]
if num in palind_list:
i = palind_list.index(num)+1
res += '* {0}번째 대칭수(Palindromic number)다.'.format(i)
if num in rep_list:
j = rep_list.index(num)+1
res +=' 또한 {0}번째 반복수(Reptile number)다.\n'.format(j)
else:
res +='\n'
return res
def checkhasard(num): #하사드 수 체크
res = ''
hasard_ind = num//1000 + (num//100)%10 + (num//10)%10+ num%10 #자리수의 합
if num<100:
hs_sum ='{0}+{1}'.format((num//10), num%10)
elif num<1000:
hs_sum ='{0}+{1}+{2}'.format(num//100, (num//10)%10, num%10)
else:
hs_sum = '{0}+{1}+{2}+{3}'.format(num//1000, (num//100)%10, (num//10)%10, num%10)
if num%hasard_ind == 0: #하사드 수인지 여부
res += '* 하사드 수(Hasard Number)이다. 즉 자리수의 합 {0}={1}은 {2}를 나눈다. \n'.\
format(hasard_ind, hs_sum, num)
return res
def sumform(_ind, _num): #파울하버 공식을 미디어위키 Latex 표현으로 묘사
if _num == 1:
return '<math>\\frac'+'{'+f'{_ind}({_ind}+1)'+'}{'+'2}</math>'
elif _num == 2:
return '<math>\\frac'+'{'+f'{_ind}({_ind}+1)(2{_ind}+1)'+'}{'+'6}</math>'
elif _num == 3:
return '<math>\\frac'+'{'+'{'+f'[{_ind}({_ind}+1)]'+'}^{'+'2}'+'}{'+'4}</math>'
elif _num == 4:
return '<math>\\frac'+'{'+f'{_ind}({_ind}+1)(2{_ind}+1)(3{{{_ind}}}^{{2}}+3{_ind}-1)'+'}{'+'30}</math>'
elif _num ==5:
return '<math>\\frac'+'{'+'{'+f'[{_ind}({_ind}+1)]'+'}^{'+'2}'+f'(2{_ind}^2+2{_ind}+1)'+'}{'+'12}</math>'
def checksumpowers(num):
res = ''
list_sumpenta = [(i*(i+1))**2*(2*i**2+2*i+1)//12 for i in range(2,10)]
list_sumquad = [i*(i+1)*(2*i+1)*(3*i**2+3*i-1)//30 for i in range(2,15)]
list_sumsquare = [i*(i+1)*(2*i+1)//6 for i in range(2,30)]
if num in list_sumpenta:
i = list_sumpenta.index(num)+2
res +='* 1부터 {0}까지의 오제곱수의 합이다.\n'.format(i)
if num in list_sumquad:
i = list_sumquad.index(num)+2
res +='* 1부터 {0}까지의 네제곱수의 합이다.\n'.format(i)
if num in list_sumsquare:
i = list_sumsquare.index(num)+2
res +='* 1부터 {0}까지의 제곱수의 합이다.\n'.format(i)
return res
printmediawiki.py[편집 | 원본 편집]
그 다음에 직접 pywikibot을 통해 문서를 채워나가는데 필요한 스크립트인 printmediawiki.py입니다. 제목을 이상하게 지은 감이 없진 않지만 그래도 이걸 이용해서 대규모로 문서 작성이 가능합니다. python pwb.py printmediaiki
로 작성했습니다.
코드 보기
import pywikibot
import createnumarticle as cn
def shownwrite(_txt):
print(_txt, end='') #개행 없이 보여주기
return _txt
for n in range(24,100):
txt = ''
print('문서 제목 : ', end='') #문서제목 보여주기
txt_title =shownwrite("{0}-{1}".format(n*10, n*10+9))
txt +=shownwrite("{{"+"좌우이동|왼쪽={0}-{1}|가운데={2}-{3}|오른쪽={4}-{5}".\
format(n*10-10, n*10-1, n*10, n*10+9, n*10+10, n*10+19)+"}}\n")
txt +=shownwrite("[[자연수]] {0}부터 {1}까지의 숫자에 관한 문서이다.\n".format(n*10, n*10+9))
txt +=shownwrite('\n')
for i in range(0,10):
txt +=shownwrite('\n== {0} =='.format(10*n+i))
txt +=shownwrite('\n')
if 10*n+i == 666: #666문서는 이미 있음. 따라서 넘겨주기 만들지 않고 본문으로 작성!
txt +=shownwrite('{'+'{'+'본문|666'+'}'+'}\n')
txt +=shownwrite(cn.checkprime(10*n+i))
txt +=shownwrite(cn.checkpower(10*n+i))
txt +=shownwrite(cn.checkpolygon(10*n+i))
txt +=shownwrite(cn.checkfibonacci(10*n+i))
txt +=shownwrite(cn.checkfactorial(10*n+i))
txt +=shownwrite(cn.checktetrahedral(10*n+i))
txt +=shownwrite(cn.checkoctahedral(10*n+i))
txt +=shownwrite(cn.checkpalindromic(10*n+i))
txt +=shownwrite(cn.checkhasard(10*n+i))
txt +=shownwrite(cn.checksumpowers(10*n+i))
txt +=shownwrite('[[분류:수]]\n')
print('길이 : ', len(txt))
#위키/목록 텍스트 작성
site = pywikibot.Site()
print('사이트 :', site)
page = pywikibot.Page(site, txt_title)
print('페이지 :', page)
page.text = txt
page.save('ko:숫자 문서 작성!')
print('문서 {0} 작성 완료!\n'.format(txt_title))
print('넘겨주기 작성 시작!')
for i in range(0,10):
txt_r_title = str(n*10+i)
if txt_r_title != '666': # 666문서는 이미 작성되어 있으므로 새로 만들기 하지 않음.
txt_r = shownwrite('#넘겨주기 [[{0}-{1}#{2}]]\n'.format(n*10, n*10+9, n*10+i))
page_r = pywikibot.Page(site, txt_r_title)
page_r.text = txt_r
page_r.save('넘겨주기 작성!')
print('넘겨주기도 모두 작성 완료!\n')