Jolly gerrymandering

26

Contexte

Les États-Unis ont un amour unique du gerrymandering –– la manipulation délibérée d'une circonscription électorale pour prédire certains résultats de vote. Tout récemment, il y a eu une affaire de gerrymandering portée devant la Cour suprême. Le Gerrymandering, en particulier lorsqu'il est lié à la race, est déclaré illégal et entraîne l'obligation de redessiner les lignes du district.

Étant donné une carte rectangulaire d'une municipalité (tableau 2D), vous dessinerez des lignes de district pour aider votre parti à obtenir le plus de représentation. Autrement dit, vous allez gerrymander. Chaque municipalité a deux partis, 0et 1. La carte sera composée de carrés avec 0ou 1sur eux. Voici un exemple de carte:

Défi

Vous regrouperez la carte en districts afin que le 1groupe obtienne au moins le nombre de districts spécifié par l'entrée.

Contribution

L'entrée consistera en une carte, le nombre de districts à dessiner et le nombre minimum de districts que le 1parti doit gagner (le score minimum).

Sortie

Le résultat sera une carte des districts. Chaque district sera composé uniquement d'une lettre majuscule de l'alphabet. Oui, cela signifie qu'il n'y aura pas plus de 26 districts.

S'il n'y a pas de sortie possible où le parti saisi gagne suffisamment de districts, soit:

  1. Imprimer "Nous avons essayé ..."
  2. Erreur fatale parce que le parti a été irrémédiablement blessé par les résultats des élections
  3. Ou les deux

Règles (également très importantes)

  1. Tous les districts doivent être contigus
  2. Les districts peuvent ne pas avoir d'autres districts en eux
  3. Chaque district doit contenir au moins quatre nœuds. L'entrée sera conforme aux règles, ce qui signifie qu'il y aura au moins des number_of_districts * 4nœuds dans la carte
  4. Le score de chaque parti est le nombre de districts où il a une majorité
  5. Si un district a le même nombre de 0s et 1s, alors aucune des parties n'en profite
  6. Règles normales de non-triche
  7. C'est le , donc le code le plus court en octets gagne.

Cas de test

1. Input       1. Output       2. Input       2. Output     3. Input      3. Output
districts: 5   Image and map   districts: 3   Image below   districts: 3  fatal error
min wins: 3                    min wins: 3                  min wins: 3
map:                           map:                         map:
00000110000    AAAAAAAAAAA     101101                       101101
10000010000    AAAAAAAAAAA     100000                       100000
10010000011    AAAAAAAAAAA     011011                       011011
11001110000    BBBBBBBAAAA     111111                       100111
00111111000    BBBBBBBAAAA     
01111111000    CCCCCDDDAAA     
01111111001    CCCCCDDDAAA     
01000111100    EEEEEDDDDDD     
00000001000    EEEEEDDDDDD     

Bien sûr, votre programme devrait fonctionner pour n'importe quel cas de test valide, pas seulement pour ceux-ci.

Daniel
la source
@Arnauld, oui, ils ne sont qu'illustratifs. La sortie réelle devrait être comme dans le premier cas de test avec les lettres de l'alphabet. J'ai changé la balise pour refléter cela.
Daniel
Une simple partition du premier cas de test serait quelque chose comme ça . Est-ce exact?
Arnauld
@Arnauld, oui, c'est valable.
Daniel
Donc, pour le 3ème exemple, si nous le divisions en rangées horizontales, chaque 1 district de haut, alors les 1 gagneraient 3 à 1 oui?
Michael Dorgan
3
Cela me rappelle beaucoup de ce qui devait être fait pour les graphiques basés sur les caractères sur les ordinateurs de poche Nintendo de DMG à DS. On vous a donné des formes spécifiques pour découper les graphiques et vous avez dû minimiser le nombre de formes utilisées car vous ne pouviez avoir qu'un nombre défini de matériel de sprites (formes) en cours d'utilisation. Ce n'était pas un problème facile.
Michael Dorgan

Réponses:

6

R , 938 896 858 952 octets

