Ce problème ressemble à la partie 2 du jour 10 de cette année.
La première partie peut être aisément fait avec un parcours en largeur/profondeur mais ça devient clairement impossible pour la partie 2.
Remarquons que l'on cherche à trouver le nombre de sommets de coordonnées entières situées à l'intérieur d'un polygone.
On va donc de baser sur le théorème de Pick et la shoelace formula.
La shoelace formula est une formule pour calculer l'aire d'un polygone.
Si les sommets du polygone sont (x1, y1), ..., (xn, yn) alors l'aire du polygone est |x1 y2 - y1 x2 + ... + x_{n-1} yn - y_{n-1} xn + xn y1 - yn x1| / 2
Le théorème de Pick donne une formule pour calculer le nombre de points intérieurs à un polygone à partir de son aire (qui est calculé par la shoelace formula) et du nombre de points à sa frontière (c'est juste la somme des distances données par les instructions).
La formule est la suivante: A = i + b/2 - 1 où A est l'aire, i le nombre de points à l'intérieur et b le nombre de points à la frontière.
Pour calculer le nombre de "#" total, il faut faire la somme i + b où i = A - b/2 - 1.
Donc, voici le code Haskell
dataDirection=Up|Down|Left|RightdataInstr=Instr!Direction!InthexToInt::String->InthexToInt=foldl'(\accx->acc*16+hexDigitToIntx)0wherehexDigitToIntx|isDigitx=ordx-ord'0'|otherwise=ordx-ord'a'+10parser::Parser[(Instr,Instr)]parser=instr`sepEndBy1`eolwhereinstr=dodir1<-direction<*" "len1<-decimal<*" (#"len2<-hexToInt<$>count5hexDigitChardir2<-direction2<*")"pure(Instrdir1len1,Instrdir2len2)direction=choice[Up<$"U",Down<$"D",Left<$"L",Right<$"R"]direction2=choice[Right<$"0",Down<$"1",Left<$"2",Up<$"3"]trenchPoints::[Instr]->[V2Int]trenchPoints=scanl'go(V200)wheregop(Instrdirlen)=p+casedirofLeft->V20(-len)Right->V20lenUp->V2(-len)0Down->V2len0-- return the double of the polygon areashoelaceFormula::[V2Int]->IntshoelaceFormulapoints=abs$sum(zipWithgopoints(drop1points++points))wherego(V2xy)(V2x'y')=x*y'-x'*y-- via Pick theorem and Shoelace Formula-- https://en.wikipedia.org/wiki/Pick%27s_theorem-- https://en.wikipedia.org/wiki/Shoelace_formulasolveFor::((Instr,Instr)->Instr)->[(Instr,Instr)]->IntsolveForfinstrs=boundary+interiorwhereinstrs'=mapfinstrsdoubleArea=shoelaceFormula(trenchPointsinstrs')boundary=sum[len|Instr_len<-instrs']interior=(doubleArea-boundary)`div`2+1solve::Text->IO()solve=aocparser(solveForfst)(solveForsnd)
# Solution en Haskell
Posté par Guillaume.B . En réponse au message Advent of Code, jour 18. Évalué à 3.
Ce problème ressemble à la partie 2 du jour 10 de cette année.
La première partie peut être aisément fait avec un parcours en largeur/profondeur mais ça devient clairement impossible pour la partie 2.
Remarquons que l'on cherche à trouver le nombre de sommets de coordonnées entières situées à l'intérieur d'un polygone.
On va donc de baser sur le théorème de Pick et la shoelace formula.
La shoelace formula est une formule pour calculer l'aire d'un polygone.
Si les sommets du polygone sont
(x1, y1), ..., (xn, yn)alors l'aire du polygone est|x1 y2 - y1 x2 + ... + x_{n-1} yn - y_{n-1} xn + xn y1 - yn x1| / 2Le théorème de Pick donne une formule pour calculer le nombre de points intérieurs à un polygone à partir de son aire (qui est calculé par la shoelace formula) et du nombre de points à sa frontière (c'est juste la somme des distances données par les instructions).
La formule est la suivante:
A = i + b/2 - 1où A est l'aire, i le nombre de points à l'intérieur et b le nombre de points à la frontière.Pour calculer le nombre de "#" total, il faut faire la somme
i + boùi = A - b/2 - 1.Donc, voici le code Haskell