Compare commits

...

4 commits

4 changed files with 492 additions and 0 deletions

101
2023/d17/ex1/ex1.py Executable file
View file

@ -0,0 +1,101 @@
#!/usr/bin/env python
import functools
import heapq
import itertools
import sys
from collections.abc import Iterator
from enum import Enum
from types import NotImplementedType
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
@functools.total_ordering
class Direction(Enum):
NORTH = Point(-1, 0)
SOUTH = Point(1, 0)
EAST = Point(0, 1)
WEST = Point(0, -1)
def apply(self, pos: Point) -> Point:
dx, dy = self.value
return Point(pos.x + dx, pos.y + dy)
def __le__(self, other: object) -> bool | NotImplementedType:
if not isinstance(other, Direction):
return NotImplemented
return self.value <= other.value
def solve(input: list[str]) -> int:
def parse(input: list[str]) -> dict[Point, int]:
res: dict[Point, int] = {}
for x, line in enumerate(input):
for y, c in enumerate(line):
res[Point(x, y)] = int(c)
return res
def possible_directions(
dir: Direction, in_a_row: int
) -> Iterator[tuple[Direction, int]]:
if in_a_row < 3:
yield dir, in_a_row + 1
DIRECTIONS = {
Direction.NORTH: (Direction.EAST, Direction.WEST),
Direction.SOUTH: (Direction.EAST, Direction.WEST),
Direction.WEST: (Direction.NORTH, Direction.SOUTH),
Direction.EAST: (Direction.NORTH, Direction.SOUTH),
}
yield from zip(DIRECTIONS[dir], itertools.repeat(1))
def minimal_path(map: dict[Point, int], start: Point, end: Point) -> int:
class PathNode(NamedTuple):
pos: Point
dir: Direction
in_a_row: int
QueueNode = tuple[int, PathNode]
# Start with arbitrary south direction with *0* in a row, to get correct neighbours
queue: list[QueueNode] = [(0, PathNode(start, Direction.SOUTH, 0))]
seen: set[PathNode] = set()
while queue:
dist, node = heapq.heappop(queue)
if node.pos == end:
return dist
# If we've already seen that exact node before, don't look at it again
if node in seen:
continue
# First time encountering those node conditions, record it
seen.add(node)
for dir, in_a_row in possible_directions(node.dir, node.in_a_row):
new_pos = dir.apply(node.pos)
if new_pos not in map:
continue
new_dist = dist + map[new_pos]
new_node = PathNode(new_pos, dir, in_a_row)
heapq.heappush(queue, (new_dist, new_node))
assert False # Sanity check
map = parse(input)
start = Point(0, 0)
end = Point(len(input) - 1, len(input[0]) - 1)
return minimal_path(map, start, end)
def main() -> None:
input = sys.stdin.read().splitlines()
print(solve(input))
if __name__ == "__main__":
main()

141
2023/d17/ex1/input Normal file
View file