function(N,M,m){U="We tried...
"
L=length
A=matrix
W=which
K=sum
S=sample
G=unique
H=function(s,p=s-1){Y=S(c(s-j,s+j,p*(p%%j>0),(s+1)*(s%%j>0)))
Y[Y>0&Y<=k]}
C=function(v,z=W(r==v))K(z%%j<2,z-j<0,(z+j)>k)
m=A(strsplit(m,"")[[1]],1)
i=W(m<0)[1]-1
m=((t(A(m,i+1))[,1:i]>0)-.5)*2
if((K(m)<M&(N-M)<1)|K(m>0)<(3*M))cat(U) else{j=max(1,nrow(m))
k=i*j;w=g=T
while(w<9&g){Z=R=N;Q=M;b=0
r=A(0,j,i)
while(b<9&g){s=W(r<1)
s=s[S(L(s))][1:min(L(s),R)]
r[s]=1:L(s);a=0
while(K(r<1)>0&a<(k^2)){a=a+1
s=S(W(r>0&r<=R),1);p=r[s]
Y=H(s)
Y=Y[r[Y]<1]
if(L(Y)){Y=Y[order(m[Y])]
if(K(m[r==p]>1))r[Y[1]]=p else r[Y[L(Y)]]=p}}
if(a<(k^2)){for(v in 1:R){if(K(m[r==v])>0){r[r==v]=max(k,max(r))+1
Q=Q-1;Z=Z-1}}
if(Q<1){g=F
for(v in 1:R)r[r==v]=max(k,max(r))+1
for(v in G(c(r)))g=g|(K(r==v)<4)|(L(G(r[H(W(r==v))]))+C(v))<3}}
b=b+1;r[r<=R]=0;R=Z}
w=w+1}
if(g)cat(U) else{u=G(c(r))
for(v in 1:L(u))r[r==u[v]]=v
cat(paste(apply(A(LETTERS[r],j,i),1,paste,collapse=""),collapse="
"))}}}

Essayez-le en ligne!

Une solution massive > 900 > 800 (non!)> 900 octets. Le code fonctionne comme suit. Soit N le nombre de circonscriptions et M le nombre minimal de circonscriptions où 1 souhaite avoir la majorité.

Premièrement, le code attribue au hasard N districts à différents groupes. Ensuite, il les agrandit au hasard, c'est-à-dire ajoute un district à un groupe sélectionné au hasard, garantissant que le district est à côté d'un district appartenant déjà à ce groupe. Dans le processus d'expansion, il donne la priorité à un district à 1 majorité, si le groupe de district n'est pas encore à 1 majorité; si le groupe est déjà une certaine majorité 1, alors il donne la priorité à un district 0. Elle se poursuit jusqu'à ce que tous les districts aient été attribués.

Chaque groupe où il y a une majorité pour le 1 parti est stocké et ses quartiers sont verrouillés. S'il y a au moins M groupes avec une majorité de 1, alors tout va bien et nous pouvons imprimer le résultat, nous pouvons vérifier s'il y a au moins 4 districts dans chaque groupe. Si le seuil de 4 districts est respecté, nous pouvons imprimer le résultat avec plaisir. Sinon, le code essaie de réaffecter les districts qui ne sont pas verrouillés à autant de groupes que possible, c'est-à-dire N - # groupes stockés.

Les codes essaient plusieurs fois (9 fois). S'il échoue, il réinitialise tout et recommence. Il le fait pour 9 autres fois avant d'abandonner et d'imprimer "nous avons essayé ...".

Si le code échoue au début, réessayez plusieurs fois. J'ai réglé le nombre de répétitions de sorte qu'il puisse fonctionner dans TIO en moins d'une minute. Cependant, s'il existe une solution, ce code peut (éventuellement) la trouver. La partie aléatoire de l'algorithme donne une probabilité non nulle que, s'il existe une solution, il puisse la trouver. Le nombre limité d'essais est le seul facteur limitant de réussite.

EDIT: ajout du contrôle qu'aucun groupe de district ne peut être entièrement entouré par un autre, à moins que le groupe de district ait des districts sur le bord de la place donnée. Je pense que je l'ai raté au début.

NofP
la source
Pouvez-vous supprimer toute nouvelle ligne?
NoOneIsHere
J'ai fait. J'ai également attribué des noms de fonction plus longs à des lettres simples et j'en ai remplacé quelques-uns ==0par <1lorsque la variable était strictement entière et positive.
NofP
1
Il y a beaucoup de choses ici qui peuvent être insignifiantes, mais c'est une bonne première tentative de réponse, alors +1, et je proposerai des modifications quelques heures une fois que je ne serai pas sur mon téléphone!
Giuseppe
1
858 octets - « réguliers » Golfs, le nettoyage de l'utilisation des accolades avec des if...elsedéclarations, l' échange cpour as.vector, changeant "\n"avec des sauts de ligne littérale, et en utilisant le fait que >seront automatiquement les numéros de COERCE à des personnages en silence et comparer leurs points de code. Il y a probablement d'autres golfs que j'ai fait dont je ne me souviens pas, mais c'est un début. Je pense qu'il y a quelques autres choses que nous pouvons modifier, mais je ne suis pas sûr à 100% de comprendre le code ...
Giuseppe
Joli! J'ai pris l'inspiration. En comparant avec votre code, j'ai également trouvé un bug dans le mien qui conduisait parfois à de très petits groupes de district (moins de 4 districts). Il est maintenant corrigé.
NofP