ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccllccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcccclllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllcclclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllcllllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllclllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllcllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcclllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllllcccccccccc:cclccclcccllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllcc::;:..,;;ccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcllllllllllllllllllllllllllllllllllllllllllllllllllllllllc,..';::::,;''',,,,;:clllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclllllcclllllllllllllllllllllllllllllllllllllllllllllllllll::c:,,,;;;;':::;.':,;:;;,,,;:cllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcclcclcllllllllllllllllllllllllllllllllllllllllllllllllllllc:clllll::clc,;,,,,;'..:::::c;':;;::::clllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccclllclllcllllllllllclllllllllllllllllllllllllllllllllllc:clllllllllc::,:;;,,,,.'....,:,,::;''.. .,:;:clllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclccclcccllclllllllllllllllllllllllllllllllllllllllllllllllccllllllllllllll;;clllll,lll;'.'..',;',,;.,.;,:;'..;::cllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllcccllllllllllllllllllllllllllllllllllllllllllclllllllllllllllllllc::lll;lllc:;,...,;;',' ....;,..',,:;;;;,;cllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclcccccccccccccccllllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllc::c,:;;::::''. ';:,,.,,;...,''::,:cc,';,,;;;;:clllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccccccccccccccclccclllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllc',:lllll,cc;...cl.c;.,;.c:.,;;,,;,,ccc;;:.;:;;;,,,;cllllllcclllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllll::clll;l;''.'';.,;c;;:.;;lcccl;'.,;;;;,.,;:;;;:ccllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccllllllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllc::l';.::c.,, .;,::::.'lllc;;'.,','',:lllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllll; ..,,::...,.;:;,.. ',,,;::cllclllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllll'',,,;,:' ':.'::'.'clllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcllllllllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllll;c.,;:c:,.;:c'.,;c:clllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccccccclclclclllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllll,c:..,,:l.cc,';.;c;:lllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclccllccclclllllllllllllllllllllllllllllllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllc:l,'..;;c.;,cc;:';c:lllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcccccllccccccccllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllc:'.':,.c: .cccllc'';lllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccclcllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllll;.:cl:lc.;.:.;lllll.'lllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllccccccccccccccllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllll:,':lcl:c' ;l,;llc,,;lllloolllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllllll:l:.;::c:' ;:c;,;;:o;looolllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccccclllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllllllll;cc,...,cl.cc:,,.,c:,looooooolllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccclllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll;cc,'.';:o.:;,:,,',c;looooolooolooooollollllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccccclllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooo;l,':c;;c, .cl:llc,;;looooooooooooooollollllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllclccllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllloooloooll.',;,',,.' .',;:::;' coooooooooooooooooooolloolooooolooool
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllolollllcc:. .,.,;lo;' ,',llllc' .:loooooooooooooooooooooooooooooooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllclllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllool:;,,,;::l''';';,,:. .c;.loo,.'colcclooooooooooooooooooooooooooooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllll:,',::,,,',,.;:::loo'l'.c';l;, ',;'.:,;l;:oooolcccoooooooooooooooooooooooooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllc;,',',;, . ...',,,;',;,,;'c;..',.cl :l:c..'::'.;ccccc::..:lllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllll,.'',.'''. ......,,...'.....'..'....... ........'. .oooool;.,:c::ooooooooooooooooooolll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllccccllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllll;:lc:';;;'...,';;;,,;.',::;''.. ......c;, ,,cl:cc'',.'';cc,.;..,;;.,::cllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllccccllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllll,.';..looool'cc:;,;;'.,:llll:c;.,.';.. . ;:;oooc,''lc,...,;cloocccoolcclooooooooooooooo
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcllllllllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllll;..,..clooool,cllooooocc:;''''...;;'...... . .,...'.. ,cc'':';:lococ:oddool::loddooodooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllll:.....;looooool,coooooooooooooooc. ''''.;;.. . ''.,''. ,;,.',':c:',ll:ddolllo:lccloodddddoo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccccccclcclclcclllllllllllllllllllllllllllllllllllllllllllllclllllllllllllllllllllllllllllllllollllllllllllc:'.''..coooooooll;coooooooooooooooo,;.,;:c';;. '. ... . ,,..,'. .'....;cloooo:odlc:cloooooo
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcllcllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllolllollllll,'.....:,looooolooo:;oooooooooooooooo,ol. ',l:., ';cc. ..,'. ..'.',.cc:c.:;..';;,.::,,,;;',,;;;
ccccccccccccccccccccccccccccccccccccccccccccccccccclccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllloooooooooc:'. ..',cl,loolloooooc,oooooooooooooood'llc. ..,oo :d;..; .c:.;:'..;;;;::,;.::::',,::';:::::,lolcl
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloooooooooo:c;..;,;ccol,clloooooool,oooooooooooddodd'ol'...';;: .',o;,:'.;,,odccdddolcc;';:;;c:c,,';cccc:'...',
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloololoooooooooooooooolll::.,':ooool::oooooooooo;looooooooooodddo.:..:cc..o; :o;ldl'. :dd:cdddddddo:dddlccccc'......,;;,c:
cccccccccccccccccccccccccccccccccccccccccccccccccccccccclllccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooloooooooooooooooooooooollllcl:;::loollol;oooooooooo;loooooodoooodddl 'lloldd;.. '..ooc..:: ,dd::dddddddl;dddddddddooo;'':oddood
ccccccccccccccccccccccccccccccccccccccccccccccccccclcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloooloooooooooooooooooooooooooooooooolllllollocolclooool,ooolllccc:';loooooddddddddl..cloldo;c. .c;.;:oo;..;ddc:dddddddo;dddddddddoccoo:ddooodd
cccccccccccccccccccccccccccccccccccclcllclcccclclccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllolloooooooooooooooooooooooooooooooooooooolllllollooolcocoooooo,;c:cllloooolllllododddddddc'o..clc:o:. .,cc.,:''cc,ddc:dddddddo;ddddddo:.,oddo;ooodddd
ccccccccccccccccccccccccccccccclllllllllcllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllollollollloloooooooooooooooooooooooooooooooooooooooooooolllllolloooooolocoooolc;,cooooooooooooodollllodddd:,dd'..,;.,; 'l:c:..;odl'ddl:oooooooolododo:.;odoooo;odddddd
ccccccccccccccccccccccccclccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooollooooooooooooooooooooooooooooooooooooooooooooooolllllolloooooooolocooolclcoooooooooooooooodddddollcc''cc,. .,:oc ,d:',,,.cdo.dooodddddddddddoocodddodddo;ddddddd
ccccccccccccccccccccclllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloloooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooolllllollooooooooooollooococooooooooooooooooodddddddddd,;o,..;.'l;; .,cd:c:c''o.oddddddddddddoldddodddddddd:ddddddo
ccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllolloooollllolllllooolollooooolooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooollllloloooooooooooooololococooooooooooooodddoddddddddddd,;.';l:l;.o: :o;odddc'..ddddddddddooldddddodddddddd;ooooood
llllllllllllllllllllllllllllllllllllllllllllllllllllllloolooloolooooooooolooooooooooolooooooooooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooollllloloooooooooooooooooll:llloooooddodddodddddddddddddddd..lololddl.. '..odddddd' oddddddoodddddddddoodddddoooddddddd
llllllllllllllllllllllllllllllllllllllllllllllllllllloooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooololllolooooooooooooooooooooloooodddddddddddddddddddddddddddo..'oloodo:l. .l:.cdddl'..oddddooddddddddddddooddoodddddddddd
llllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooololloolooooooooooooddoddoddddddddddddddddddddddddddddddddddood.o;.,loc:o;. .ldo.,o,.'o'ldooddddddddddddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooloooooooooooddddddddddddddddddddddddddddddddddddddddoodddd.ddc .'c;'cl ,l:lo. ':dd,cddddddxxdddddddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllllolloooolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooooooodododddddddddddddddddddddddddddddddddddddddddddoodddddd.dxo;...'dxo ,xd,.,,.;dd;:xxxxxxxxxxdddddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooolloooooooddddddddddddddddddddddddddddddddddddddddddddddoodddddxxxo.xd;..,.c::l ,;.co,;:..d::xxxxxxxxxxxxxddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodooooooooooooooooooooolloooooooddddddddddddddddddddddddddddddddddddddddddddddoodddddxxxxxl'o..,cl:.:o, :dc:dxoc'.';xxxxxxxxxxxxdddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddooooooodoooooloooooodddddddddddddddddddddddddddddddddddddddddddddddooddddddxxxxxxxc..cooldxd.', ..,lxxxxxo; .dxxxxxxxxxxxxddddddddddddddddddddd
llllllllllllllllllllllllllllllllllllooolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddoddoodddddddddddddddddddooooloooooddddddddddddddddddddddddddddddddddddddddddddddddodddddddddxxxxxxx; :xoolxxxc'. .;.;xxxxxxc..dxxxxxxxxxdddddddddddddddddddddddd
llllllllllllllllllllllllllllllooloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddddddddddddooollooooddddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddxxxxxd;;,':olxo:ld' 'xx;'oxxl'.c.xxxxxxxxdddddddddddddddddddddddddd
lllllllllllllllllllllllollolloooloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodoooddoooddddddddddddddddddddddddddddddooolloooodddddddddddddddddddddddddddddddddddddddddddddddoooddddddddddddddxddxxx,cdc.'cc:o;., .;ldl.;,,;dd.dxxxxxxddxdddddddddddddddddddddddd
llllllllllllllllllllloollooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddoddddddddddddddddddddddddddddooolloooddddddddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddxxxxxxxx':lo:...''ldl ,xo;;...,lll.dxxxxxxxxxxxdddddddddddddddddddddd
lllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooododoooddddddddddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddxxxxxxxxxd.:oo:,. ,:dxl ,xo'',.'.;lc.oxxxxxxxxxxxxxxxdddddddddddddddddd
lllllllllllllllllloolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddoddddddddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddxxdxxxxxxdddd.cx:...,.:c,: .';ol:':c',d lxxxxxxxxxxxxxxxxxdddddxxxddddddxx
llllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddoooooooodddddodddddddddddddddddddoooolooodddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddxxdxxxddddxxd c''cd,lo.,c. :l:cx,do:'. cxxxxxxxxxxxxxxxxxxxdxxxxxxxxdxxxx
lllllllllllllloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddooooooooddooddddddddddddddddddddddooccloooddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddxxxxxddddxxxxc .:l:c,:;;,.. ..,llc;ccc:. ,dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
llllllollllloolloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddddooolccloddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddxxxxddddxxxolll' .c;''.;ll:;. .:.,locoool' .:loxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
llllllloollloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddxxxxddddxdlllloxxo:.;.cl::,o:ll. .;oc.oxxd:.';;xxdllldxxxxxxxxxxxxxxxxxxxxxxxxxx
llloooooooollloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddddddddddddddoooloooddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddxxxddddolllc,:l:;c;;:'xd..;l:'l;,: .,,:;.;:,,cxc,xxxxxxolloxxxxxxxxxxxxxxxxxxxxxxx
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddddddddddddddooooooodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddxdocc,..':cc:,c:oxxlx;'oxx;..:;':xo ,xo:;....cooc'xxxxxxxxxdllldxxxxxxxxxxxxxxxxxxx
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddolccc,:,',,;: .. ...',':,';..',;,...;llcl ,xx:,;,;..';;.oododc,clccc:..codddddddddddddddd
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddoooooooodddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddd;.;,;'' ...... ',,.';c,cc:,..;.... .... ....''..'. c .'::;.':lccl:l;dolccodddddddddddd
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddddddddddddddddddoooooooddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddd::lc;.lddolc::,.',;:;;c,ccccc.'.,;..,:',' .. 'c:;odo;. ...:;.,,..'coo:ld;ddddoccccddddddddd
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodooddddddddddddddddddddoooooooodddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddddo' .;.'dddxxxxxd::dddoc:,;,.',, .;lc,, .. .,,....',. ,:;'oc;,ll;oxx:xxxxdooccllldxxxxx
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddoodddoddddddddddddddddddooooooooddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddddddddddo,.....cddddxxxxxxl;dxxxxxxxxxxxd; ,,'.'.:;,'. ....,:',,,,. .,,:,,,...';lo:xdoodxxolxxxolloxx
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddodddddoddddddddddddddddddlooodooddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddddddddddcc. '. ,ddddxxxxxxxxo;dxxxxxxxxxxxxx...xxccc,o:.. c; ...;co;. .;:,. ... .:dxxxxdcxxxxdl;,o
Pyscn tree-sitter analysis cover Pyscn is a code quality analyzer for Python built by DaisukeYoda at ludo-technologies. It finds dead code, code clones, coupling issues, and complexity hotspots. It’s written in Go, uses tree-sitter for parsing, and processes over 100,000 lines per second.
I’ve been studying its internals and the engineering decisions are worth writing about: how it detects dead code through control flow analysis, finds duplicated code across clone types 1-4 with LSH acceleration, and integrates with AI coding assistants via MCP.
Why Go + tree-sitter# Python has excellent AST modules (ast, astroid), but they’re slow for large codebases. Parsing in Python means the analysis tool is bottlenecked by the interpreter’s speed. Go gives native performance while tree-sitter provides production-grade Python parsing without writing a custom grammar.
tree-sitter is a parser generator used by editors like Neovim, Helix, and Zed. Its Go binding (go-tree-sitter) lets you parse Python source files into concrete syntax trees, then walk those trees with Go’s speed.
The tradeoff: tree-sitter produces CSTs (concrete syntax trees), not ASTs. You get every token including whitespace and punctuation. This means more node types to handle, but it also means you can reconstruct exact source locations — useful for reporting the exact lines of dead code.
Dead Code via Control Flow Graphs# Most dead code detectors look for unused functions or unreachable imports. Pyscn goes deeper by building a Control Flow Graph for each function and finding code that’s unreachable through any execution path.
The CFG construction works like this:
Parse the function body with tree-sitterCreate nodes for each statement or expressionAdd edges for sequential flow and branching (if/elif/else, try/except, loops)Mark exit points (return, raise, break, continue)Walk from entry to find all reachable nodesReport any node that wasn’t reachedThe key insight is handling exhaustive branches. If every branch of an if/elif/else chain ends with a return or raise, then code after the chain is unreachable:
def process (status):
if status == "active" :
return handle_active()
elif status == "pending" :
return handle_pending()
else :
raise ValueError (f "Unknown status: { status} " )
# This code is dead — all branches above exit the function
log_completion() # pyscn catches this
Simple dead code detectors miss this because they don’t track control flow through branches. Pyscn’s CFG analysis handles nested branches, early returns inside loops, and try/except/finally blocks.
Clone Detection: Types 1-4# Code duplication isn’t binary. Pyscn classifies clones into four types:
Type Definition Example Type 1 Identical except whitespace/comments Copy-pasted verbatim Type 2 Identical structure, different identifiers/literals Renamed variables Type 3 Similar structure with small modifications Added/removed a line Type 4 Same logic, different syntax List comp vs. for loop
Types 1-2 are detected by normalizing the AST (stripping identifiers, replacing literals with type markers) and hashing the result. Identical hashes mean identical structure.
Type 3 detection uses a similarity threshold on the normalized token sequences. This is where it gets expensive — naive pairwise comparison is O(n^2) in the number of code blocks.
Pyscn uses Locality-Sensitive Hashing (LSH) to accelerate this. Instead of comparing every pair of code blocks, it hashes each block into multiple buckets using MinHash signatures. Blocks that land in the same bucket are likely similar. This reduces the comparison space dramatically — only blocks that share a bucket get compared directly.
Type 4 is the hardest. Same logic, different syntax. Pyscn handles this through semantic normalization: both [x for x in items if x > 0] and the equivalent for loop get normalized to a similar token sequence before comparison.
MCP Integration# Pyscn ships as both a CLI tool and an MCP (Model Context Protocol) server. The MCP server exposes the same analysis capabilities to AI coding assistants like Claude Code, Cursor, and ChatGPT.
This means you can ask your AI assistant “find duplicate code in this directory” and it calls pyscn under the hood, getting structured analysis results that it can reason about and suggest refactoring for.
# Claude Code setup
claude mcp add pyscn-mcp uvx -- pyscn-mcp
The MCP server wraps the same Go binary that the CLI uses. No separate analysis engine, no quality difference between CLI and AI-assisted usage. The Go microservice handles the analysis, and a thin Python wrapper (pyscn on PyPI) handles distribution and MCP transport.
The 100K+ lines/sec number comes from two factors:
Go’s concurrency model. File parsing happens concurrently across goroutines. Each file is independent, so the analysis parallelizes naturally.tree-sitter’s parsing speed. tree-sitter parsers are generated C code called through Go’s FFI. The parsing itself is native speed, not interpreted.The architecture — Go for the analysis engine, Python wrapper for distribution, MCP for AI integration — lets each layer play to its strengths. Go handles the performance-critical work. Python handles the ecosystem integration. MCP bridges the gap to AI tooling.