ジョリーゲリマンダリング


26

バックグラウンド

米国には、ゲリマンダリングに対する独特の愛情があります。特定の投票結果を予測するための選挙区の意図的な操作です。つい最近、最高裁判所に持ち込まれたゲリマンダー事件がありました。ジェリーマンダリングは、特に人種に関連する場合、違法と判断され、地区の路線を変更する必要が生じます。

自治体の長方形の地図(2次元配列)を指定すると、地区の線を描画して、パーティが最も表現しやすくなります。つまり、ゲリマンダーになります。すべての自治体には2つの政党が0あり1ます。マップは、いずれか0または1その上の正方形で構成されます。以下にマップの例を示します。

チャレンジ

マップを地区にグループ化して、1パーティが少なくとも入力で指定された地区の数を取得できるようにします。

入力

入力は、マップ、描画する地区の数、および1パーティーが勝つ必要がある地区の最小数(最小スコア)で構成されます。

出力

出力は、地区の地図になります。各地区はアルファベットの大文字で一意に構成されます。はい、これは26以上の地区がないことを意味します。

入力されたパーティが十分な地区に勝つ可能性のある出力がない場合、次のいずれかです

  1. 印刷してみました...
  2. 選挙結果により党が取り返しのつかないほど負傷したため、致命的なエラー
  3. または両方

ルール(非常に重要)

  1. すべての地区は連続している必要があります
  2. 地区には他の地区がない場合があります
  3. 各地区には、少なくとも4つのノードが必要です。入力はルールと一致します。つまりnumber_of_districts * 4、マップには少なくともノードがあります。
  4. 各政党のスコアは、政党が過半数を占める地区の数です
  5. 地区の0sと1sの数が同じ場合、どちらの当事者もその恩恵を受けません
  6. 通常の不正行為のルール
  7. これはなので、バイト単位の最短コードが優先されます。

テストケース

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     

もちろん、あなたのプログラムはのために働く必要があります任意の有効なテストケースだけでなく、これらのもの。


@Arnauld、はい、それらは例示にすぎません。実際の出力は、アルファベットの文字を含む最初のテストケースのようになります。これを反映するようにタグを変更しました。
ダニエル

最初のテストケースの単純なパーティションは、このようなものになります。あれは正しいですか?
アーナルド

@Arnauld、はい、それは有効です。
ダニエル

3番目の例では、1地区の高さの水平列に分割すると、1が3対1で勝ちます。
マイケルドーガン

3
これは、ニンテンドーハンドヘルドのDMGからDSまでの文字ベースのグラフィックスに対して行わなければならなかったことの多くを思い出させます。グラフィックをカットするための特定の形状が与えられ、使用する形状の数を最小限に抑える必要がありました。使用できるのはハードウェアで定義された数のスプライト(形状)だけでした。それは簡単な問題ではありませんでした。
マイケルドーガン

回答:


6

R938 896 858 952バイト

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

オンラインでお試しください!

大規模な> 900 > 800解決バイト(ハズレ!)> 900。コードは次のように機能します。Nを選挙区の数、Mを1が過半数にしたい地区の最小数とします。

最初に、コードはN個の地区を異なるグループにランダムに割り当てます。次に、それらをランダムに展開します。つまり、ランダムに選択したグループに地区を追加し、そのグループに既に属している地区の隣に地区を確保します。拡張プロセスでは、地区グループがまだ完全な過半数でない場合、過半数が1の地区を優先します。グループがすでに特定の1多数派である場合、0地区が優先されます。すべての地区が割り当てられるまで続きます。

1党に過半数があるグループはすべて保存され、その地区はロックされます。過半数が1のグループが少なくともM個ある場合、すべてが良好であり、結果印刷して、各グループに少なくとも4つの地区があるかどうかを確認できます。4つの地区のカットオフが満たされた場合、結果を喜んで印刷できます。そうでない場合、コードは、ロックされていない地区を使用可能なグループ、つまりN-#stored-groupsに再割り当てしようとします。

コードは数回(9回)試行します。失敗すると、すべてがリセットされ、再起動します。あきらめて「試してみました...」を印刷する前に、他の9回も同様に行います。

コードが最初に成功しない場合は、数回再試行してください。TIOで1分未満で実行できるように、繰り返し回数を調整しました。ただし、解決策がある場合、このコードは(最終的に)それを見つけることができます。アルゴリズムのランダム性の部分は、解があればそれを見つけることができるゼロ以外の確率を与えます。試行回数が限られていることが成功の唯一の制限要因です。

編集:地区グループが指定された広場の端に地区を持たない限り、地区グループを別の地区グループだけで完全に囲むことはできないというコントロールを追加しました。最初は見逃したと思います。


改行を削除できますか?
NoOneIsHere

やった。また、より長い関数名を1文字に割り当て、変数が厳密に整数で正の場合にいくつか==0を置き換えました<1
NOFP

1
ここには簡単にゴルフできるものがたくさんありますが、これは答えへの最初の良い試みですので、+ 1、そして私は電話をしていないときに数時間編集を提案します!
ジュゼッペ

1
858バイト -「通常の」ゴルフ、if...else文でのブレースの使用のクリーンアップ、交換c、文字列の改行でのas.vector変更"\n"、および>自動的に数字を文字に強制的に変換してコードポイントを比較するという事実の使用。おそらく覚えていない他のゴルフもいくつかありますが、これはスタートです。...確か私は、コードを理解し、私たちはダウン微調整することができ、いくつかのより多くの事があると思いますが、私は100%ではないよ
ジュゼッペ・

良いですね!インスピレーションを受けました。あなたのコードと比較することで、非常に小さな地区グループ(4地区未満)につながるバグを発見しました。現在は修正されています。
NofP
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.