用户:ColorfulGalaxy/Programs
外观
xdi8tools.py
Unfortunately, I still have no idea how to obtain the entire Shidinn dictionary database (including ).
from xdict import dict_xdi8
# dict_xdi8 is a Shidinn dictionary e.g. { '一':'NV','二':'42' }
b1i45=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,(0),0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,44,39,42,22,23,38,26,41,0,0,0,0,0,0,0,
0,35,27,0,11,34,25,0,14,0,0,0,37,0,15,0,
0,0,0,0,40,0,43,0,0,36,0,0,0,0,0,0,
0,31,1,28,17,33,29,19,21,45,5,20,16,3,9,32,
2,6,13,12,18,30,24,4,7,8,10,0,0,0,0,0,0]+65535*[0]
b1i90000=[(((i-1)%9+1) * (10**((i-1)//9))if i!=0 else 0) for i in b1i45]
xdi8hanzi=list(dict_xdi8.keys())
def b1i45encode(word):
return ' '.join((str(b1i45[ord(q)]) if len(str(b1i45[ord(q)]))>=2 else '0'+str(b1i45[ord(q)])) for q in word)
def b1i90000sum(word):
return sum([b1i90000[ord(q)] for q in word])
def translate_into_xdi8(word,sep=''):
return sep.join((dict_xdi8[q] if (q in xdi8hanzi) else q) for q in word)
Infinite song list tools
These programs might not be run regularly. This is because the input is so large that it might not fit on "Try it online". A seperate offline engine for Python would be needed.
The chart will be placed in User:ColorfulGalaxy/ / . (citation needed)
Convert json to python dictionary
Takes Module:Songlist-brief.json as input.
import json
with open("songlist-brief-04157a.json","r",encoding="utf-8") as f:
data=json.load(f)
with open("songlist_brief_04157a.py","w",encoding="utf-8") as g:
print('songlist=',data,file=g)
print('done')
Convert python dictionary to wiki chart
New columns added. You can help us expand it.
from songlist_brief_04157a import songlist
import sys
import os.path
from xdi8tools import *
songnumbers=list(songlist['songlist'].keys())
# xdi8aho translation exception
xdi8exlist={
'0':'He f8 k2 Huo k2 miLh',
'239':'jbia rA xue',
'1028':'x8 x8 diVb xd8', # Questionable
'1520':'ti2 dDE l3 v8B',
'1751':'6li8 ju6 k2 42',
}
xdi8exlistk=list(xdi8exlist.keys())
def xdi8titleof(num1,sep1=''):
return (xdi8exlist[num1].replace(' ','') if sep1=='' else xdi8exlist[num1]) if num1 in xdi8exlistk else translate_into_xdi8(songlist['songlist'][songnumbers[p]]['song']['name'],sep=sep1)
timelist={
'0':'0'
}
timelistk=list(timelist.keys())
keylist={
'0':'0'
}
keylistk=list(keylist.keys())
keymodlist={
'0':'0'
}
keymodlistk=list(keymodlist.keys())
titleclasslist={
'0':1,
'1':6,
'2':6,
'4':5,
'10':6,
'11':2,
'12':5,
'12A':5,
'18':5,
'21':6,
'31':'5<ref>Questionable. The two syllables in the title appear in the song, but they are separated by just a whitespace, putting the song somewhere between group 5 and group 6.</ref>',
'33':6,
'41':5,
'44':3,
'50':6, # Questionable
'59':6,
'75':1,
'85':5,
'86':5,
'89':6,
'92':3,
'97':6,
'98':6,
'103':6,
'115':1, # not confirmed
'120':5,
'160':5,
'167':5,
'208':6,
'236':6,
'244':6,
'250':5,
'255':5,
'256':6,
'273':6,
'275':5,
'312':1,
'315':6,
'326':2,
'328':4,
'327':5,
'335':3,
'342':5,
'364':1,
'373':6,
'379':5, # 2026-02-09 has completely different lyrics
'385':6,
'400':5,
'402':5,
'406':6,
'411':3,
'418':6,
'425':6,
'428':6,
'448':2,
'452':3,
'480':5,
'489':3,
'508':6,
'521':6,
'523':6,
'532':5,
'549':6,
'550':5,
'555':6,
'592':6,
'606':6,
'618':5,
'625':'6<ref>Case insensitive</ref>',
'626':6,
'630':3,
'643':5,
'643A':1, # TODO: Allow alternatives to be displayed on sortable chart
'650':6,
'672':5,
'676':3,
'730':6,
'737':6,
'741':5,
'769':6,
'782':6,
'784':6,
'789':6,
'810':5,
'840':6,
'850':4,
'866':6,
'889':3,
'893':'6<ref>This song has two different titles. If you consider the English title, it is in Group 3 instead.</ref>',
'895':5,
'896':6,
'899':6,
'908':5,
'914':6,
'931':6,
'968':6,
'978':5,
'1011':5,
'1040':6,
'1046':3,
'1081':6,
'1117':'2<ref>Mandarin version is in Group 5 (?)</ref>',
'1134':6,
'1138':6,
'1140':5,
'1160':5, # appears very briefly in the second stanza and means something very different
'1194':5,
'1216':5,
'1266':3,
'1282':6,
'1315':6,
'1317':6,
'1331':6,
'1351':5,
'1354':6,
'1364':6,
'1390':3,
'1396':5,
'1441':6,
'1446':6,
'1456':3,
'1479':3,
'1521':3,
'1523':5,
'1527':5,
'1528':6,
'1554':6,
'1568':2,
'1582':6,
'1592':6,
'1616':6,
'1660':3,
'1666':5,
'1672':6,
'1736':6,
'1780':5,
'1782':6,
'1787':3,
'1787A':5,
'1812':5,
'1897':5,
'1903':3,
'1917':6,
'1938':6,
'1956':2,
'1983':3,
'2011':2,
'2036':6,
}
titleclasslistk=list(titleclasslist.keys())
# 30 day song challenge (ColorfulGalaxy's opinion)
# One song may have multiple "days", while not all songs will have a "day".
tdsclist={
'255':'23',
'737':'08',
'810':'08',
}
tdsclistk=list(tdsclist.keys())
saltdatelist={
'1407':'2025-05-20 (?)',
'810':'2025-07-18',
'247':'2025-07-20 (?)',
'1217':'2025-07-22 (?)',
'313':'2025-07-25 (?)',
'236':'2025-07-26',
'2011':'2025-08-01',
'418':'2025-08-05',
'1521':'2025-08-06',
'625':'2025-08-07',
'672':'2025-08-08',
'1011':'2025-08-09',
'1134':'2025-08-10',
'1897':'2025-08-12',
'1983':'2025-08-13',
'275':'2025-08-14',
'33':'2025-08-17',
'1216':'2025-08-20',
'1660':'2025-08-22',
'1046':'2025-08-23',
'10':'2025-08-26',
'400':'2025-08-27',
'256':'2025-08-30',
'914':'2025-08-31',
'41':'2025-09-03',
'1528':'2025-09-07',
'866':'2025-09-08',
'1554':'2025-09-09',
'335':'2025-09-12',
'1282':'2025-09-13',
'1117':'2025-09-14 (?)',
'737':'2025-09-15',
'1317':'2025-09-20',
'160':'2025-09-21',
'1364':'2025-09-22',
'315':'2025-09-24',
'98':'2025-09-26',
'208':'2025-09-27',
'18':'2025-10-02',
'1582':'2025-10-05',
'630':'2025-10-08',
'618':'2025-10-09 (?)',
'1616':'2025-10-13',
'255':'2025-10-14',
'741':'2025-10-15',
'480':'2025-10-17',
'489':'2025-10-19',
'1672':'2025-10-20',
'1456':'2025-10-21',
'978':'2025-10-23',
'273':'2025-10-25',
'364':'2025-10-26',
'643':'2025-10-27 (A)',
'4':'2025-10-30',
'385':'2025-10-31',
'784':'2025-11-04',
'402':'2025-11-05',
'1331':'2025-11-06',
'1266':'2024-09-25 (?)<br>2025-11-07',
'508':'2025-11-09',
'89':'2025-11-10',
'373':'2025-11-11',
'606':'2025-11-12',
'895':'2025-11-15',
'1351':'2025-11-17',
'931':'2025-11-18',
'31':'2025-11-19',
'21':'2025-11-20',
'549':'2025-11-24',
'411':'2025-11-26',
'550':'2025-07-17 (A?)<br>2025-11-28',
'626':'2025-11-30',
'1354':'2025-12-02',
'1194':'2025-12-06',
'1446':'2025-12-11',
'896':'2025-12-13',
'782':'2025-12-16',
'1782':'2025-12-22',
'244':'2025-12-23',
'1780':'2025-12-24',
'97':'2025-12-25',
'968':'2025-12-26',
'342':'2025-12-27',
'1903':'2025-12-28',
'1527':'2025-12-29',
'2':'2026-01-04',
'1040':'2026-01-05',
'1479':'2026-01-09',
'523':'2026-01-10',
'250':'2026-01-13',
'1441':'2026-01-14',
'1956':'2026-01-15',
'1787':'2026-01-16 (A)',
'326':'2026-01-17',
'1160':'2026-01-18',
'428':'2025-10-11<br>2026-01-19',
'12':'2025-12-12 (A)<br>2026-01-20 (A)',
'1592':'2026-01-22',
'521':'2026-01-24',
'676':'2026-01-26',
'92':'2025-10-04<br>2026-01-27',
'44':'2026-01-28', #Possibly an alternative
'1140':'2026-01-29',
'1666':'2026-01-30',
'406':'2026-02-01',
'312':'2026-02-02',
'1390':'2026-02-06',
'327':'2026-02-11',
'85':'2025-11-22<br>2026-02-13',
'452':'2026-02-14',
'889':'2026-02-16',
'103':'2024-09-27 (?)<br>2026-02-18',
'1812':'2025-09-02<br>2026-02-19',
'425':'2026-02-20',
'1315':'2025-09-05<br>2026-02-21',
'840':'2025-10-29<br>2026-02-23',
'1917':'2026-02-25',
'120':'2026-02-26',
'1138':'2025-12-08<br>2026-02-27',
'2036':'2026-02-28',
'908':'2026-03-01',
'115':'2026-03-03',
'50':'2026-03-04',
'1523':'2026-03-05',
'75':'2025-08-29<br>2026-03-06',
'1396':'2025-07-19 (stub?)<br>2026-03-07',
'1938':'2026-03-08',
'769':'2026-03-11',
'532':'2026-03-12',
'1736':'2025-12-19 (?)<br>2026-03-14 (?)',
'167':'2026-03-15',
'86':'2026-03-16',
'592':'2025-11-08<br>2026-03-17',
'730':'2026-02-15<br>2026-03-18',
'59':'2026-03-20',
'1081':'2026-03-21',
'1568':'2026-03-22',
'328':'2026-03-24',
'789':'2026-03-25',
}
saltdatelistk=list(saltdatelist.keys())
# 与之 旋律/和声/节奏/曲风 相近的音游曲目
# Not all songs will be paired with a rhythm game soundtrack
rhythmgamesonglist={
'555':'Kingdom War (RS)',
'650':'Komorebi (ADOFAI)',
'899':'Temple Fair (RS)',
'903':'Tropical Tides (RS)',
}
rhythmgamesonglistk=list(rhythmgamesonglist.keys())
f=open("songlist-wikifile.txt","w",encoding="utf-8")
f.write("\'\'\'Lucas Song List\'\'\', also called the Infinite Song List, is a system organized by Lucas that maps popular songs to integers in a somewhat mathematical manner. \n")
f.write("The current database version is 04157a. The list below may contain errors, mainly because the Shidinn translator (programmed manually by ColorfulGalaxy) is unable to handle homograph.\n\n")
f.write("{| class=\"wikitable sortable\"\n");
f.write("! Number !! Song title !! Singers !! Title in Shidinn !!data-sort-type="text"| b1i45 index !! Shidinn gematria !! Time signature !! Key signature !! Key modulation (half-steps) !! [http://puzzling.stackexchange.com/questions/106137 Title category] !! Day # in<br>original<br>30-day song<br>challenge !! Salt song guess date !! 与之 旋律/和声/节奏/曲风 相近的音游曲目<ref>The contents of this column is subject to change. It is not as constant as the original Infinite Song List. It should be viewed as a permanently ongoing lookalike contest for rhythm game soundtracks.</ref>\n");
for p in range(len(songnumbers)):
f.write("|-\n")
f.write("| "+songnumbers[p]+" || ")
f.write(songlist['songlist'][songnumbers[p]]['song']['name']+" || "+','.join(songlist['songlist'][songnumbers[p]]['song']['singers'])+" || ")
f.write(xdi8titleof(songnumbers[p],sep1=' ')+" || ")
f.write(b1i45encode(xdi8titleof(songnumbers[p]))[0:17]+" || ")
f.write(str(b1i90000sum(xdi8titleof(songnumbers[p])))+" || ")
f.write((timelist[songnumbers[p]]if songnumbers[p] in timelistk else '')+" || ");
f.write((keylist[songnumbers[p]]if songnumbers[p] in keylistk else '')+" || ");
f.write((keymodlist[songnumbers[p]]if songnumbers[p] in keymodlistk else '')+" || ");
f.write(str(titleclasslist[songnumbers[p]]if songnumbers[p] in titleclasslistk else '')+" || ");
f.write((tdsclist[songnumbers[p]]if songnumbers[p] in tdsclistk else '')+" || ");
f.write((saltdatelist[songnumbers[p]]if songnumbers[p] in saltdatelistk else '')+" || ");
f.write((rhythmgamesonglist[songnumbers[p]]if songnumbers[p] in rhythmgamesonglistk else '')+"\n");
# TODO
f.write("|}")
f.close()
Numberblocks tools
LifeViewer RLE to UIUA Mosaic
#comment
import sys
# REMOVE LIFEVIEWER RLE HEADER
colorblock="Zzt ,COR ,COO ,COY ,COG ,COC ,COB ,COV ,COM ,COL ,COT ,COJ ,COD ,COK ,COI ,COH ,Czt ,CTA ,CTO ,CTY ,CTG ,CTC ,CTB ,CTV ,CTM ,CTL ,CTT ,CTJ ,CTD ,CTK ,CTI ,CTH ,Tzt ,TTA ,TTO ,TTY ,TTG ,TTC ,TTB ,TTV ,TTM ,TTL ,TTT ,TTJ ,TTD ,TTK ,TTI ,TTH ,Lzt ,LTA ,LTO ,LTY ,LTG ,LTC ,LTB ,LTV ,LTM ,LTL ,LTT ,LTJ ,LTD ,LTK ,LTI ,LTH ,Qzt ,QTA ,QTO ,QTY ,QTG ,QTC ,QTB ,QTV ,QTM ,QTL ,QTT ,QTJ ,QTD ,QTK ,QTI ,QTH ".split(',') # Add more to the list
c='0'
cell=''
n=0
def sum(cl):
sm=0
for i in cell:
if 'A'<=i<='Z':
sm+=ord(i)-64
elif 'p'<=i<='z':
sm+=24*(ord(i)-111)
elif i=='o':
sm+=1
elif i in 'b.':
pass
return sm
sys.stdout.write("red join fill 0[red rows join[")
while(len(c)>0 and c!="!"):
c=sys.stdin.read(1)
if '0'<=c<='9':
cell=''
n=n*10+int(c)
elif 'A'<=c<='X' or (c in 'ob.'):
cell+=c
if n==0:
n=1
sys.stdout.write(n*colorblock[sum(c)])
cell=''
n=0
elif 'p'<=c<='z':
cell+=c
elif c=='$':
if n==0:
n=1
sys.stdout.write(n*"Zzt] red rows join[")
cell=''
n=0
sys.stdout.write("]]")
Tetradecimal numberblocks template (in UIUA)
#New update: added support for forties through sixties Sz ← 32 A ← self tab mul self div+1 ran Sz T ← tab mul flo bacdiv1+1 ran Sz self div+1 ran Sz L ← tab mul self div+1 ran Sz flo bacdiv1+1 ran Sz AT ← -T1 AL ← -L1 AQ ← mul AT AL Q ← -AQ1 Z ← self tab mul self - ran Sz G ← tab mul div on ran Sz self div+1 ran Sz Zzt ← tra joi joi cou Z Z Z Z COR ← tra joi joi cou A Z Z A COO ← tra joi joi cou A div2A Z A COY ← tra joi joi cou A A Z A COG ← tra joi joi cou Z A Z A COC ← tra joi joi cou Z A A A COB ← tra joi joi cou Z Z A A COV ← tra joi joi cou div2A Z A A COM ← tra joi joi cou A Z A A COL ← tra joi joi cou div4*3A div4*3A div4*3A A COI ← tra joi joi cou div2A div2A div2A A COH ← tra joi joi cou div4A div4A div4A A COT ← tra joi joi cou div2A div4A Z A COJ ← tra joi joi cou div2G div2G div2G A COD ← tra joi joi cou Z div2A A A COK ← tra joi joi cou A A G A CTA ← tra joi joi cou A A A A LTA ← tra joi joi cou A AL AL A TTA ← tra joi joi cou A AT AT A QTA ← tra joi joi cou A AQ AQ A CTO ← tra joi joi cou A div4*3A div4A A LTO ← tra joi joi cou A +div2A div4AL div4AL A TTO ← tra joi joi cou A +div2A div4AT div4AT A QTO ← tra joi joi cou A +div2A div4AQ div4AQ A CTY ← tra joi joi cou A A div2A A LTY ← tra joi joi cou A -div4L A div2A A TTY ← tra joi joi cou A -div4T A div2A A QTY ← tra joi joi cou A -div4Q A div2A A CTG ← tra joi joi cou div2A A div2A A LTG ← tra joi joi cou div2A -div4L A div2A A TTG ← tra joi joi cou div2A -div4T A div2A A QTG ← tra joi joi cou div2A -div4Q A div2A A CTC ← tra joi joi cou div2A A A A LTC ← tra joi joi cou div2A -div4L A A A TTC ← tra joi joi cou div2A -div4T A A A QTC ← tra joi joi cou div2A -div4Q A A A CTB ← tra joi joi cou div2A div2A A A LTB ← tra joi joi cou div2A div2A -div4L A A TTB ← tra joi joi cou div2A div2A -div4T A A QTB ← tra joi joi cou div2A div2A -div4Q A A # Silver = 11 # Gold = 13 # List above is incomplete # insert output of above python code here
Factorial base calculator
, 。 。
def carry(n:list): for i in range(len(n)-1,1,-1): n[i-1]+=n[i]//i n[i]=n[i]%i return n def add(n1:list,n2:list): while len(n1)<len(n2): n1.append(0) for i in range(len(n2)): n1[i]+=n2[i] return carry(n1) pi=[0,0,0] fa=2 for b in range(3,73,2): fa*=(b//2+1)*(b-1) add(pi,[0]*b+[fa]) print(pi) print() e=[0,1,0] for b in range(1,15): add(e,[0]*b+[1]) print(e)
Older programs
Chart generator (August 2025 - a new version using custom xdi8tools module should be uploaded)
import sys
import os.path
import pypinyin
import xdi8string # all the characters spaced out translated into shidinn
f=open("wikifile.txt","w",encoding="utf-8")
characters=[chr(i) for i in range(0x4e00,0xa000)]
plaintext=' '.join(chr(n) for n in range(0x4e00,0xa000))
ciphertext=xdi8string.output
b1i45=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,(0),0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,44,39,42,22,23,38,26,41,0,0,0,0,0,0,0,
0,35,27,0,11,34,25,0,14,0,0,0,37,0,15,0,
0,0,0,0,40,0,43,0,0,36,0,0,0,0,0,0,
0,31,1,28,17,33,29,19,21,45,5,20,16,3,9,32,
2,6,13,12,18,30,24,4,7,8,10,0,0,0,0,0,0]
b1i90000=[(((i-1)%9+1) * (10**((i-1)//9))if i!=0 else 0) for i in b1i45]
def b1i45encode(word):
return ' '.join((str(b1i45[ord(q)]) if len(str(b1i45[ord(q)]))>=2 else '0'+str(b1i45[ord(q)])) for q in word)
def b1i90000sum(word):
return sum([b1i90000[ord(q)] for q in word])
plain=plaintext.split()
cipher=ciphertext.split()
maxlength=0
maxlench=[]
f.write("Do not simply rely on this chart to translate, as this chart did not handle [[talk:希顶日本语#注意多音字|homograph]] properly. The calculation may be incorrect. If so, please fix it.")
f.write("{| class=\"wikitable sortable\"\n");
f.write("! Character !! Unicode decimal !! Stroke count !! han4 yu3 pin1 yin1 !! xdi8 aho !! [[b1i45密码|b1i45]] !! xdi8 aho letter count !! [[希顶解经|Numeral sum]] !! Stress pattern !! Notes\n")
for p in range(len(plain)):
if(plain[p]!=cipher[p]):
f.write("|-\n");
f.write("| "+plain[p]+" || ")
f.write(str(ord(plain[p])))
f.write(" || || ")
f.write(pypinyin.pinyin(characters[p],style=pypinyin.Style.TONE3,neutral_tone_with_five=True)[0][0])
f.write(" || "+cipher[p])
f.write(" || "+b1i45encode(cipher[p]))
f.write(" || "+str(len(cipher[p])))
f.write(" || "+str(b1i90000sum(cipher[p])) + "\n")
if(maxlength<len(cipher[p])):
maxlench=[p]
maxlength=len(cipher[p])
elif(maxlength<=len(cipher[p])):
maxlench+=[p]
f.write("|}")
print(maxlench,maxlength,len(maxlench))
f.close();