@ -0,0 +1,141 @@
332114151454212113454214512653223255653145556624424154456133366132437365465536664121621126441346245234461242215311265554234431413125424232423
424122453313324434224115136213521634564424342426236222533671444755341166437735256274463642146521245445525564224535224235252421321153331414212
413135332143231235543411242346121246426526353322253563266165247116731545675123735113725356164644235243456435165362223324541111145554434255422
342414155321154351141122633651163361322521331431171711732775134466255552673716661246145621631741136461146333345323514452212522243423331243533
233122133123434345314435544645431134453126541174227715665316662211115137412561563227455475361474445363563152111331443163553513522255241544413
311155314135534244231531535261532514433556673217725631772737642444271655435143741351644364131521776726224131145423362141264421135213424444312
125223544215111353343424155256123365154351463763766674147324253115775277444764475616636627512777314123411653155251461135612231241532431443541
154322542255554251655461341623214513115361722221264336433413737164732151366715314571755667734463471347653566243234254154662144543222435244125
252325122542331561151545613663525144424744652635577332743277337361111426356754123713326313135767754125231545141233212414322652635242142211243
454455312142515231552161246536164222446676131324746654761237342662724443133775752352417235142551513416366647642554343645133342433313112223215
211321313544336425166555444645646314661414271372414365632613313465526437351145461333343753254644114475234636422562331151621222261343242132553
333323312524514633125345124531441435312467416662235315752745412217643724364731152373347747421417475252352125265161445435134163426142233353211
143415113132116416143626162231614424513725134766666676741241522865823673657635526716525717332247166312254667317151665462144364126645223552411
123334222542663461264564446667515346467312356331546413675457588884644474545872866632331424544647524462746756437435461546521636115321425325224
535345333562155134222145436426256733221166524375121367788836878623525623827363242436426285231274677542316742253627612345624461262345554521442
513513214555346252356533625326334371762344355253554747668642823328845258872476637478333343444741446277731137761242516643141361443236463232215
314525145346116555121632636161213754311442177643444555582648638323545372736247584882637437532357337727176314174617322351326335323111115424155
142332123435235625634363646646665357435316213755777836867244734747572768533477723538834633673282641347553626573276175764552564465454441435441
115211236413132455511236635577446251412725323837876686385477828546337857552852634472863357843565343753573547723431623543642234642413143151542
344114335565255663416177255247156565162253555737563755723446262582337484754524764236238872364836885463427235157556711172742232315152424214355
322351245444122231555251374126727321177145723432388575878262785645433733687626542747657328463363325266561117334673213464515334316451252323323
114145243212231145266145633211575313262368663374456836668225838276887736247478522334345632464286642377734773245555273715255363521255411436125
455425264555563656334547167127221744428428767672557672528634562733434744234767632378343637854563773843778372227556167732575433414361653661645
523515321446441335631614642677743527678465286472244872478426436773365258245445623486253654722483532674422763615327372421556232261315262663663
243531332212553542512231776744326572857225588676323528368528574588687496986977437666235744834528878678885244665767573623253644364166116254113
444444112522431332452677416112527782362277632366487625237276747897354943947465889953376837548526737743346528781622556466746677544446126242133
551224351455343155254473223427545326426283637545435543486459335566488585644794556748393635283844433672572582847247363644233223765612263324266
624512252531155611465764114412153772872664238382223677844796388487978588349347899373747553577834454374823787527861133444621766341566356141365
122513321515254337477661465512352573543734686234338559996944463795463356755575964934753954988266763385387234286423462633175673633153162556456
536631433532656576652771312522342646633782573233279989744885775639388386544597879884345946975725737282827242738352524521432253763215654523115
322242133611462672545617461568524454733756842479444543488449547487568897468683955886935535694896858528355443457358667243642313225326142635412
433165134443115323655412565336574774363263823339637755748738478844753443366543756864599667497478638535364437368324232432351147613376615461324
255546365535224352467626565444446263832366733855339686844454779545954833997374664863737346696795866578234664656443247566163775227133522126211
332543346224456342457145637872588878872574934465846438696585998768959393446858386444585949749989395845243437522874257474667424163321432143662
562336531135536464571531445325786432525654973537497993963876555849853689467557948538984566573893374699522258566835263827361447616765121531241
134431331273426633773265462863548226445269397663747657533667545839948559886569784664389446348545683389848688445244623781735357464754775332441
455514441477666641215728225436682865472376638684673865686537967585959697777945778763958683986999446946735832744256768434443442331647672323162
642551661752757431115132444368754488566587583899343636597956846969766697666696549958595334986455854649598564858883536552667547462457766361136
523135446552147326745727437763658824294779583474959943837486894449889786848545858986984945998848759695488574225628248774221513366313255152244
662142534574774471476733285584773353469368338384693894458894844555764768998647478459784635737579344766346566445772776385244757261641646262231
426164675347223367356542678766487676449383835573944385678679999588547686484865465688679958436853663379986545474734678688476311743671535264562
636221515617411216247337338427225735479885464746489395486445598697885986665448699866884656794474879996386956934725254526364324475256241275663
631655547723135622724356638578268487796375786548339985946895559755594954857979446575876457888866863986588685442687887862434325557242465434334
526561675234753571754873872743282697865877868743798687568577798587569899574484554484486596454938697634387879836757377864647232634674626657136
224367751471353647528352332475353678438596388378986467455448887646465576695666985755458794657464949967358875375525855268833747673643621712113
555155247624263644685247526382749435467889975896454465589895886678995785898565848957859844445874878643778658535937624565377735216144455146652
326237275165115664286248564635235597494984939548556988958465866659979766684556496568777489668689659466945846453722248242466764614544772336545
252431512527441277652682654526537378589387973677795869974677788748496486946677468975449899885555473979374748343648488332525562346344443772553
334445255752755383853263265588439634448596738474455889458598988975979996868859879877898797766766846958879864596965328638267846232745551326455
331776676677775667763658323247548647473346994464947655845774859797686965997669898985478769844957676563749678677496544457376882437561732771415
524166432536425482552537234634638489648635668489984866757588557998759988879759786984579576979588678858478864969749575527756262527122755635643
621727645151575887576234428334879934367558864978956787976575789687695598659778579995684454959976779569644787946544773527367553271175577267671
146536267557111863546535476546756933855578657694848587666677867759855877966869976666895795977754986464958576833534434856257276637677672374622
627162456571435862223277266645437845769458457477859464885659565779885987687868765787589649788985577888968356376393555423832745685215266467517
356365425561522443354482823779863564644867657899958444967567857769895796968885877556985858769679467875486466963448536675724876383637637347332
662617714433245736446788383839477478955657876855994484679589576895957757596689789878757698854677478674545986936783367487553578825131414257161
332752445446138652863525378663559896379746684495687998757655759676957899686977876787997889474577748675663489587853377638443448848132472112131
453742717451167763344725476499465974694977569678544576559869769779787858777859878659995587547699787885775974835467735257544662734254664167234
637433522225172664387548695933565599774766649475487879985879567866859778897575697897755575969866878866559366585534438655344868386256513661571
546147626464562275655733897739395889457894577877799798775969558887665695975589685557965565588684599794655433543949864872227536744356275446534
466362637642348545833267889637543575568589757869745856956895658665988768997999655989667957999546697465848679934687374434356755244437463163527
432241752456735627523255338945585453647447657554545955769795789789997877986787567985578897759678944769468657795794576536268322838744716172531
362335524521283767267868233894954334695664994778485687755666859567896666877777856977986957755786769546887535444947538736628443346847462743523
242277366552744663233252489644883664499486849778665576798778978997766697987689796855857957659765978885748744987558355833587345887644235437312
561476674157528347537548599693576474885768577976886585698957697776687879979969876766765577555667674874858777897543556687327834848556466137735
266443423617535645753445779387753884547464964579665696566776797688777799889668699855885667595966647668866856763675976465687353888681336245316
572245756261228737774356774434644334465597956478659678566557786678987687767797677855856669659856465546998943449649767856528226362754511645257
765454637722232528732727987873694678786897686957758658776958776876669697776896797985686878577656659767548457559453559953286436834721254612345
715574444332523722776764939533778537899944495848987975789655786679777697866668686698596879975965745866774945968874839792274752686441541427615
345426643746658264878244879834877886854849486559776688568989799999769977869688867896566869679855957757568478643556858683764734437851357452275
155264155457638423874255465346979399784764447766558558566789767877968796988868867775556888798564684589499477496386865936552684743662561437775
556553777462428352772346536564948445645848965477587585797665668668998889899669897695759889687557667557584743537744477835564286662643223525755
641634624577764727436225779978964774555745645897796877559888677666767998968896788888689868597664985685858554356376665498623746875723662152372
273464717234862288588878479738499968679778769844967858766886688999898688976778797877666987697667878994996657354955977482446733867376656676652
551452257437387582588858645358387357746754779495965859595599878879877987668898767897997855656868855556757747486357487665847763562466422346611
563771242132683432222557436749937783648584568946588665665565698788787787998889676985866968796874695585557699853673538872377582853855131713461
621754271237543666875247946859748999855959977745986585788867866697696868789869768995576776679784564654855987787897358797454368778485716675345
164557236272472546822232846668399389759849987667659785676559867986867888878979688978688695876854496969468763957695738688223564746777531171265
242346713471432688725345548968585493977887799777998877589665998798978979687788866756996567759999475865446943768859868732555538748467434116221
724542325744422353827368477965435394957587656594657956589558869678779879978997989779557567777576965957979596983484379373273827325462765413315
134467152455573564745453678895499973399455464974855888996756898968898666769686667565559598686586858797879648838954569323385654838463315425344
677644725227283525233274374448443847867587946496756687655559798668967889678966568857686688687474797656795664978587359585475743444537567171372
336331514454173343536876798555466989966569868897467756888959675759587897868888779865575958968754759769695636436637498444722662454277255276665
245372163442533628423276455934688944899667958898697795685589868988659597757695978985568755897588876768955385979973858688872756554467423674135
251472373172465268687323637558467886966997454586679595656555799786788685987977899567657589878679656758649535738838795357634278627632741221151
165461424121142643385468264846788537647578965477849879999585588788675566556988859776968656866748767857679947367996538366526226283326214137262
552347532473355256876326459866563676749894796886745598856867798578859675999778699689958599985994868557485944545796355254658552388764762637577
411635777264744624762842767953597944883658696686489566856859985666787779576968666779658795444747587477754964887759644474728635835454465116123
525225774221277357825768273779533699948575746956759694897959969678678956879656896656877599855484649666456453586543836385766273838732235171565
413446335411722332567467583938598777437966488478684886785797667899976899669555696776775778568978567578544555855646936463366758257267556526367
232225126611437885288888224674796768654898896446868958777899786966689959778798898557578584894674968778348499974537656632752837285262221612562
312524227137512563356783624765555493696544874684948745994767775568987755855875779575947858745547754676685368397837548474384853754524257634625
164576266612155222885335524447458943676659664764845487449595699877699967897599959997454474895848957865889443963557382768878244863267411634354
343423173533275137862288876573755898763474747556889894445589898998965697755557969845649449784567454999596856689395535336738467324251433443313
324642722572242663573535885523747435878468838854477747966756946868979567855589567654976484995966698365838477364437873477732253364252715313424
633536551523473523243244283326385679995773658874569756469784895788454454466967676647864944477548686957835935734344472886742338655365237743545
126254446714213213436657334784236857866388445465965986588698754599946596568588549887968594867664769467935498667776266236524482164321464331744
632122261674245423458774627724266986994837445876996574698444995879887876557659858469744965457586679894948948458686783436673327143364537263243
465244311333114323725266442638884838436463333596776867596749549964879559765764848754756989656759354743483867679752528468865454711412437437215
261415356334624227658332247423732949399345845987468987484698858676956555788758758658656776848894849855333685652263222425756836554766646272443
521646365566326414152826643636235965753596433593485485995795654765798865954954774954854696879635646973347786334722533446758821117733417454123
252365462474552424777626563728632557857897556978697654768788568859684765969498588674456548639599966588966387644635645878744172627175772722511
322111677544534553154787663277355446646868855664534468569956798568597597797985774677475959647634668749666469868462232582736411761171527151611
612342244172321553733876453434327274768778644399663358375677775959999689866565698576678735898955879849469468533635274885381342774377452254623
651234151461371123426165832588863365476947993573539948648464444454868478568755779686456634875633856784657866623534635827356542713775643236154
426422164365351275264187473582686768433977556986656756547883959898696745877867456753466554348833684967659438745566626826373666115341437512356
251224616536545656545722482674755228883867595576787346349774537744798879665975566954395436673954998843688762228354424347472522235531376331326
335541164543114144761463764542372366287647948934896437773435546559497746964557357657989773374388363578827574482885664583611615165136533323225
261331415374732264655453647768254758542843666899665464693864936867468988485548354636569486458753866966873563534677586636515154572216163145356
313232345646561617413414322476366687653335889569688478593764445835478384478864579889578586636387865692637456447655326361775525421537351443252
354422624313221353436553153273228525734583687565383399578579988847365867834335367495554595854533343462877332872884662534165677211161214245532
542143423513624235434762263462784556783874775748777548864766786566666483439848384735573868946946858786326267558486871376536352777136111223641
563426221453513247534322123144884253486238658666956647949649676497797648994455393587476533436988875438823554657527344561756544414561541432165
142324116651521772664345223478653548388638657544743867958975353393743498698444676463749436355523368338437534752654673372352117774565612455142
521252364664151234171376543732684442243322874775475946689463578554843486635378489996373438934348323722334326883767125435113461472456453544434
366456342146455776343221412213427758323428237676455365546898955778897855479458369598384867528536647227825337245572327613615476534655616364436
456262313325465615634626471552134825254874668258282367564793649864648953456359464348433437556572444858443732283547165236722572136426516552255
215214555215121531363153365156745726838285476672588458468636756485794378474346453448633724336222848523788322461363427143622643764542154516631
445435243132162412737127746252357518384582434632727743323776457988789744747556744546232245626842323687453554237454472415624653454464312353566
413512155566552553344114742623626673426573822753222774627337845846626888678573728525426326742682452368847826463175721614615753615514521215131
121335422224363443354722134157661571538463676346636753673773667735542264247284835668253673727235386467366265255634467667311151641335353324222
124223214542653663566665314176475124517877488374766545574687862278742556456474375457627645727273436443464373242226321257155151623466354226535
224342321546661552253517421437534637164144462465386448554748656436426565223525648357863358822784435247243523427371615216772115551454466464444
152151341446215313532274524113276662527567472536387628785437566568247675623344644462557726773438776443134255637564367716346225361466131111152
441131264554242642424433222772464422143526743636387232724335464526838833628275276362774824878543373332675711255316334646112165166145436225355
222223346255612511131365546422132224534414716137367462626727462537235434658525224753354265433542656353255435456465556334646626646616114541252
122254524154564644355156315711257331373433572663242435353634872647446868386788243424223288834522715673434774222724734714143326426614126132222
512124425315656654512332445376341167415722616144652756353244273445678654828624424884532254424714514364625764637237362662611534611466615252341
144321153255241633164514444655277754717616621362745215268637475632553485326364864874882263216537664313267663452313553535362633636242154324325
215522151121146641113121366265573756214663745551174365226877835824533746627332877664426625513336257243467577673364646532514644421421452544444
335313335414162252122432222633336424453112573546364534773326574784656537542222587263555442637622533151434567664221616224322511431465543243151
554515254153443453616316365142667412367456471655714423572426445365634244714461517246763535321157222422452237455335224412113513116341541551245
242342552224414663454122443156612324424462742634773552556733543127575614737735454524176471342351442215257671354234543465566226442453421214332
423332221231152525435143325351441332245166165545746441225161776522365226425741716113757265346324464231517554455663426161163531133151125441514
424112342444153352442235323533255342273475361517511641775633616543162217257766644611574212127347362451473365646541415632262325644422215452323
535123215132355441452363223224326111142177116662677154564514756736116151566423375123522315721736346462721611643433515643226113553235433255245
224211552121124334331251616112654554353552524371574216334214517671732613731631733667464726623341735667366531311523356541525225553551524513511
133135253512342521415314125243161342522122244673535175332435771431335676512526131661651773762677772541211631242452526663421451534253432541324
332331532553424153415425566412652656345152461311365447431514137764335267535631223555617762772366325564623566653643641356522511155115525413323
124122513322542451532212635122623231342565341643435327641416177253251451471617514752111736553524423266211413554453514154155451335251224234321
114322223311332542521324344432242254215112631121532433351616521421133465333644152516113467545556154614445514451441162115222213523543445151233

