(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')