Neşeli gerrymandering


26

Arka fon

Amerika Birleşik Devletleri’nin kendine özgü bir avlanma sevgisi var - bir seçim bölgesinin belirli oy kullanma sonuçlarını öngörmek için kasıtlı olarak manipülasyonu. Daha yakın bir zamanda , Yüksek Mahkeme huzurunda açılan bir gerrymandering davası vardı . Gerrymandering, özellikle ırk ile ilgili olduğunda yasadışı olarak kabul edilir ve bölge sınırlarının yeniden çizilmesi gerekliliği ile sonuçlanır.

Bir belediyenin dikdörtgen haritası (2d dizisi) göz önüne alındığında, partinizin en fazla temsili almasına yardımcı olmak için ilçe çizgileri çizeceksiniz. Yani, sen gerryman olacaksın. Her belediye iki tarafı vardır, 0ve 1. Harita, üzerinde 0veya 1üzerinde olan karelerden oluşacaktır . Örnek bir harita:

Meydan okuma

Haritayı, bölgelere göre gruplandıracaksınız, böylece 1taraf en azından Girdi tarafından belirtilen bölge sayısını elde edecek.

Giriş

Girdi bir harita, çekilecek ilçe sayısı ve 1partinin kazanması gereken asgari ilçe sayısından (asgari puan) oluşacaktır .

Çıktı

Çıktı ilçelerin haritası olacak. Her bölge benzersiz bir şekilde alfabenin büyük harflerinden oluşacaktır. Evet, bu 26'dan fazla ilçenin olmayacağı anlamına geliyor.

Girilen tarafın yeterince ilçe kazandığı yerlerde olası bir çıktı yoksa, ya:

  1. “Denedim…” yazdır
  2. Ölümcül hata, çünkü parti seçim sonuçlarıyla onarılamaz şekilde yaralandı
  3. Ya da her ikisi de

Kurallar (ayrıca çok önemli)

  1. Tüm bölgeler bitişik olmalı
  2. İlçelerde başka ilçeler olmayabilir
  3. Her ilçede en az dört düğüm bulunmalıdır. Girdi kurallarla tutarlı olacak, yani number_of_districts * 4haritada en az düğüm olacak
  4. Her bir tarafın puanı, çoğunluğa sahip olduğu ilçelerin sayısıdır.
  5. Bir bölge aynı sayıda 0s ve 1s'ye sahipse, taraflardan hiçbiri bundan yararlanamaz.
  6. Normal hile yapma kuralları
  7. Bu , bayt cinsinden en kısa kod kazanır.

Test durumları

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     

Tabii ki, programınız için çalışması gerektiğini herhangi geçerli bir test durumu, sadece bu olanları.


@Arnauld, evet onlar sadece açıklayıcıdır. Gerçek çıktı, ilk testte alfabenin harfleri ile aynı olmalıdır. Etiketi bunu yansıtacak şekilde değiştirdim.
Daniel

İlk test durumda basit bir bölme şey olurdu böyle . Bu doğru mu?
Arnauld

@Arnauld, evet, bu geçerli.
Daniel

Öyleyse, 3. örnek için, her birini 1 ilçe yüksekliğinde, yatay sıralara bölersek 1'ler 3'e 1 kazanır mı?
Michael Dorgan

3
Bu bana DMG'den DS'ye kadar Nintendo el cihazlarında char tabanlı grafikler için yapılması gerekenleri hatırlatıyor. Grafikleri kesmek için size özel şekiller verildi ve yalnızca donanımda tanımlanmış sayıda sprite (şekil) kullanımda olabileceğiniz için kullanılan şekil sayısını en aza indirmeniz gerekti. Bu kolay bir problem değildi.
Michael Dorgan

Yanıtlar:


6

R , 938 896 858 952 bayt

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="
"))}}}

Çevrimiçi deneyin!

Büyük > 900 > 800 (hayır!)> 900 baytlık çözüm. Kod aşağıdaki gibi çalışır. N, seçim bölgelerinin sayısı ve M'nin 1'in çoğunluğunun olmasını istediği asgari ilçe sayısı.

İlk olarak, kod rastgele N ilçelerini farklı gruplara atar. Daha sonra, onları rasgele genişletir, yani rasgele seçilen bir gruba bir ilçe ekler, ilçenin zaten o gruba ait bir ilçenin yanında olmasını sağlar. Genişleme sürecinde, bölge grubu henüz tam 1 çoğunluk değilse, 1’lik çoğunluğu olan bir ilçeye öncelik tanır; eğer grup zaten 1 çoğunluğa sahipse, o zaman 0 ilçesine öncelik verir. Tüm bölgelere atanana kadar devam eder.

1 parti için çoğunluğun olduğu her grup saklanır ve ilçeleri kilitlenir. Eğer çoğunluğu 1 olan en az M grubu varsa, o zaman her şey iyidir ve sonucu yazdırabiliriz, her grupta en az 4 bölge olup olmadığını kontrol edebiliriz. 4 ilçenin kesilmesi sağlandığında sonucu mutlu bir şekilde yazdırabiliriz. Aksi halde, kod mümkün olduğu kadar çok gruba, yani N - # depolanmış gruba kilitli olmayan bölgeleri yeniden atama girişiminde bulunur.

Kodlar birkaç kez dener (9 kez). Başarısız olursa, her şeyi sıfırlar ve yeniden başlar. Diğer 9 kez pes etmeden ve "denedik ..." yazdırarak yapar.

Kod ilk önce başarılı olmazsa, birkaç kez tekrar deneyin. Tekrarlama sayısını TIO'da bir dakikadan daha az çalışacak şekilde ayarlamıştım. Ancak bir çözüm varsa, bu kod (sonunda) bulabilir. Algoritmanın rastgelelik kısmı, bir çözüm varsa, bulabileceği sıfır olmayan bir olasılık verir. Sınırlı sayıda deneme, başarıyı sınırlayan tek faktördür.

DÜZENLEME: bölge grubu, belirli bir meydanın kenarındaki bölgelere sahip olmadığı sürece, hiçbir bölge grubunun bir başkası ile tamamen çevrilemeyeceği kontrolünü ekledi. Sanırım ilk başta özledim.


Yeni satırları kaldırabilir misiniz?
Hayır,

Yaptım. Ayrıca, tek harflere daha uzun fonksiyon isimleri verdim ve değişkenin kesin olarak tamsayı ve pozitif ==0olması <1durumunda birkaçını kullandım.
NofP

1
Burada önemsizce golf oynayabilecek pek çok şey var, ancak bu bir cevapta iyi bir ilk girişim, yani +1, ve ben de telefonumda olmadığımda birkaç saat düzenlemeleri önereceğim!
Giuseppe,

1
858 bayt - "normal" golf, if...elseifadeler ile parantez kullanımını temizleme , değiş tokuş cyapma as.vector, değişmeyen "\n"yeni satırlarla değiştirme ve >sayıları otomatik olarak karakterlere zorlayacak ve kod noktalarını karşılaştıracak gerçeği kullanma . Muhtemelen hatırlayamadığım başka golf var ama bu bir başlangıç. Tweak yapabileceğimiz birkaç şey olduğunu düşünüyorum ama kodu anladığımdan% 100 emin değilim ...
Giuseppe

Güzel bir! İlham aldım. Kodunuzu karşılaştırarak da madende bazen çok küçük ilçe gruplarına (4 bölgeden az) yol açabilecek bir hata buldum. Şimdi düzeltildi.
NofP
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.