109
2023/d17/ex2/ex2.py Executable file
View file

@ -0,0 +1,109 @@
#!/usr/bin/env python
import functools
import heapq
import itertools
import sys
from collections.abc import Iterator
from enum import Enum
from types import NotImplementedType
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
@functools.total_ordering
class Direction(Enum):
NORTH = Point(-1, 0)
SOUTH = Point(1, 0)
EAST = Point(0, 1)
WEST = Point(0, -1)
def apply(self, pos: Point) -> Point:
dx, dy = self.value
return Point(pos.x + dx, pos.y + dy)
def __le__(self, other: object) -> bool | NotImplementedType:
if not isinstance(other, Direction):
return NotImplemented
return self.value <= other.value
def solve(input: list[str]) -> int:
def parse(input: list[str]) -> dict[Point, int]:
res: dict[Point, int] = {}
for x, line in enumerate(input):
for y, c in enumerate(line):
res[Point(x, y)] = int(c)
return res
def possible_directions(
pos: Point, dir: Direction, in_a_row: int, map: dict[Point, int]
) -> Iterator[tuple[Direction, int]]:
if in_a_row < 10:
yield dir, in_a_row + 1
DIRECTIONS = {
Direction.NORTH: (Direction.EAST, Direction.WEST),
Direction.SOUTH: (Direction.EAST, Direction.WEST),
Direction.WEST: (Direction.NORTH, Direction.SOUTH),
Direction.EAST: (Direction.NORTH, Direction.SOUTH),
}
if in_a_row >= 4:
for new_dir in DIRECTIONS[dir]:
dx, dy = new_dir.value
if Point(pos.x + 4 * dx, pos.y + 4 * dy) not in map:
continue
yield new_dir, 1
def minimal_path(map: dict[Point, int], start: Point, end: Point) -> int:
class PathNode(NamedTuple):
pos: Point
dir: Direction
in_a_row: int
QueueNode = tuple[int, PathNode]
# Start with arbitrary all directions with *0* in a row, to get correct neighbours
queue: list[QueueNode] = [
(0, PathNode(start, Direction.SOUTH, 0)),
(0, PathNode(start, Direction.EAST, 0)),
]
seen: set[PathNode] = set()
while queue:
dist, node = heapq.heappop(queue)
if node.pos == end:
return dist
# If we've already seen that exact node before, don't look at it again
if node in seen:
continue
# First time encountering those node conditions, record it
seen.add(node)
for dir, in_a_row in possible_directions(*node, map):
new_pos = dir.apply(node.pos)
if new_pos not in map:
continue
new_dist = dist + map[new_pos]
new_node = PathNode(new_pos, dir, in_a_row)
heapq.heappush(queue, (new_dist, new_node))
assert False # Sanity check
map = parse(input)
start = Point(0, 0)
end = Point(len(input) - 1, len(input[0]) - 1)
return minimal_path(map, start, end)
def main() -> None:
input = sys.stdin.read().splitlines()
print(solve(input))
if __name__ == "__main__":
main()

