In een bepaalde regio liggen er heel wat ziekenhuizen dicht bij elkaar. De concurrentie tussen deze ziekenhuizen is moordend, en dat valt letterlijk te nemen. Bij noodoproepen worden patiënten door een ziekenwagen immers niet altijd naar het dichtsbijzijnde ziekhuis gebracht. Hierdoor gaat kostbare tijd verloren, soms met dodelijke gevolgen. De plaatselijke overheid wil hier paal en perk aan stellen, en vaardigt een nieuwe regelgeving uit die ziekenwagens verplicht om hun patiënten altijd naar het dichtsbijzijnde ziekhuis te brengen. Hiervoor moet een plan opgesteld worden dat de regio opdeelt in zones waarin telkens één ziekenhuis gelegen is.

zoneplan euclidisch
Zoneplan dat werd opgesteld voor 20 ziekenhuizen (gelegen op locaties aangeduid met een zwart punt), waarbij afstanden berekend werden op basis van de Euclidische afstand.
zoneplan manhattan
Zoneplan dat werd opgesteld voor 20 ziekenhuizen (gelegen op locaties aangeduid met een zwart punt), waarbij afstanden berekend werden op basis van de Manhattan-afstand.

De overheid vraagt je om een indeling van een regio te maken, zodat het dichtste ziekenhuis op elk punt in een zone telkens het enige ziekenhuis is dat in die zone gelegen is. De individuele ziekenhuizen willen echter hun invloedssfeer zo groot mogelijk houden, en daarom is er nog wat discussie over de manier waarop de afstand tussen twee punten moet berekend worden. Onderstaande tabel bevat een aantal mogelijke definities die de ziekenhuizen hebben voorgesteld om de afstand tussen twee punten $$(x_1, y_1)$$ en $$(x_2, y_2)$$ te berekenen.

naam formule
Euclidische afstand $$d=\sqrt{(x_1-x_2)^2 + (y_1-y_2)^2}$$
Manhattan-afstand $$d=|x_1-x_2| + |y_1-y_2|$$
schaakbord-afstand $$d=\max(|x_1-x_2|,|y_1-y_2|)$$

Opgave

Beschouw een rechthoekige regio waarin een aantal ziekenhuizen gelegen zijn. We hebben deze regio opgedeeld in vierkante cellen die een rooster vormen, zodat elke cel hoogstens één ziekenhuis bevat. De rijen en kolommen van het rooster worden respectievelijk van boven naar onder en van links naar rechts genummerd vanaf 0. De cellen van het rooster waarin een ziekenhuis gelegen is, markeren we met een (unieke) hoofdletter en de overige cellen markeren we met een punt. Daardoor kan de ligging van de ziekenhuizen in de regio voorgesteld worden door een kaart die de volgende vorm heeft:

......B..
.........
...A.....
.........
.......D.
.........
.C.......
.....E...
.........

De positie van een cel in het rooster wordt voorgesteld door een tuple $$(r, k)$$. Hierbij stelt $$r$$ het rijnummer en $$k$$ het kolomnummer voor van de cel in het rooster. Gevraagd wordt:

Voorbeeld

Bij onderstaande voorbeeldsessie gaan we ervan uit dat het bestand ziekenhuizen.txt1 zich in de huidige directory bevindt.

>>> euclidischeAfstand((0, 0), (3, 4))
5.0
>>> manhattanAfstand((0, 0), (3, 4))
7.0
>>> schaakbordAfstand((0, 0), (3, 4))
4.0

>>> posities('ziekenhuizen.txt')
(9, 9, {(0, 6): 'B', (4, 7): 'D', (7, 5): 'E', (2, 3): 'A', (6, 1): 'C'})

>>> dichtste((0, 0), {(0, 6): 'B', (4, 7): 'D', (7, 5): 'E', (2, 3): 'A', (6, 1): 'C'})
'A'
>>> dichtste((8, 8), {(0, 6): 'B', (4, 7): 'D', (7, 5): 'E', (2, 3): 'A', (6, 1): 'C'}, afstand=manhattanAfstand)
'E'

>>> zones('ziekenhuizen.txt')
aaaabbBbb
aaaaabbbb
aaaAaabdd
aaaaaaddd
ccaaaddDd
cccceeddd
cCcceeedd
ccceeEeee
ccceeeeee
>>> zones('ziekenhuizen.txt', afstand=manhattanAfstand)
aaaabbBbb
aaaaabbbb
aaaAaabdd
aaaaaaddd
ccaaaddDd
cccaeeddd
cCcceeedd
ccceeEeee
ccceeeeee
>>> zones('ziekenhuizen.txt', afstand=schaakbordAfstand)
aaaaabBbb
aaaaabbbb
aaaAaabbb
aaaaaaddd
caaaaadDd
ccccedddd
cCcceeedd
cccceEeed
cccceeeee
>>> zones('ziekenhuizen.txt', 'zones.txt')