From 26f63c023263938e487822835d70fc99f564ffde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr> Date: Thu, 15 Jul 2021 15:20:21 +0200 Subject: [PATCH] Ensure each grid template can be resolved, update templates, add solve script --- android/gradle.properties | 4 +- assets/files/templates.json | 426 +++++++++++------- .../metadata/android/en-US/changelogs/34.txt | 1 + .../metadata/android/fr-FR/changelogs/34.txt | 1 + generator/batch.sh | 13 +- generator/solve.py | 227 ++++++++++ generator/solve_game_templates.sh | 32 ++ 7 files changed, 539 insertions(+), 165 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/34.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/34.txt create mode 100644 generator/solve.py create mode 100755 generator/solve_game_templates.sh diff --git a/android/gradle.properties b/android/gradle.properties index 9dfcc42..4617f96 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.0.33 -app.versionCode=33 +app.versionName=0.0.34 +app.versionCode=34 diff --git a/assets/files/templates.json b/assets/files/templates.json index e4c884e..ae6ac50 100644 --- a/assets/files/templates.json +++ b/assets/files/templates.json @@ -2,202 +2,308 @@ "templates": { "2x2": { "easy": [ - "0120040000010300", - "4000002030000401", - "4000030000010023", - "0100000410022300", - "0040000101343012", - "0000020334020000", - "0003130200200134", - "2000431000230000", - "0103304000000300", - "0043000000144030" + "0000300200000423", + "0002004010003200", + "0002200432000100", + "0010000010300400", + "0040010200230304", + "0040401301003000", + "0120024020100000", + "0200400324300040", + "0200430020000040", + "0201014200031304", + "0310004310300000", + "0400000241230200", + "0401000440000143", + "1000021004000040", + "1004003004000043", + "2003042000020000", + "2004340000030010", + "3001000000004020", + "3200002304002310", + "3400000042000302" ], "medium": [ - "4000010000010034", - "3002040100031300", - "4000000302000010", - "0100300000020043", - "0000004040013000", - "1003000420000000", - "1000000302300002", - "2001010400430000", - "0401200300004000", - "3004042000002000" + "0000104000000302", + "0000200000014003", + "0000420000403000", + "0003400010020000", + "0004300002004002", + "0020000010003001", + "0030000030100200", + "0030000040003002", + "0030020000004001", + "0120000000000043", + "0204000030010000", + "1000000240000003", + "2000000201000030", + "2000100400030000", + "2001040000000030", + "2100400000100040", + "4000000302000001", + "4000010002100000", + "4010030400003000", + "4030000001040000" ], "hard": [ - "0001000004200200", - "4030100000040000", - "0130021000002000", - "2000130000010020", - "0103300000010400", - "0000042000001004", - "0300000301044000", - "0001010002000003", - "0020020300010300", - "0410200010000200" + "0000004302004020", + "0000020140000100", + "0000040000200310", + "0000204001200004", + "0001000030202003", + "0003000130004000", + "0003002042000100", + "0003400002000020", + "0004100000303001", + "0020300100001000", + "0100000200030400", + "0204401000000100", + "0430010000000004", + "1000004000033010", + "1040040200000020", + "2000400100030000", + "3000021000200000", + "3002000040000001", + "3004002014000000", + "4200100000010030" ], "nightmare": [ - "1003030001000020", - "0000000120003004", - "2300010000020010", - "4001000002300000", - "0200000204000003", - "0000100203010020", - "0000001300023000", - "0004000004012000", - "4200000000002130", - "0400000200000034" + "0000000301020301", + "0000020000010420", + "0000042000001300", + "0000100302040000", + "0000200331020000", + "0001004041002000", + "0003001001200000", + "0004403000233000", + "0010000010400200", + "0010400000000302", + "0012000000010300", + "0020030102001000", + "0020300000020400", + "0100000200030040", + "0104000000002003", + "0200040000200010", + "0240000010000003", + "0301000000030020", + "3000000423000000", + "3000001020000400", ] }, "3x2": { "easy": [ - "000142214003050361006500503006000405", - "420000000000241030356410602040014603", - "540010030050120405003162360521210643", - "014300023160005423342516406230230005", - "200061004530000206006015045120302050", - "651400230600460201020004500103000006", - "010602206051160305523004640013001000", - "500004042060010032024650460320003046", - "060123102500340050605341006005450610", - "560034004002000041105263600400050306" + "000004040010054120301006000230213460", + "000560050030016000000002500306403100", + "004126012034100352300600401060200000", + "006400450060310520060300230004640035", + "016200204060500002000504600000001006", + "020016060040005460000500450602602000", + "020300035421213504400130060200000003", + "030000150036200143300265000021021000", + "143506006014320061000200030000000050", + "154236230145420503503420345000012004", + "300100561340006200430010000003003020", + "300152052040004030620010465300030064", + "350041004250500030243165000006005004", + "405003000000610032500006000320002651", + "420053530040015064003025052006004010", + "450200023600264510531060610304345126", + "500000260001403106100045645013000050", + "600432000060126054030200300041410020" ], "medium": [ - "005000600400300005200004020000010060", - "000060020051306040000005000000040020", - "023010100060500300030100000602005001", - "000306500002400000230000600030010640", - "000030006405030650002300000000160020", - "050100460000030020120603045000000305", - "063010410003000460645000030000100000", - "000000205004100000023010060001530040", - "620304000000500063400010003100040036", - "000120510600300000050301060010005000" + "000003400060005001020000006150100020", + "004600200014000430000000305100610003", + "005000600100064005030200000630000000", + "010062000130100320035006053000000000", + "020014000600000003000540530400200000", + "023000010000000400301002002106005240", + "025461000000512000400002004000000506", + "032005004006005004100600000000000400", + "050010601005004000200000000003123400", + "060503000002002050000400620100014200", + "200400000060001000000650650040042000", + "240005100200000620004300502060403500", + "261005400120010030002050123000000000", + "400200002060030104504300000030000040", + "400501500340100000003600010050302000", + "603250200000005300100000000046006002", + "610000530200050030000006300600000302", + "620030540001200610000000000005005100" ], "hard": [ - "015000000400200000000014000000156300", - "003160000050006004300015040200231000", - "060000002000000002000300004010100650", - "002501500400605200000060000000020600", - "030100002600000420021000053000000030", - "103204205100006005000003500000600002", - "000200060300500002012004000003040100", - "052400000001000050005006040032020000", - "200160060023000600000002050430004000", - "400000060000010400006002000205050046" + "000000500006403210002064000000200400", + "000000600324002460000010003000015630", + "000001301006204603000050500000006100", + "000003000126000060000501460200052610", + "000006206015052004000000135000000000", + "000100000004006005024000400020060030", + "001005020006002100030000510600040001", + "003250005063100020300000000100060000", + "004010002450000530056000205000010000", + "005300002040000060200000060200403650", + "006512010006600000000065200004000230", + "024006000000001054006000000400405120", + "060053450200000504000000100300040001", + "060300504600000510001004020100000032", + "062003000201004302000050300600400000", + "100005000040420006600003014000000030", + "340000600000500021000003050300000206", + "401050000030520600040000000460600000", + "600000400010000005302000003100504002" ], "nightmare": [ - "004000002150600000000630000002040300", - "300000041000000406600010000045005200", - "000000412000000200003150000500000062", - "000002602400004060060314000000030000", - "100623003001000000000034000000600200", - "040006036000100500600300002040010000", - "000050500006000000400125305600002540", - "006021300060004000000200001006000050", - "000130003200230000040050506000010000", - "002030006501000300020000053040200000" + "000300500140120006030500601000000000", + "000600650400060000430000300105012000", + "000650056000004010000340401005305000", + "001000060005600030305060500140102356", + "001006006530002140000000000260060005", + "001540002306000400160000000004003000", + "006000320000000510000436000150103000", + "006010040206050001001005204000010400", + "006302205406300501000000502003040000", + "006500012600031006000120000001000300", + "020016064030005064006200000601000000", + "042300060024010405004003006000000000", + "060050001000200100100040002304304006", + "100025000060003210002054000000350000", + "205004001500040600000003000000050140", + "260100000000010006300020001004050000", + "640100001000020001064000000000410263", ] }, "3x3": { "easy": [ - "004210007090083010000500200007050831910600740400000000006100000801007450050300000", - "740150820562400070000000006308002000106040932090700605901830067680001000437690018", - "798413000340002809251800047003060092070000008519728030127650980900281670860907501", - "061030480300100000408060000009401008832070904100093056000009002903748001704052830", - "807625419000038602056090837729050060508061973103800500070902041081047296092316780", - "046000510815400039709060800074000208082541060053000104060014025091002300007093000", - "305000000009020600742301085918043500030107020407080019803710096674009132200406700", - "090002015165097040078450693802914000000005309000003081014529876580706132006130054", - "608010307070650800409008000000083600965074003300000072104500730806307200030020064", - "046050900000600700825010430002470085150809640000060000900238000038000120200190860" + "000000308038402076629300150064700800000001040015004039040050203000000500053087091", + "000060200203000806856930000782603015039054728045020690020010570560040082074080900", + "000800060030104005004573082026418057009000010400057230090705021870021000100000570", + "004690710800231045003705809936027581582319476001856302079082164615970238420163950", + "007005028300089100400007900203800006598246713716093402029150000070900841000000000", + "008072040479000008253001679041500006800300590690200480780006050030840007006029004", + "008630027013900000406800350607090085000270030530006091060008072000329500000000840", + "064305092050029000298000105500006014002904000647000280085090041901048573076531008", + "070950803823647000560310702400096007218000900706201000002069078607425301940083600", + "100870920008029064502060803670401382913280457284300691327910546459630718801740209", + "204980650306205089058376140000810004500700306040003008723108000861452907005030021", + "390700008064392750072405630040059803600100205018004000720060084050800000083040060", + "452380100018026057706109208001000023284700690570062000160870002320090500800210076", + "500090030960150820010076400630827041000305070027000563000040380086500019200701000", + "604570381950001040080302050890407263345000000206100405068214530002605078519730624", + "610500008040006000530080200390718002872405319056093784705000923003800601000032000", + "897245306065081904130796258742638190306409082589000040608900531403002069951803027", + "908150624006803715105426309050702460342560971017000052701249530293605147500001006" ], "medium": [ - "200960400006070900700000200000002040064090800002080307090000030038000502407100098", - "900500103010000005200001470825390604740000308000005702000219000060854020090063000", - "847300950900040003100008640004030001309804005000070406401785009000020004500000200", - "032070100048100090105300002001000050003000000200817400000783004000901000507426830", - "028000196506400700900816205069042000000078002702000000000591008100000000695004000", - "300000005006800100200005090002500000000107420718000003007008054460000200830640001", - "460100507915007000000000030000709002040000103000200050007024600000000780100675309", - "010039020000600041200000003360107002020003160000265370040076005100904700090010000", - "840063502100090003030702100204087300000420007080000009000076930050314200026000000", - "010805306004010800000000400057400008021073040040200710600000130000380004470026080" + "000000706060001208308406005036100000890352600150000004010094080080010460073008090", + "000020008000408605070056000000007103760105200810000000037509000059012806002603070", + "010309060020050100906000024800000300005097000100060980453200690000910000291400000", + "020400105043600700090008030004000000000904573306700000400270306000586007500040982", + "050070149009000000071508000820000950937000061005907080603150000010340805504080600", + "070200068053600140009000000006920501002158070045700289698500007510090826007000095", + "308910504070050090060004000000000053000070002000005701080000300205000069794060010", + "400908060029060040086000705000001000030506800000400000000600304503100620907043500", + "439700000582091700000480005003200160000300097901500030016030000040802300098050006", + "490750800630080275080000140100590684000613002700000500048205961070000000000460027", + "609000040053001000107209000001000087270000000006030104790305006000090002400607308", + "700301000000600080320048100050079200800000000073005019502004070098007020010080900", + "706090003000050000039200058090081046401000800005070009000903002912040307000700900" ], "hard": [ - "300089050520600007679150300000390804090068000700010005000071030000000000000935701", - "016007000000040105000000020023900046840000900607300010002501000008000600100639000", - "001800200089006050000053000600004700090070000007200809002700604000002100304000020", - "005000001000002598021000000009006003010000045000018700030049806407000000090760010", - "060000000058093000934080700002650007800900020400010008009307106000000080040009075", - "092500730030000900004930100008320506607050020300000000000005810500070009000208050", - "400063001008507000000900070300000910890070000106005004001600402000058036500400000", - "000007800004003000000000092000000184007009030810300059009034010400600020756190000", - "000003040009020078060700000952604000040210000000000900300500780090001060006002010", - "040070620300800904062000700407080000000615040056040000784060009600100070900000000" + "000006000013700000004082500000000600090300807208010005006070009001903008400865030", + "000100000000876493008000027087901000932060010600003000100389076000025000200017840", + "000620500001500027003000004400870102006401708100950000300009670000000905040000003", + "000800000503970014801005009000390407000000200039064000284009050005742600370580000", + "010365009320079000005001000874600103250000600003090004500748000000020401092006030", + "900007000510390604060502301280079400000423060400060709600900807070000000000000045", + "920031040000000018050006720080014203400000050237085004810253407364090002000068930" ], "nightmare": [ - "000805900600000040250600000300170500721000300800003700006000000007030682100500000", - "300090450006000139001003000403000027009040000658000001700080006000000003000209700", - "000270080090000200010009040900000000300004009401600020003050000708906100040100502", - "090000002207000060063500004000600150100085000050004090000700000006209000702000010", - "092803000400100600800700010240000007000008030070400090036080100000000408000910300", - "078060205020000000640000190400020800700001504502000009300016900000200301001703008", - "021803700008200090007000002000907630019036420000000005003000000070300069000410570", - "400007000600408000070039002000000007006100000000000501750000406902060170068050030", - "008003704000000029010020300800200000090008470100495002040001060050046001000502007", - "708100000010087060400000000500060000074020500000005602030002000040000700000796240" + "000007958004080060800090073210504000600800000070060000060908030000630590930040000", + "000867439090000000006394010103245008050600070269700000810000390605030000000028051", + "001079583205400000708601200000740150012005007060012090000000400370100000850000060", + "002080507100000000000002300219806740580009600060004800620040908700060000801205003", + "037009008002000006568300020090010045003007001000593000000030502000100400009000063", + "038200007240001890070405020002003000013000580000008970507000040000090005069507230", + "050809003000603500732004060000090801097300004128006070340200100201900000900000730", + "060070900040009500530086024010003097354007010700640000026300000003518000005000009", + "200460300000002009300090010053009006008500000020040705016203040049600020002080050", + "300000004000060000020400679030906020108024003206003145000050080503070401002049007", + "940008060006000729000006040025000000010000030400021980000009800760850402508702300", ] }, "4x4": { "easy": [ - "340E80D9F100C20B00000030749000G570C0A00G0E520001010800006003A9740C0230000000008EF381BD0296A000400G0078AE000001B0000A06C40B8D20F010000047G006080D000F520B0830000707009A08DC040E3F006CDG13500F9002023065BF00D0470060170900000B0DEA09DB007000150000EFA410G002600008", - "0007G03D548A0020GCBE000A6F03D5840040000B000E001002600C0E7000F00360398DB10GF00E02F00032700D10090A400G096F20E0530000004GE5370900D1C420009G06D0000019A0E4F0035070B0BE00510049A030003G5600D2EC0810090F9A0E00100BG7C65600C00098004B0EE08065G40A00010073040B190EC00A5F", - "0009A010F576000CCBF4200ED19G38000617F0002A8005045GA260C900B3000163000F02C000G9B000CA863GB210047F0250C00740691080470B090183G0A062A00800051030CB9E009000000D00400000G301049CEB02500C209BA0560007G3F00D05000GC0864700057D080BF400CG804C00F079D05A300A000000000E01D9", - "0010C0807E00GDA009206FA050CBE00008070G2BF0400005500E900D00G6400006G842DE0B0CF5101EF07C0G640309000745A0B0EF1806D0D03908012G057C40730000C542000G60010C0036B98004070FD60B401037020042BG0E7FCD6A085000E184GC00B0073000C4009A072EBFG180000000D301C0900A9001F0G0546E8D", - "51A0C068E39F072G20D6EA4000BG0F3C000F00D924500B8A0B0325FGD6A7094130089GE54C162AF006G2B47F09D3081E1C4EA83007F29G0005F7DC01AG08000002C5FE007D89A4068E1AGD9C6230B500D000768B000A02E06F0952A40EGB3C08030D40BA906000C2E86039GDCF25700440010FC23A0E80B07A20015EGB4DF693", - "F04BG3E00920DC1002090000G3A00400C0ED48900B513G6AG1A3C00B000E00900E06300098D00020003006FC420G0000700G2D8031FA50062AD809G40C7B1E030G05B400ED10A07F04C08G59203006B09B7FE1230600085D0000FA7D0GB820C410BC00A00000050000527E08CA0061000000900005G20DAC00G40CB507638200", - "00B006008D29GC300G538097C00F00DE9A00E10070005B0F8702D0GC500BA9600908C70DGF45B0E0D00098B5273040C0A0000E00DC016F000BGC0461A00E000540050FCE0B103AGD120E00D008G0C706G00B05860A0002407C3A0920E650F81BB00G6D0915C38EF2030100000000067CCD7900006GFA10B3F826BC030E079500", - "EGF965080402B0006C07A0EGD03028590BD394020FC6AG0E200A3D7B5E0G4C60D0C01A06F9548230F985423D0CG10E0040B6E7GFA80300C13001095060E000D00602FE401D803A0C85902BD0C34E0706CFE40163GAB05D28130D0000270F09400458B0A10G20CF93A13BG82796FC04E5GE2FDC90351076BA9D60500E4000G182", - "7GA09005080BFC61B8934A00C00020ED1020C0BE49FG730AFE000D6G72A3B098820075A00B0F0D39050E0089GC36A010003FG01287D00EC590G0EF3010004B8720D0FE0400008106C0400GD061800F0060FG000050B0C74351E8600A3024D9G03FC00041B6070000D70A0CE3240016F0E000A0G0F000950CG61902F0AECD3800", - "AC00BG067D0930F28EF0005002G19640G00630908F5EAB07B79410EFC6A0G050500108CE407G236F06004AD10C02B98E09380B206010C47540C273659EF81A0DD0E9G07318CB502A0A5B0EFCD0246G91086C50B00G00E034310FA9020500D80BCF4E25G0300071B0608DEF1927B000A09G0704A0F1EC80D315BAC037G486F2E9" + "004AG065287001BD00G000BE4D0F70C0D00040C00010360E5F021D00A00E49G8B9E0A1G03280C704G4AC57926BF0DE80827000D00AE00B00605000E47C0GA02143FDCG0190002A70702064FBD1080G3C956GD07000400000C01B0529F7G00D400134EBAC80D00267A005704G0F208CE92G069F5000C7001AEC072618B5A0G4DF", + "006003500E0800G0003FA8200009001C0AC50D90420030070EBG0F6003A1520470006A400D0C08FEF2000E009G000A6330080B0CA016G0D00DA60905F800107B0089ECDA060F703006000470E135090A0F200130790040B0E370900F0004000000G0B5E41C00000F600387020F40EB0DD5FE0GC08B6A27011042F6A0300E8GC0", + "02E6G00530B7F0890514860E0DG27C0AF7D9000208E016G38CB00A97146F2D050697E0B002300804BA4E19237080DGC0CD20745GA00631FE5F31680C0040B0026EADC37000F092181B00506029D300074G03F2190A0E6B00290FDG8B0710E03C03009C4D01AG057001C0070603584E00D4G50F00BE7CA0607800A5004629C30G", + "041050D000F0CAG00520BA0F107G000003AG01806DB5924F0070004G009A5DB10050C0G4008DE0A0A800D0B10963GF70200B000950006800D00000600A00B00070BA9C05G640D300500E1B3D00000GF0F030G4A0D5C8172B4GD10000B00F05000090867C0GA40BEDEBFC0G0002070018G0070E03C050F09A0A42FD9B00E0005G", + "0809BE6F0D37AGC4B1000ADG6482090FFGAD90000BCE010274C01520F0A0DB00107029E0304B0D05E90A000C056F02075D3000487E0GC69A8640705029DCF0130A600000DF20B70E9B0E0F0000538CD10FD80102G700300600176430E00820F9D09040CBA8E50F0G478GD0000100E30060F5G0A1C27D004BA0B007FE93G4050D", + "10GC705F2D390068A050E0G8000F70D3E0091D3A060000004D379B620GEA0F5CF612CED0030004000900A2000800613DGED30180FC0000000008000019000CF034A0B570900GF602BC91364E00F2D8GA0G00F0AC4B0D0E01D000201G30005B9420BG50E7DF90C006030D8G04CE0002100F8AD3C062010500C5046F0107A38DB9", + "24F539A870DE0610C100507098A0D2E3307GCE0010628095E98D2F60B00000A70BC000F4017A9080F61A80005E007DC47G030AD6008C2B50D000750B00F60000430197050D28CABE00506B00E0C300DG0EA7D80CG501640200DCA02E0B070809000FG0030700002A100B020AC6E439000C00BD1000G90008073800092F5D010B", + "28EF46090DA531C0534AC01G709F000DGCD6FB3510420E7A01B920A83GE0F546D610A09E507G0CBF4FAE10B7028960G097GC0400EBFA5812320B0C8F410009E71A8GD06B2000700004607AF0G5000290EB00004CF060GAD1F5978GE0DA1B0634AEF400G060B027856905E82DA4G703FB0D0367C48F01EGA08G00BF0A9003D40C", + "36FC1705004DAB82G1E5A20B00039F4DA0089ED40G0253C1D429C08F0B007EG09CD7G64AE350281F5BG00D9C00010703804105E2G0AFBC09006A0831C7D9G4051902E457DF6G0A0B080D0009000CF05G0036DGC8152AE0047G542AF3B9E0100C2D8G5C76FA0431B0001B0920080ED500C5730F0E0DB04G9A4E0F3BAD5107C628", + "4000DG59C000A00F15C0000E490FD00B0F00C023681B549G8020000BD5GA6C7E2D7080G05E014000B1400D900FA7G8005G0F620A00B01ED79C00040180D0BA050A0C706G1D4529E80952480D0003701A0ED00000F00C0BG600G100E070960054003720B801C0F50DC2FE3906B75D0040A00051D40G0007BCDB050CF0E00800A0", + "480E01CD67G32B000A0D0065C091G0700G00000705B080D65730G40200A00E003070A609G200B8100F007008000AE50G10EG0F4B780C000A65802E010030C04D700F80540300AGE0AB4030EG01C9D0F000D509268AFG4CB026G1CD0AE00059308DA0600E0C04000B900C0G70060D005E0E60D01C0F500A800407B083200E0D9C", + "59A2600E0300F07BF6C098127B4AD0030G083CFD19E0A426001DB5A70F2680C0006A09540007CEBF72E0063A540C000D0034DF7CB6000200C0052EBG9001400705D672084EB000001F80000B079D204500B7004581020000204900D6005G7B08002FAG83E01B060000G10B0908D00750D003070FAC6408108B0CED6120093FA0", + "5A0000C0D0200300F300E0700B80AD2500C70050000080G000263D0A570410BF00G20F6803DCB74E0F000207400A3861AB800E0G000000CD00740C008000GA5201FEG020A04056907G00D0AEB050248CC4D805012006EGABB0A06480GC70D0036E4A08B0109072DG0000F006E0A0C030000000ED6800000000B10A9502CD6FE8", + "607E0DC95100A340D90GA001C00370F80AF03G026408D1E92310F078090A006C70G3000010C0F4A6000A0F06E0240B130B26DC1000008007F1548B0A006000CD570F109D2B063C0G02010007800C96000400000G3000007A00D0C8000F07425BG69D004C0A80E03FB0C8000000016D000E37028B460D0A9040A0600F7030G0B0", + "60E70C20038A000D029008F00754A000418093AGE02005BCAG0CD740B1F9028EC002000458A7BED35E6B0D0040C3G01F8001CB030FG069000D0GAF9E2000C050060405000AEG03C0100D02090070EB0408053E7C004B1D60E00060BA0C3DF8200030B1E006D00G09000A09327EB58601942E706D0G105C0B0F008G05349200E0", + "68024GA0CD000790FAE9681C4G57B0D0C005DE0700F9G6A80D7G29FB0A804C1504D0BF23189A750C7030A1C6D4E00G8B0090G450F37B00ED5B81709E0C2GAF4300009BEG0F1C0D5406FC537DA90008BG8E0B00400000C970495D80607B00002F0F2015B0G6A0040090CA070000BF0206B003008F27D01009D71436009E0050F0", + "703G0AD0C8E0014B090BC0E0D034G00085DC0F4B02000E370E04120G9075D0000A900520300100BC4CG006F0090E70D20D57000E00F0390100EF00900DA00804G0C39E0FB0601000E0800C01F007060G51B2G470E0D000A8006008B2G14A00E5281600G04EC0A070C00E00601A038D5003000D100F0B6GCEA0F0E08C7G560019", + "70A10426DE8FB0G0D8F05BCA231G470626G0D3704C0B810ACB4501F89A7623EDE01039070D24GA084A63000257G0F009BG000A4FC931D25E092D0G8BE6FA0417A00078003G00104F6DC01E34AF97582B0004006000B0AGD30200B5A0014DE97C3F9082D5006C0EB007E200B0F0D0053485D047091B03000210BC06E370000D0G", + "A3FB2CD8G41006902008A619C537BE0G5C670BEG829FD1A49E0074006ADB23C8F5CA83204EB60D1909G20D5A37C8400F07ED0G40F95A02836834C00BD021E0570F0E400C508D39B0D17CF20E0349A5060B050963A1E2FC7D3609D5B17FG084E072B65E3F98A01G0C80419A02EC6G5000CA90B8G00DF5672E0G0F61C00B73984A", + "ADC0263F00G00450086000G009500FA2F0G970B5C42A08D34E20C089FD3007100270B0E018AG590F00009527DC6F8A001FB0400A05000E609A5610F0E7B0200D0GE08C1D40020006C092EFA00010D307001A396B0ED0F0C08030527490FC100E09D30158BGE74C0000A100005F0036E0058EFB4300C00D7GGCF4A7900680B105", + "BA026005F401D0EG376F0B1A09D0C425G90C700E8000B006540E0009B002708A0E01000F6540A70DF000A0D12E80650C000408000D0B920020CDB05G300A800098B00003000000C00G2A090070F00E004D0700A0C81030F000F3C582A0B0G0970C480AE000000G596F053DC00000087000EB06G807004C03D0000F2700C00601", + "C060940B503A712007A00360G01F004B54E0G70F000BA306030F0D0064009G0800900E50A08D00G03B0G00D0CE90800AA80E00G91603BD72D0074A30F000091EE0D63BCA81G9F457050B0F700000G2894FG0028E7B500A008C70019G3F00EB000DC300A629F700E570F0E843006GDCA10E05290000A167B36A14C0B0E0D02F0G", + "E0G764A0910C5F0090083FE0BGA2C07D213AG7BCF65D049EC6BF9D250E870GA1FGA305960401E7B074DE2CFG60B8A310109B083EAD0005646800B0047903DCGF837CAG601040B005BA0GE90280F501C049018B0730D6G2EAD0200140009B68F7A7100EG058290B3C5009F2CAD0107E46GFC45370EB001D0232ED000BCF009A50", + "EC0A0000F10687000B238017040950A089F0A0003D0BG01001G00000A5000000GE31080F7B9A2DC0B6C8E7D01005009A00A960BC400000G000050A30206D0001C0E200010G040907A36D008050720100000FCB0600304GD200B403796FDCAE5030000008D740B0E0621GB0F4E008007D54D0790AC200608G0A80350000BF1240", + "G0E0689D50F3B000270D530B0AG48E690085407AB6C0F30GA63B021FDE987C040408210900EFG7B390B1043765AGED0F0D7E0G56243B980AC3GABF0E09814520004C0900E86ADB31E0203D8CF1B954G70F007B010250A00E0159A6EG0307C0F8000GE0F83B16200C48071500AF0D69E00B02DC609G7E10856E109A000C453G7D", + "G23CFE48010A5B76EB15790G438CD2FA8070352AFBEG94C0F94AD1CB7060083003GFB481EDC9265791EBCGA524763F8DC502E37D0GFB4A1970D82F96A503ECBG0G276C193ED4F5A85F8942070AG10EDC4EC38A009657B1G216A05BGECF28039438B407FC09A21DE00C5E98B4173DA02F2A9G1DE3504FC76B0001A652GCBE8943" ], "medium": [ - "340E80D9F100C20B00000030749000G570C0A00G0E520001010800006003A9740C0230000000008EF381BD0296A000400G0078AE000001B0000A06C40B8D20F010000047G006080D000F520B0830000707009A08DC040E3F006CDG13500F9002023065BF00D0470060170900000B0DEA09DB007000150000EFA410G002600008", - "0007G03D548A0020GCBE000A6F03D5840040000B000E001002600C0E7000F00360398DB10GF00E02F00032700D10090A400G096F20E0530000004GE5370900D1C420009G06D0000019A0E4F0035070B0BE00510049A030003G5600D2EC0810090F9A0E00100BG7C65600C00098004B0EE08065G40A00010073040B190EC00A5F", - "0009A010F576000CCBF4200ED19G38000617F0002A8005045GA260C900B3000163000F02C000G9B000CA863GB210047F0250C00740691080470B090183G0A062A00800051030CB9E009000000D00400000G301049CEB02500C209BA0560007G3F00D05000GC0864700057D080BF400CG804C00F079D05A300A000000000E01D9", - "0010C0807E00GDA009206FA050CBE00008070G2BF0400005500E900D00G6400006G842DE0B0CF5101EF07C0G640309000745A0B0EF1806D0D03908012G057C40730000C542000G60010C0036B98004070FD60B401037020042BG0E7FCD6A085000E184GC00B0073000C4009A072EBFG180000000D301C0900A9001F0G0546E8D", - "51A0C068E39F072G20D6EA4000BG0F3C000F00D924500B8A0B0325FGD6A7094130089GE54C162AF006G2B47F09D3081E1C4EA83007F29G0005F7DC01AG08000002C5FE007D89A4068E1AGD9C6230B500D000768B000A02E06F0952A40EGB3C08030D40BA906000C2E86039GDCF25700440010FC23A0E80B07A20015EGB4DF693", - "F04BG3E00920DC1002090000G3A00400C0ED48900B513G6AG1A3C00B000E00900E06300098D00020003006FC420G0000700G2D8031FA50062AD809G40C7B1E030G05B400ED10A07F04C08G59203006B09B7FE1230600085D0000FA7D0GB820C410BC00A00000050000527E08CA0061000000900005G20DAC00G40CB507638200", - "00B006008D29GC300G538097C00F00DE9A00E10070005B0F8702D0GC500BA9600908C70DGF45B0E0D00098B5273040C0A0000E00DC016F000BGC0461A00E000540050FCE0B103AGD120E00D008G0C706G00B05860A0002407C3A0920E650F81BB00G6D0915C38EF2030100000000067CCD7900006GFA10B3F826BC030E079500", - "EGF965080402B0006C07A0EGD03028590BD394020FC6AG0E200A3D7B5E0G4C60D0C01A06F9548230F985423D0CG10E0040B6E7GFA80300C13001095060E000D00602FE401D803A0C85902BD0C34E0706CFE40163GAB05D28130D0000270F09400458B0A10G20CF93A13BG82796FC04E5GE2FDC90351076BA9D60500E4000G182", - "7GA09005080BFC61B8934A00C00020ED1020C0BE49FG730AFE000D6G72A3B098820075A00B0F0D39050E0089GC36A010003FG01287D00EC590G0EF3010004B8720D0FE0400008106C0400GD061800F0060FG000050B0C74351E8600A3024D9G03FC00041B6070000D70A0CE3240016F0E000A0G0F000950CG61902F0AECD3800", - "AC00BG067D0930F28EF0005002G19640G00630908F5EAB07B79410EFC6A0G050500108CE407G236F06004AD10C02B98E09380B206010C47540C273659EF81A0DD0E9G07318CB502A0A5B0EFCD0246G91086C50B00G00E034310FA9020500D80BCF4E25G0300071B0608DEF1927B000A09G0704A0F1EC80D315BAC037G486F2E9" + "001G40805320B0FDFB8DG1760AC9000EA460000000BD80G70E950F0210G76A4C4GB000A0003C96E090ECFD0B800542A3D3A0942E0G0BC71000008063000E0G0F004906EG00D3F80A5AC30B08G64FE0010DF032C1095AG0646000DA040CE835090F302G006081700B0070093FCE0250D0005408BC9D0G1F06G90607100B04A000", + "030E9A00C0020405G2058C17009F00A3070B2FED0500C000C8D00040EGA0B7004068D0700E05G000F90G0E0310B758007DE215FG93060B005A03C800G0240D000500A20E003D0006A69D540F00GE0038E00C0D300060900034216G085CF00E7D8050G02060EB30000070E00030D06F540G340756F80A200C200000D009500A00", + "0E00900030800F009A0070E601FB0G000F4D8B300006900E600304025000780B008CA0G0205400E0030408500000F0007DB210906C0050A3F05A0D000300G008002F407305BD010CD530F00E090C204G0G000C0A00E1D307AC1002D00073E0F0000100C0B70000GDC4D02000000G8E0F07A03F0B9D0E0C200B0ED00GC8206090", + "0G5EF00C070180B38041B06900D00G000007G100A6EC0D0FAD000042080G107656B20C01007F3E0A037DE00400G000084AE000GF02C5900B10GF05D63E8B002C0060027089F00CA02E0A080500000B90GF15D90AC4B208E7970BC4EG1A560F30B0DG0A83EF60C21000095607DC20B000F004000D0BA8000900064000G0105080", + "49800E00603C572A5000600C00700E0DC0D74A2150E0B068006E0000800D0G13020001D0050764CGB07C0G6028000309DF1903050000208BAG46800009B3E5D0ECF52080430B90A10402ED907C0106B0169GB0A40E087030780DC0030090G04E002409000B0500GC9D00F000G04EA000FB5137G8C06A09E40ECA1050908F0B06", + "50F0008GED020607030E04000B00DFG0D8203A070000000BC9GB600D040015806007F13A0C0B000E100CG7040E00500F800G090B050A6104A0E9000000107020E07510D32800C4B62010E04050000008G698A20C4FD3E7050003050810002DF0BGC00DAF39750061350D0610B00FG279070053G982E1B0C090A070C2DG600050", + "70960BD02000A0050E0B0002900000465024EF8910G6007C0C00A60400000900B900007050F0D4026F70C59GAD008030300CB02869705010GD00000E380C9A600200073AB500160F06B5D8C000370GA40710000006083CBDA3F8600B04C07E000000006D0019C0F3000020A187E30000C00A00F3406BG00100E0G000CF0D6290", + "9EC0A08F6000G07003006B00G94008005G0640000B8000AD8102G5EC30A700097C08E00640B30D0F00E0F1A30G7542C6065F08201EC0AG071004C000A6FD0E006090BF0GDC3E0152C0B072680004D00E080G300070006000003150C0280G790B04601EG5B0080F00G71E800B0300902400002C3AF0G60000000C94D051E20000", + "9GACD05002806000BD28009A50C0F7EG0E0108000A9000D500400000000D00981000832G00E000A0F080CD056G400329D000E0000013800B0300F1600002E50078006F0009300B0A42000008E05600F0050G004DF820CE1609001500A40B02072A00560000BE307006FB720103A0400001004ED000F0A600C4059A3B006001G0", + "C2070D000840G00095B60030F0G000010E0F6G2095DC000BG000800CB301F02E00401F028060B0002090370040C0D0000015CBE6A70D203GA00004900B03E0F006207AG03900008CE00400007D586200B97350006G0000A458GDF000C00407037109A600502F000D005200CFG68730000G0B2879DC0000606308D500000900E0", + "DF00C98030517BG00B8700000CF0020490014000BG000A80A3E000F080600900670000302BGF18D0G800A290000300500C0386G5000D27000210700D0006C00G000001C0E0B00G0500G200A0F50CE6170060F500D00G030B000EG0627130000004500G0F6782B1A31A3D980BGFE56070F070530040CB00E220B0604C03DA050F", + "G76CD0402FE5B80A0B500007A30C601E8403200E916B00G710E00F068GD00C20E07F12D040B630C5AD2067F43C5EG10B41B0E00CF07G06A20C30B00A1000FE7005009E0D60000B000ACE780BD2900456029B346070010ADG68D4F0A150G0200000070D30000095010F02A600C51D000000G08010000000FCC3A0400FB8097G6D", + "GCD4FE000700000A58A03000000F7400760104008CBD00F03F0967810000020D0000GF08BD12900EAD9F5370060020G00100D094E30GA80FE08G00B20FA7D00407009AE05B460G019048000F00CE000310068000FG70E092D5BE200718006F00800000F3040000E000GDC010350B4A00603C4BGA7008F9050B570200A9F1G0C0" ], "hard": [ - "340E80D9F100C20B00000030749000G570C0A00G0E520001010800006003A9740C0230000000008EF381BD0296A000400G0078AE000001B0000A06C40B8D20F010000047G006080D000F520B0830000707009A08DC040E3F006CDG13500F9002023065BF00D0470060170900000B0DEA09DB007000150000EFA410G002600008", - "0007G03D548A0020GCBE000A6F03D5840040000B000E001002600C0E7000F00360398DB10GF00E02F00032700D10090A400G096F20E0530000004GE5370900D1C420009G06D0000019A0E4F0035070B0BE00510049A030003G5600D2EC0810090F9A0E00100BG7C65600C00098004B0EE08065G40A00010073040B190EC00A5F", - "0009A010F576000CCBF4200ED19G38000617F0002A8005045GA260C900B3000163000F02C000G9B000CA863GB210047F0250C00740691080470B090183G0A062A00800051030CB9E009000000D00400000G301049CEB02500C209BA0560007G3F00D05000GC0864700057D080BF400CG804C00F079D05A300A000000000E01D9", - "0010C0807E00GDA009206FA050CBE00008070G2BF0400005500E900D00G6400006G842DE0B0CF5101EF07C0G640309000745A0B0EF1806D0D03908012G057C40730000C542000G60010C0036B98004070FD60B401037020042BG0E7FCD6A085000E184GC00B0073000C4009A072EBFG180000000D301C0900A9001F0G0546E8D", - "51A0C068E39F072G20D6EA4000BG0F3C000F00D924500B8A0B0325FGD6A7094130089GE54C162AF006G2B47F09D3081E1C4EA83007F29G0005F7DC01AG08000002C5FE007D89A4068E1AGD9C6230B500D000768B000A02E06F0952A40EGB3C08030D40BA906000C2E86039GDCF25700440010FC23A0E80B07A20015EGB4DF693", - "F04BG3E00920DC1002090000G3A00400C0ED48900B513G6AG1A3C00B000E00900E06300098D00020003006FC420G0000700G2D8031FA50062AD809G40C7B1E030G05B400ED10A07F04C08G59203006B09B7FE1230600085D0000FA7D0GB820C410BC00A00000050000527E08CA0061000000900005G20DAC00G40CB507638200", - "00B006008D29GC300G538097C00F00DE9A00E10070005B0F8702D0GC500BA9600908C70DGF45B0E0D00098B5273040C0A0000E00DC016F000BGC0461A00E000540050FCE0B103AGD120E00D008G0C706G00B05860A0002407C3A0920E650F81BB00G6D0915C38EF2030100000000067CCD7900006GFA10B3F826BC030E079500", - "EGF965080402B0006C07A0EGD03028590BD394020FC6AG0E200A3D7B5E0G4C60D0C01A06F9548230F985423D0CG10E0040B6E7GFA80300C13001095060E000D00602FE401D803A0C85902BD0C34E0706CFE40163GAB05D28130D0000270F09400458B0A10G20CF93A13BG82796FC04E5GE2FDC90351076BA9D60500E4000G182", - "7GA09005080BFC61B8934A00C00020ED1020C0BE49FG730AFE000D6G72A3B098820075A00B0F0D39050E0089GC36A010003FG01287D00EC590G0EF3010004B8720D0FE0400008106C0400GD061800F0060FG000050B0C74351E8600A3024D9G03FC00041B6070000D70A0CE3240016F0E000A0G0F000950CG61902F0AECD3800", - "AC00BG067D0930F28EF0005002G19640G00630908F5EAB07B79410EFC6A0G050500108CE407G236F06004AD10C02B98E09380B206010C47540C273659EF81A0DD0E9G07318CB502A0A5B0EFCD0246G91086C50B00G00E034310FA9020500D80BCF4E25G0300071B0608DEF1927B000A09G0704A0F1EC80D315BAC037G486F2E9" + "001G40805320B0FDFB8DG1760AC9000EA460000000BD80G70E950F0210G76A4C4GB000A0003C96E090ECFD0B800542A3D3A0942E0G0BC71000008063000E0G0F004906EG00D3F80A5AC30B08G64FE0010DF032C1095AG0646000DA040CE835090F302G006081700B0070093FCE0250D0005408BC9D0G1F06G90607100B04A000", + "030E9A00C0020405G2058C17009F00A3070B2FED0500C000C8D00040EGA0B7004068D0700E05G000F90G0E0310B758007DE215FG93060B005A03C800G0240D000500A20E003D0006A69D540F00GE0038E00C0D300060900034216G085CF00E7D8050G02060EB30000070E00030D06F540G340756F80A200C200000D009500A00", + "0E00900030800F009A0070E601FB0G000F4D8B300006900E600304025000780B008CA0G0205400E0030408500000F0007DB210906C0050A3F05A0D000300G008002F407305BD010CD530F00E090C204G0G000C0A00E1D307AC1002D00073E0F0000100C0B70000GDC4D02000000G8E0F07A03F0B9D0E0C200B0ED00GC8206090", + "0G5EF00C070180B38041B06900D00G000007G100A6EC0D0FAD000042080G107656B20C01007F3E0A037DE00400G000084AE000GF02C5900B10GF05D63E8B002C0060027089F00CA02E0A080500000B90GF15D90AC4B208E7970BC4EG1A560F30B0DG0A83EF60C21000095607DC20B000F004000D0BA8000900064000G0105080", + "49800E00603C572A5000600C00700E0DC0D74A2150E0B068006E0000800D0G13020001D0050764CGB07C0G6028000309DF1903050000208BAG46800009B3E5D0ECF52080430B90A10402ED907C0106B0169GB0A40E087030780DC0030090G04E002409000B0500GC9D00F000G04EA000FB5137G8C06A09E40ECA1050908F0B06", + "50F0008GED020607030E04000B00DFG0D8203A070000000BC9GB600D040015806007F13A0C0B000E100CG7040E00500F800G090B050A6104A0E9000000107020E07510D32800C4B62010E04050000008G698A20C4FD3E7050003050810002DF0BGC00DAF39750061350D0610B00FG279070053G982E1B0C090A070C2DG600050", + "70960BD02000A0050E0B0002900000465024EF8910G6007C0C00A60400000900B900007050F0D4026F70C59GAD008030300CB02869705010GD00000E380C9A600200073AB500160F06B5D8C000370GA40710000006083CBDA3F8600B04C07E000000006D0019C0F3000020A187E30000C00A00F3406BG00100E0G000CF0D6290", + "9EC0A08F6000G07003006B00G94008005G0640000B8000AD8102G5EC30A700097C08E00640B30D0F00E0F1A30G7542C6065F08201EC0AG071004C000A6FD0E006090BF0GDC3E0152C0B072680004D00E080G300070006000003150C0280G790B04601EG5B0080F00G71E800B0300902400002C3AF0G60000000C94D051E20000", + "9GACD05002806000BD28009A50C0F7EG0E0108000A9000D500400000000D00981000832G00E000A0F080CD056G400329D000E0000013800B0300F1600002E50078006F0009300B0A42000008E05600F0050G004DF820CE1609001500A40B02072A00560000BE307006FB720103A0400001004ED000F0A600C4059A3B006001G0", + "C2070D000840G00095B60030F0G000010E0F6G2095DC000BG000800CB301F02E00401F028060B0002090370040C0D0000015CBE6A70D203GA00004900B03E0F006207AG03900008CE00400007D586200B97350006G0000A458GDF000C00407037109A600502F000D005200CFG68730000G0B2879DC0000606308D500000900E0", + "DF00C98030517BG00B8700000CF0020490014000BG000A80A3E000F080600900670000302BGF18D0G800A290000300500C0386G5000D27000210700D0006C00G000001C0E0B00G0500G200A0F50CE6170060F500D00G030B000EG0627130000004500G0F6782B1A31A3D980BGFE56070F070530040CB00E220B0604C03DA050F", + "G76CD0402FE5B80A0B500007A30C601E8403200E916B00G710E00F068GD00C20E07F12D040B630C5AD2067F43C5EG10B41B0E00CF07G06A20C30B00A1000FE7005009E0D60000B000ACE780BD2900456029B346070010ADG68D4F0A150G0200000070D30000095010F02A600C51D000000G08010000000FCC3A0400FB8097G6D", + "GCD4FE000700000A58A03000000F7400760104008CBD00F03F0967810000020D0000GF08BD12900EAD9F5370060020G00100D094E30GA80FE08G00B20FA7D00407009AE05B460G019048000F00CE000310068000FG70E092D5BE200718006F00800000F3040000E000GDC010350B4A00603C4BGA7008F9050B570200A9F1G0C0" ], "nightmare": [ - "340E80D9F100C20B00000030749000G570C0A00G0E520001010800006003A9740C0230000000008EF381BD0296A000400G0078AE000001B0000A06C40B8D20F010000047G006080D000F520B0830000707009A08DC040E3F006CDG13500F9002023065BF00D0470060170900000B0DEA09DB007000150000EFA410G002600008", - "0007G03D548A0020GCBE000A6F03D5840040000B000E001002600C0E7000F00360398DB10GF00E02F00032700D10090A400G096F20E0530000004GE5370900D1C420009G06D0000019A0E4F0035070B0BE00510049A030003G5600D2EC0810090F9A0E00100BG7C65600C00098004B0EE08065G40A00010073040B190EC00A5F", - "0009A010F576000CCBF4200ED19G38000617F0002A8005045GA260C900B3000163000F02C000G9B000CA863GB210047F0250C00740691080470B090183G0A062A00800051030CB9E009000000D00400000G301049CEB02500C209BA0560007G3F00D05000GC0864700057D080BF400CG804C00F079D05A300A000000000E01D9", - "0010C0807E00GDA009206FA050CBE00008070G2BF0400005500E900D00G6400006G842DE0B0CF5101EF07C0G640309000745A0B0EF1806D0D03908012G057C40730000C542000G60010C0036B98004070FD60B401037020042BG0E7FCD6A085000E184GC00B0073000C4009A072EBFG180000000D301C0900A9001F0G0546E8D", - "51A0C068E39F072G20D6EA4000BG0F3C000F00D924500B8A0B0325FGD6A7094130089GE54C162AF006G2B47F09D3081E1C4EA83007F29G0005F7DC01AG08000002C5FE007D89A4068E1AGD9C6230B500D000768B000A02E06F0952A40EGB3C08030D40BA906000C2E86039GDCF25700440010FC23A0E80B07A20015EGB4DF693", - "F04BG3E00920DC1002090000G3A00400C0ED48900B513G6AG1A3C00B000E00900E06300098D00020003006FC420G0000700G2D8031FA50062AD809G40C7B1E030G05B400ED10A07F04C08G59203006B09B7FE1230600085D0000FA7D0GB820C410BC00A00000050000527E08CA0061000000900005G20DAC00G40CB507638200", - "00B006008D29GC300G538097C00F00DE9A00E10070005B0F8702D0GC500BA9600908C70DGF45B0E0D00098B5273040C0A0000E00DC016F000BGC0461A00E000540050FCE0B103AGD120E00D008G0C706G00B05860A0002407C3A0920E650F81BB00G6D0915C38EF2030100000000067CCD7900006GFA10B3F826BC030E079500", - "EGF965080402B0006C07A0EGD03028590BD394020FC6AG0E200A3D7B5E0G4C60D0C01A06F9548230F985423D0CG10E0040B6E7GFA80300C13001095060E000D00602FE401D803A0C85902BD0C34E0706CFE40163GAB05D28130D0000270F09400458B0A10G20CF93A13BG82796FC04E5GE2FDC90351076BA9D60500E4000G182", - "7GA09005080BFC61B8934A00C00020ED1020C0BE49FG730AFE000D6G72A3B098820075A00B0F0D39050E0089GC36A010003FG01287D00EC590G0EF3010004B8720D0FE0400008106C0400GD061800F0060FG000050B0C74351E8600A3024D9G03FC00041B6070000D70A0CE3240016F0E000A0G0F000950CG61902F0AECD3800", - "AC00BG067D0930F28EF0005002G19640G00630908F5EAB07B79410EFC6A0G050500108CE407G236F06004AD10C02B98E09380B206010C47540C273659EF81A0DD0E9G07318CB502A0A5B0EFCD0246G91086C50B00G00E034310FA9020500D80BCF4E25G0300071B0608DEF1927B000A09G0704A0F1EC80D315BAC037G486F2E9" + "001G40805320B0FDFB8DG1760AC9000EA460000000BD80G70E950F0210G76A4C4GB000A0003C96E090ECFD0B800542A3D3A0942E0G0BC71000008063000E0G0F004906EG00D3F80A5AC30B08G64FE0010DF032C1095AG0646000DA040CE835090F302G006081700B0070093FCE0250D0005408BC9D0G1F06G90607100B04A000", + "030E9A00C0020405G2058C17009F00A3070B2FED0500C000C8D00040EGA0B7004068D0700E05G000F90G0E0310B758007DE215FG93060B005A03C800G0240D000500A20E003D0006A69D540F00GE0038E00C0D300060900034216G085CF00E7D8050G02060EB30000070E00030D06F540G340756F80A200C200000D009500A00", + "0E00900030800F009A0070E601FB0G000F4D8B300006900E600304025000780B008CA0G0205400E0030408500000F0007DB210906C0050A3F05A0D000300G008002F407305BD010CD530F00E090C204G0G000C0A00E1D307AC1002D00073E0F0000100C0B70000GDC4D02000000G8E0F07A03F0B9D0E0C200B0ED00GC8206090", + "0G5EF00C070180B38041B06900D00G000007G100A6EC0D0FAD000042080G107656B20C01007F3E0A037DE00400G000084AE000GF02C5900B10GF05D63E8B002C0060027089F00CA02E0A080500000B90GF15D90AC4B208E7970BC4EG1A560F30B0DG0A83EF60C21000095607DC20B000F004000D0BA8000900064000G0105080", + "49800E00603C572A5000600C00700E0DC0D74A2150E0B068006E0000800D0G13020001D0050764CGB07C0G6028000309DF1903050000208BAG46800009B3E5D0ECF52080430B90A10402ED907C0106B0169GB0A40E087030780DC0030090G04E002409000B0500GC9D00F000G04EA000FB5137G8C06A09E40ECA1050908F0B06", + "50F0008GED020607030E04000B00DFG0D8203A070000000BC9GB600D040015806007F13A0C0B000E100CG7040E00500F800G090B050A6104A0E9000000107020E07510D32800C4B62010E04050000008G698A20C4FD3E7050003050810002DF0BGC00DAF39750061350D0610B00FG279070053G982E1B0C090A070C2DG600050", + "70960BD02000A0050E0B0002900000465024EF8910G6007C0C00A60400000900B900007050F0D4026F70C59GAD008030300CB02869705010GD00000E380C9A600200073AB500160F06B5D8C000370GA40710000006083CBDA3F8600B04C07E000000006D0019C0F3000020A187E30000C00A00F3406BG00100E0G000CF0D6290", + "9EC0A08F6000G07003006B00G94008005G0640000B8000AD8102G5EC30A700097C08E00640B30D0F00E0F1A30G7542C6065F08201EC0AG071004C000A6FD0E006090BF0GDC3E0152C0B072680004D00E080G300070006000003150C0280G790B04601EG5B0080F00G71E800B0300902400002C3AF0G60000000C94D051E20000", + "9GACD05002806000BD28009A50C0F7EG0E0108000A9000D500400000000D00981000832G00E000A0F080CD056G400329D000E0000013800B0300F1600002E50078006F0009300B0A42000008E05600F0050G004DF820CE1609001500A40B02072A00560000BE307006FB720103A0400001004ED000F0A600C4059A3B006001G0", + "C2070D000840G00095B60030F0G000010E0F6G2095DC000BG000800CB301F02E00401F028060B0002090370040C0D0000015CBE6A70D203GA00004900B03E0F006207AG03900008CE00400007D586200B97350006G0000A458GDF000C00407037109A600502F000D005200CFG68730000G0B2879DC0000606308D500000900E0", + "DF00C98030517BG00B8700000CF0020490014000BG000A80A3E000F080600900670000302BGF18D0G800A290000300500C0386G5000D27000210700D0006C00G000001C0E0B00G0500G200A0F50CE6170060F500D00G030B000EG0627130000004500G0F6782B1A31A3D980BGFE56070F070530040CB00E220B0604C03DA050F", + "G76CD0402FE5B80A0B500007A30C601E8403200E916B00G710E00F068GD00C20E07F12D040B630C5AD2067F43C5EG10B41B0E00CF07G06A20C30B00A1000FE7005009E0D60000B000ACE780BD2900456029B346070010ADG68D4F0A150G0200000070D30000095010F02A600C51D000000G08010000000FCC3A0400FB8097G6D", + "GCD4FE000700000A58A03000000F7400760104008CBD00F03F0967810000020D0000GF08BD12900EAD9F5370060020G00100D094E30GA80FE08G00B20FA7D00407009AE05B460G019048000F00CE000310068000FG70E092D5BE200718006F00800000F3040000E000GDC010350B4A00603C4BGA7008F9050B570200A9F1G0C0" ] } } diff --git a/fastlane/metadata/android/en-US/changelogs/34.txt b/fastlane/metadata/android/en-US/changelogs/34.txt new file mode 100644 index 0000000..c5015db --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/34.txt @@ -0,0 +1 @@ +Ensure each grid template can be resolved, update templates, add solve script diff --git a/fastlane/metadata/android/fr-FR/changelogs/34.txt b/fastlane/metadata/android/fr-FR/changelogs/34.txt new file mode 100644 index 0000000..7a838c7 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/34.txt @@ -0,0 +1 @@ +Vérification que chaque modèle peut être résolu, mise à jour des modèles, ajout d'un script (naïf) de résolution diff --git a/generator/batch.sh b/generator/batch.sh index 49c66b0..ec54300 100755 --- a/generator/batch.sh +++ b/generator/batch.sh @@ -7,11 +7,18 @@ ALLOWED_DIFFICULTY_VALUES="easy medium hard nightmare" GRIDS_COUNT=10 for BLOCK_SIZE in ${ALLOWED_BLOCK_SIZE_VALUES}; do - echo "Block size: ${BLOCK_SIZE}" for DIFFICULTY in ${ALLOWED_DIFFICULTY_VALUES}; do - echo "Difficulty: ${DIFFICULTY}" + echo "Block size: ${BLOCK_SIZE} / Difficulty: ${DIFFICULTY}" for i in $(seq ${GRIDS_COUNT}); do - python ${CURRENT_DIR}/generate.py ${BLOCK_SIZE} ${DIFFICULTY} | tail -n 1 + # Generate grid candidate + GRID="$(python ${CURRENT_DIR}/generate.py ${BLOCK_SIZE} ${DIFFICULTY} | tail -n 1)" + # Ensure grid can be resolve without any assumption + CAN_BE_SOLVED="$(python ${CURRENT_DIR}/solve.py ${BLOCK_SIZE} ${GRID} | tail -n 1)" + if [ "${CAN_BE_SOLVED}" == "Ok" ]; then + echo "${BLOCK_SIZE} ${DIFFICULTY} ${GRID}" + else + echo "FAILED: ${BLOCK_SIZE} ${DIFFICULTY} ${GRID}" + fi done done done diff --git a/generator/solve.py b/generator/solve.py new file mode 100644 index 0000000..331ef6f --- /dev/null +++ b/generator/solve.py @@ -0,0 +1,227 @@ +#!/usr/bin/python +# -*- coding: iso-8859-15 -*- + +# +# Naive sudoku grid solver +# +# Will try to solve sudoku grid without making any assumption +# -> pick and fill first cell where only one value is allowed +# and loop until grid is filled +# +# Will fail if solution needs any assumption on a cell value +# + +import sys +import math + +if (len(sys.argv) != 3): + print('Usage: solve.py block-size grid') + print('block-size: [2x2|3x2|3x3|4x4]') + exit() + +blocksize, gridTemplate = sys.argv[1], sys.argv[2] + +if not blocksize in ['2x2', '3x2', '3x3', '4x4']: + print('wrong size given') + exit() + +splitted_blocksize = blocksize.split('x') +size_horizontal = int(splitted_blocksize[0]) +size_vertical = int(splitted_blocksize[1]) + +boardSize = size_horizontal * size_vertical + +if (len(gridTemplate) != boardSize * boardSize): + print('wrong grid length (should be '+str(boardSize * boardSize)+')') + exit() + +debugSolveGrid = False + +############################################################################ + +sys.stdout.write('Will solve grid: ['+str(size_horizontal)+'x'+str(size_vertical)+'] // '+gridTemplate+'\n') + +stringValues = '0123456789ABCDEFG' + +# draw grid (array style) +def drawGrid(grid): + gridVerticalSize = len(grid) + gridHorizontalSize = len(grid[0]) + horizontalLineLength = ((size_horizontal + 1) * size_vertical) + 1 + + for row in range(gridHorizontalSize): + if ((row % size_vertical) == 0): + sys.stdout.write(('â•' * horizontalLineLength) + '\n') + for col in range(gridVerticalSize): + if ((col % size_horizontal) == 0): + sys.stdout.write('â•‘') + if grid[row][col] != 0: + sys.stdout.write(stringValues[grid[row][col]]) + else: + sys.stdout.write(' ') + sys.stdout.write('â•‘\n') + sys.stdout.write(('â•' * horizontalLineLength) + '\n') + sys.stdout.write('\n') + +# (deep) copy of grid +def copyGrid(grid): + copiedGrid = [] + for row in range(len(grid)): + copiedGrid.append([]) + for col in range(len(grid[row])): + copiedGrid[row].append(grid[row][col]) + return copiedGrid + +# Init grid from given template +def initGrid(boardSize, gridTemplate): + grid = [] + index = 0 + for row in range(boardSize): + grid.append([]) + for col in range(boardSize): + grid[row].append(stringValues.index(gridTemplate[index])) + index += 1 + return grid + +# Check if grid is fully completed, without any empty cell +def isFullyCompleted(grid): + for row in range(len(grid)): + for col in range(len(grid[row])): + if grid[row][col] == 0: + return False + return True + +# Check if a list contains duplicates (conflicts) +def containsDuplicates(list): + tmp_set = set(list) + return (len(list) != len(tmp_set)) + +# Check if given grid contains conflicts +def hasConflict(grid, size_horizontal, size_vertical): + # Check horizontal conflicts + for row in range(len(grid)): + values = [] + for col in range(len(grid[row])): + value = grid[row][col] + if value != 0: + values.append(value) + if containsDuplicates(values): + # print('Horizontal conflict found') + return True + + # Check vertical conflicts + for col in range(len(grid[0])): + values = [] + for row in range(len(grid)): + value = grid[row][col] + if value != 0: + values.append(value) + if containsDuplicates(values): + # print('Vertical conflict found') + return True + + # Check sub-blocks conflicts + for blockRow in range(size_horizontal): + for blockCol in range(size_vertical): + # Get sub-square + blockColFrom = size_horizontal * int(col / size_horizontal) + blockRowFrom = size_vertical * int(row / size_vertical) + values = [] + for rowInBlock in range(size_vertical): + for colInBlock in range(size_horizontal): + row = (blockRow * size_vertical) + rowInBlock; + col = (blockCol * size_horizontal) + colInBlock; + value = grid[row][col] + if value != 0: + values.append(value) + if containsDuplicates(values): + # print('Sub-block conflict found') + return True + + return False + +# Check if a value is allowed in a cell (without conflicting) +def isValueAllowed(grid, size_horizontal, size_vertical, row, col, candidateValue): + testGrid = copyGrid(grid) + testGrid[row][col] = candidateValue + if not hasConflict(testGrid, size_horizontal, size_vertical): + return True + return False + +# Get allowed values in a cell (witjout conflicting) +def findAllowedValuesForCell(grid, size_horizontal, size_vertical, row, col): + allowedValues = [] + if not hasConflict(grid, size_horizontal, size_vertical): + for candidateValue in range(1, size_horizontal * size_vertical + 1): + if isValueAllowed(grid, size_horizontal, size_vertical, row, col, candidateValue): + allowedValues.append(candidateValue) + return allowedValues + + +# Globally solve grid +def solve(grid, size_horizontal, size_vertical): + iterations = 0 + maxIterations = 500 + boardSize = size_horizontal * size_vertical + + # Loop until grid is fully completed + while True: + iterations += 1 + if isFullyCompleted(grid) or (iterations > maxIterations): + break + + if debugSolveGrid: + print('===================================') + print('Iteration: '+str(iterations)) + + # Get first/next cell with only one allowed value + candidates = [] + if debugSolveGrid: + print('Searching for empty cells...') + for row in range(len(grid)): + for col in range(len(grid[row])): + if grid[row][col] == 0: + if debugSolveGrid: + print('Found empty cell ['+str(col)+','+str(row)+']') + candidates.append([row,col]) + + if len(candidates): + for candidate in candidates: + candidateRow = candidate[0] + candidateCol = candidate[1] + allowedValues = findAllowedValuesForCell(grid, size_horizontal, size_vertical, candidateRow, candidateCol) + if debugSolveGrid: + print('Allowed values for cell ['+str(candidateCol)+','+str(candidateRow)+']: '+str(allowedValues)) + if len(allowedValues) != 1: + if debugSolveGrid: + print(' Non unique allowed value for cell. Skip to next cell') + else: + value = allowedValues[0] + grid[candidateRow][candidateCol] = value + if debugSolveGrid: + print(' Found unique allowed value for cell ['+str(candidateCol)+','+str(candidateRow)+']: '+str(value)) + drawGrid(grid) + +######################### + +sys.stdout.write('Building start grid:\n') +grid = initGrid(boardSize, gridTemplate) +drawGrid(grid) + +sys.stdout.write('Checking grid:\n') +if hasConflict(grid, size_horizontal, size_vertical): + sys.stdout.write(' - oups, initial conflict found.\n') +else: + sys.stdout.write(' - ok, no initial conflict found.\n') + + sys.stdout.write('\n') + + sys.stdout.write('Solving grid...\n') + solve(grid, size_horizontal, size_vertical) + + if isFullyCompleted(grid): + sys.stdout.write('Ok, solved grid:\n') + drawGrid(grid) + sys.stdout.write('Ok\n') + else: + sys.stdout.write('Failed to solve grid\n') diff --git a/generator/solve_game_templates.sh b/generator/solve_game_templates.sh new file mode 100755 index 0000000..7169ae3 --- /dev/null +++ b/generator/solve_game_templates.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" + +# Fetch grid from game templates +GRIDS="$(cat "${CURRENT_DIR}/../assets/files/templates.json" | grep "0" | sed 's/"//g' | sed 's/,//g')" + +function get_block_size() { + BLOCK_SIZE="" + + GRID_LENGTH="$(echo -n "${GRID}" | wc -c)" + if [ "${GRID_LENGTH}" == "16" ]; then + BLOCK_SIZE="2x2" + fi + if [ "${GRID_LENGTH}" == "36" ]; then + BLOCK_SIZE="3x2" + fi + if [ "${GRID_LENGTH}" == "81" ]; then + BLOCK_SIZE="3x3" + fi + if [ "${GRID_LENGTH}" == "256" ]; then + BLOCK_SIZE="4x4" + fi + + echo "${BLOCK_SIZE}" +} + +for GRID in ${GRIDS}; do + BLOCK_SIZE="$(get_block_size "${GRID}")" + echo "GRID: ${BLOCK_SIZE} / ${GRID}" + python ${CURRENT_DIR}/solve.py ${BLOCK_SIZE} ${GRID} | tail -n 1 +done -- GitLab