141
2023/d17/ex2/input Normal file
View file

@ -0,0 +1,141 @@
332114151454212113454214512653223255653145556624424154456133366132437365465536664121621126441346245234461242215311265554234431413125424232423
424122453313324434224115136213521634564424342426236222533671444755341166437735256274463642146521245445525564224535224235252421321153331414212
413135332143231235543411242346121246426526353322253563266165247116731545675123735113725356164644235243456435165362223324541111145554434255422
342414155321154351141122633651163361322521331431171711732775134466255552673716661246145621631741136461146333345323514452212522243423331243533
233122133123434345314435544645431134453126541174227715665316662211115137412561563227455475361474445363563152111331443163553513522255241544413
311155314135534244231531535261532514433556673217725631772737642444271655435143741351644364131521776726224131145423362141264421135213424444312
125223544215111353343424155256123365154351463763766674147324253115775277444764475616636627512777314123411653155251461135612231241532431443541
154322542255554251655461341623214513115361722221264336433413737164732151366715314571755667734463471347653566243234254154662144543222435244125
252325122542331561151545613663525144424744652635577332743277337361111426356754123713326313135767754125231545141233212414322652635242142211243
454455312142515231552161246536164222446676131324746654761237342662724443133775752352417235142551513416366647642554343645133342433313112223215
211321313544336425166555444645646314661414271372414365632613313465526437351145461333343753254644114475234636422562331151621222261343242132553
333323312524514633125345124531441435312467416662235315752745412217643724364731152373347747421417475252352125265161445435134163426142233353211
143415113132116416143626162231614424513725134766666676741241522865823673657635526716525717332247166312254667317151665462144364126645223552411
123334222542663461264564446667515346467312356331546413675457588884644474545872866632331424544647524462746756437435461546521636115321425325224
535345333562155134222145436426256733221166524375121367788836878623525623827363242436426285231274677542316742253627612345624461262345554521442
513513214555346252356533625326334371762344355253554747668642823328845258872476637478333343444741446277731137761242516643141361443236463232215
314525145346116555121632636161213754311442177643444555582648638323545372736247584882637437532357337727176314174617322351326335323111115424155
142332123435235625634363646646665357435316213755777836867244734747572768533477723538834633673282641347553626573276175764552564465454441435441
115211236413132455511236635577446251412725323837876686385477828546337857552852634472863357843565343753573547723431623543642234642413143151542
344114335565255663416177255247156565162253555737563755723446262582337484754524764236238872364836885463427235157556711172742232315152424214355
322351245444122231555251374126727321177145723432388575878262785645433733687626542747657328463363325266561117334673213464515334316451252323323
114145243212231145266145633211575313262368663374456836668225838276887736247478522334345632464286642377734773245555273715255363521255411436125
455425264555563656334547167127221744428428767672557672528634562733434744234767632378343637854563773843778372227556167732575433414361653661645
523515321446441335631614642677743527678465286472244872478426436773365258245445623486253654722483532674422763615327372421556232261315262663663
243531332212553542512231776744326572857225588676323528368528574588687496986977437666235744834528878678885244665767573623253644364166116254113
444444112522431332452677416112527782362277632366487625237276747897354943947465889953376837548526737743346528781622556466746677544446126242133
551224351455343155254473223427545326426283637545435543486459335566488585644794556748393635283844433672572582847247363644233223765612263324266
624512252531155611465764114412153772872664238382223677844796388487978588349347899373747553577834454374823787527861133444621766341566356141365
122513321515254337477661465512352573543734686234338559996944463795463356755575964934753954988266763385387234286423462633175673633153162556456
536631433532656576652771312522342646633782573233279989744885775639388386544597879884345946975725737282827242738352524521432253763215654523115
322242133611462672545617461568524454733756842479444543488449547487568897468683955886935535694896858528355443457358667243642313225326142635412
433165134443115323655412565336574774363263823339637755748738478844753443366543756864599667497478638535364437368324232432351147613376615461324
255546365535224352467626565444446263832366733855339686844454779545954833997374664863737346696795866578234664656443247566163775227133522126211
332543346224456342457145637872588878872574934465846438696585998768959393446858386444585949749989395845243437522874257474667424163321432143662
562336531135536464571531445325786432525654973537497993963876555849853689467557948538984566573893374699522258566835263827361447616765121531241
134431331273426633773265462863548226445269397663747657533667545839948559886569784664389446348545683389848688445244623781735357464754775332441
455514441477666641215728225436682865472376638684673865686537967585959697777945778763958683986999446946735832744256768434443442331647672323162
642551661752757431115132444368754488566587583899343636597956846969766697666696549958595334986455854649598564858883536552667547462457766361136
523135446552147326745727437763658824294779583474959943837486894449889786848545858986984945998848759695488574225628248774221513366313255152244
662142534574774471476733285584773353469368338384693894458894844555764768998647478459784635737579344766346566445772776385244757261641646262231
426164675347223367356542678766487676449383835573944385678679999588547686484865465688679958436853663379986545474734678688476311743671535264562
636221515617411216247337338427225735479885464746489395486445598697885986665448699866884656794474879996386956934725254526364324475256241275663
631655547723135622724356638578268487796375786548339985946895559755594954857979446575876457888866863986588685442687887862434325557242465434334
526561675234753571754873872743282697865877868743798687568577798587569899574484554484486596454938697634387879836757377864647232634674626657136
224367751471353647528352332475353678438596388378986467455448887646465576695666985755458794657464949967358875375525855268833747673643621712113
555155247624263644685247526382749435467889975896454465589895886678995785898565848957859844445874878643778658535937624565377735216144455146652
326237275165115664286248564635235597494984939548556988958465866659979766684556496568777489668689659466945846453722248242466764614544772336545
252431512527441277652682654526537378589387973677795869974677788748496486946677468975449899885555473979374748343648488332525562346344443772553
334445255752755383853263265588439634448596738474455889458598988975979996868859879877898797766766846958879864596965328638267846232745551326455
331776676677775667763658323247548647473346994464947655845774859797686965997669898985478769844957676563749678677496544457376882437561732771415
524166432536425482552537234634638489648635668489984866757588557998759988879759786984579576979588678858478864969749575527756262527122755635643
621727645151575887576234428334879934367558864978956787976575789687695598659778579995684454959976779569644787946544773527367553271175577267671
146536267557111863546535476546756933855578657694848587666677867759855877966869976666895795977754986464958576833534434856257276637677672374622
627162456571435862223277266645437845769458457477859464885659565779885987687868765787589649788985577888968356376393555423832745685215266467517
356365425561522443354482823779863564644867657899958444967567857769895796968885877556985858769679467875486466963448536675724876383637637347332
662617714433245736446788383839477478955657876855994484679589576895957757596689789878757698854677478674545986936783367487553578825131414257161
332752445446138652863525378663559896379746684495687998757655759676957899686977876787997889474577748675663489587853377638443448848132472112131
453742717451167763344725476499465974694977569678544576559869769779787858777859878659995587547699787885775974835467735257544662734254664167234
637433522225172664387548695933565599774766649475487879985879567866859778897575697897755575969866878866559366585534438655344868386256513661571
546147626464562275655733897739395889457894577877799798775969558887665695975589685557965565588684599794655433543949864872227536744356275446534
466362637642348545833267889637543575568589757869745856956895658665988768997999655989667957999546697465848679934687374434356755244437463163527
432241752456735627523255338945585453647447657554545955769795789789997877986787567985578897759678944769468657795794576536268322838744716172531
362335524521283767267868233894954334695664994778485687755666859567896666877777856977986957755786769546887535444947538736628443346847462743523
242277366552744663233252489644883664499486849778665576798778978997766697987689796855857957659765978885748744987558355833587345887644235437312
561476674157528347537548599693576474885768577976886585698957697776687879979969876766765577555667674874858777897543556687327834848556466137735
266443423617535645753445779387753884547464964579665696566776797688777799889668699855885667595966647668866856763675976465687353888681336245316
572245756261228737774356774434644334465597956478659678566557786678987687767797677855856669659856465546998943449649767856528226362754511645257
765454637722232528732727987873694678786897686957758658776958776876669697776896797985686878577656659767548457559453559953286436834721254612345
715574444332523722776764939533778537899944495848987975789655786679777697866668686698596879975965745866774945968874839792274752686441541427615
345426643746658264878244879834877886854849486559776688568989799999769977869688867896566869679855957757568478643556858683764734437851357452275
155264155457638423874255465346979399784764447766558558566789767877968796988868867775556888798564684589499477496386865936552684743662561437775
556553777462428352772346536564948445645848965477587585797665668668998889899669897695759889687557667557584743537744477835564286662643223525755
641634624577764727436225779978964774555745645897796877559888677666767998968896788888689868597664985685858554356376665498623746875723662152372
273464717234862288588878479738499968679778769844967858766886688999898688976778797877666987697667878994996657354955977482446733867376656676652
551452257437387582588858645358387357746754779495965859595599878879877987668898767897997855656868855556757747486357487665847763562466422346611
563771242132683432222557436749937783648584568946588665665565698788787787998889676985866968796874695585557699853673538872377582853855131713461
621754271237543666875247946859748999855959977745986585788867866697696868789869768995576776679784564654855987787897358797454368778485716675345
164557236272472546822232846668399389759849987667659785676559867986867888878979688978688695876854496969468763957695738688223564746777531171265
242346713471432688725345548968585493977887799777998877589665998798978979687788866756996567759999475865446943768859868732555538748467434116221
724542325744422353827368477965435394957587656594657956589558869678779879978997989779557567777576965957979596983484379373273827325462765413315
134467152455573564745453678895499973399455464974855888996756898968898666769686667565559598686586858797879648838954569323385654838463315425344
677644725227283525233274374448443847867587946496756687655559798668967889678966568857686688687474797656795664978587359585475743444537567171372
336331514454173343536876798555466989966569868897467756888959675759587897868888779865575958968754759769695636436637498444722662454277255276665
245372163442533628423276455934688944899667958898697795685589868988659597757695978985568755897588876768955385979973858688872756554467423674135
251472373172465268687323637558467886966997454586679595656555799786788685987977899567657589878679656758649535738838795357634278627632741221151
165461424121142643385468264846788537647578965477849879999585588788675566556988859776968656866748767857679947367996538366526226283326214137262
552347532473355256876326459866563676749894796886745598856867798578859675999778699689958599985994868557485944545796355254658552388764762637577
411635777264744624762842767953597944883658696686489566856859985666787779576968666779658795444747587477754964887759644474728635835454465116123
525225774221277357825768273779533699948575746956759694897959969678678956879656896656877599855484649666456453586543836385766273838732235171565
413446335411722332567467583938598777437966488478684886785797667899976899669555696776775778568978567578544555855646936463366758257267556526367
232225126611437885288888224674796768654898896446868958777899786966689959778798898557578584894674968778348499974537656632752837285262221612562
312524227137512563356783624765555493696544874684948745994767775568987755855875779575947858745547754676685368397837548474384853754524257634625
164576266612155222885335524447458943676659664764845487449595699877699967897599959997454474895848957865889443963557382768878244863267411634354
343423173533275137862288876573755898763474747556889894445589898998965697755557969845649449784567454999596856689395535336738467324251433443313
324642722572242663573535885523747435878468838854477747966756946868979567855589567654976484995966698365838477364437873477732253364252715313424
633536551523473523243244283326385679995773658874569756469784895788454454466967676647864944477548686957835935734344472886742338655365237743545
126254446714213213436657334784236857866388445465965986588698754599946596568588549887968594867664769467935498667776266236524482164321464331744
632122261674245423458774627724266986994837445876996574698444995879887876557659858469744965457586679894948948458686783436673327143364537263243
465244311333114323725266442638884838436463333596776867596749549964879559765764848754756989656759354743483867679752528468865454711412437437215
261415356334624227658332247423732949399345845987468987484698858676956555788758758658656776848894849855333685652263222425756836554766646272443
521646365566326414152826643636235965753596433593485485995795654765798865954954774954854696879635646973347786334722533446758821117733417454123
252365462474552424777626563728632557857897556978697654768788568859684765969498588674456548639599966588966387644635645878744172627175772722511
322111677544534553154787663277355446646868855664534468569956798568597597797985774677475959647634668749666469868462232582736411761171527151611
612342244172321553733876453434327274768778644399663358375677775959999689866565698576678735898955879849469468533635274885381342774377452254623
651234151461371123426165832588863365476947993573539948648464444454868478568755779686456634875633856784657866623534635827356542713775643236154
426422164365351275264187473582686768433977556986656756547883959898696745877867456753466554348833684967659438745566626826373666115341437512356
251224616536545656545722482674755228883867595576787346349774537744798879665975566954395436673954998843688762228354424347472522235531376331326
335541164543114144761463764542372366287647948934896437773435546559497746964557357657989773374388363578827574482885664583611615165136533323225
261331415374732264655453647768254758542843666899665464693864936867468988485548354636569486458753866966873563534677586636515154572216163145356
313232345646561617413414322476366687653335889569688478593764445835478384478864579889578586636387865692637456447655326361775525421537351443252
354422624313221353436553153273228525734583687565383399578579988847365867834335367495554595854533343462877332872884662534165677211161214245532
542143423513624235434762263462784556783874775748777548864766786566666483439848384735573868946946858786326267558486871376536352777136111223641
563426221453513247534322123144884253486238658666956647949649676497797648994455393587476533436988875438823554657527344561756544414561541432165
142324116651521772664345223478653548388638657544743867958975353393743498698444676463749436355523368338437534752654673372352117774565612455142
521252364664151234171376543732684442243322874775475946689463578554843486635378489996373438934348323722334326883767125435113461472456453544434
366456342146455776343221412213427758323428237676455365546898955778897855479458369598384867528536647227825337245572327613615476534655616364436
456262313325465615634626471552134825254874668258282367564793649864648953456359464348433437556572444858443732283547165236722572136426516552255
215214555215121531363153365156745726838285476672588458468636756485794378474346453448633724336222848523788322461363427143622643764542154516631
445435243132162412737127746252357518384582434632727743323776457988789744747556744546232245626842323687453554237454472415624653454464312353566
413512155566552553344114742623626673426573822753222774627337845846626888678573728525426326742682452368847826463175721614615753615514521215131
121335422224363443354722134157661571538463676346636753673773667735542264247284835668253673727235386467366265255634467667311151641335353324222
124223214542653663566665314176475124517877488374766545574687862278742556456474375457627645727273436443464373242226321257155151623466354226535
224342321546661552253517421437534637164144462465386448554748656436426565223525648357863358822784435247243523427371615216772115551454466464444
152151341446215313532274524113276662527567472536387628785437566568247675623344644462557726773438776443134255637564367716346225361466131111152
441131264554242642424433222772464422143526743636387232724335464526838833628275276362774824878543373332675711255316334646112165166145436225355
222223346255612511131365546422132224534414716137367462626727462537235434658525224753354265433542656353255435456465556334646626646616114541252
122254524154564644355156315711257331373433572663242435353634872647446868386788243424223288834522715673434774222724734714143326426614126132222
512124425315656654512332445376341167415722616144652756353244273445678654828624424884532254424714514364625764637237362662611534611466615252341
144321153255241633164514444655277754717616621362745215268637475632553485326364864874882263216537664313267663452313553535362633636242154324325
215522151121146641113121366265573756214663745551174365226877835824533746627332877664426625513336257243467577673364646532514644421421452544444
335313335414162252122432222633336424453112573546364534773326574784656537542222587263555442637622533151434567664221616224322511431465543243151
554515254153443453616316365142667412367456471655714423572426445365634244714461517246763535321157222422452237455335224412113513116341541551245
242342552224414663454122443156612324424462742634773552556733543127575614737735454524176471342351442215257671354234543465566226442453421214332
423332221231152525435143325351441332245166165545746441225161776522365226425741716113757265346324464231517554455663426161163531133151125441514
424112342444153352442235323533255342273475361517511641775633616543162217257766644611574212127347362451473365646541415632262325644422215452323
535123215132355441452363223224326111142177116662677154564514756736116151566423375123522315721736346462721611643433515643226113553235433255245
224211552121124334331251616112654554353552524371574216334214517671732613731631733667464726623341735667366531311523356541525225553551524513511
133135253512342521415314125243161342522122244673535175332435771431335676512526131661651773762677772541211631242452526663421451534253432541324
332331532553424153415425566412652656345152461311365447431514137764335267535631223555617762772366325564623566653643641356522511155115525413323
124122513322542451532212635122623231342565341643435327641416177253251451471617514752111736553524423266211413554453514154155451335251224234321
114322223311332542521324344432242254215112631121532433351616521421133465333644152516113467545556154614445514451441162115222213523543445151233