マジックボックスの問題


15

サイズがm * nの入力配列があります。配列内の各セルには、PまたはTが入力されます。配列に対して実行できる操作は、列の反転のみです。列を反転すると、その列のすべてのセルの文字が切り替わります(PはTになり、逆も同様です)。同じ文字で「x」個の行がある場合(PPPPなど)、ポイントを取得します。結果の配列が可能な最大数のポイントを持つように、配列を取り込んでソリューション(どの列を反転するか)を返すアルゴリズムを設計します。

注:最高のスコアをもたらす複数のソリューションがある場合、フリップの数が最も少ないものを選択してください。例:

入力配列:

PPTPP
PPTPP
PPTTP
PPPTT
PPPTT

出力:

3

説明:
最高点をもたらす解決策:列番号を反転します。3
次に、元の配列は次のようになります。

PPPPP // 1 point
PPPPP // 1 point
PPPTP
PPTTT
PPTTT

//Total: 2 points

列4と5を反転してスコア2を取得することもできますが、追加の反転が必要なことに注意してください。

任意の便利な入力形式を使用して2次元配列を表すことができます。また、2つの異なる(ただし固定された)値を表しP、およびを表すこともできますT

これはコードゴルフなので、最短の回答(バイト単位)が勝ちです。


6
PPCGへようこそ。これは大きな挑戦ですが、話題になるには勝利の基準が必要です。
Ypnypn 14

入力形式を制御できますか?PはFalse、TはTrueと言えますか?そうでない場合、入力形式は何ですか?
誇りに思ってhaskeller 14

確かに、入力形式は重要ではありません。chars、ints、boolean、または任意のタイプの2方向配列があるとします。
bruhhhhh

3
有効な回答のどれが最良であるかを決定するための勝利基準が必要です。有効な回答が入力グリッドの最大ポイントを提供する必要があると仮定すると(これを述べる必要があります)、妥当な時間で32列のグリッドをブルートフォースできるようになるはずです。したがって、ia codegolf(最短のコード勝利)
Level River St 14

1
私はピーターの最初の提案で働きました。気に入らない場合は、自由に言い回しを変更してください。
マーティンエンダー14

回答:



1

ピス、28

f@eo+/QN/Qm!dN_osZ^U2lhQTUhQ

ネストされたリストの形式で入力を受け取ります。例えば

[[0,0,1,0,0],[0,0,1,0,0],[0,0,1,1,0],[0,0,0,1,1],[0,0,0,1,1]]

出力に0のインデックスを付けます。例えば

[2]

^U2lhQ:正しい長さの0と1の可能なリストをすべて生成します。

_osZ:これらのリストを最大1から最小に並べます。

+/QN/Qm!dN:各リスト(N)とその逆、0と1が入れ替わった(m!dN)が入力で発生した回数をカウントします。前者はすべてゼロを残す一連のフリップに対応し、後者はすべて1を残すことに対応します。

eo:上記のキーでリストを並べ替え、最後の要素を取得します。これは、最も一致する列を持つ結果となり、その中で最も列数が少ない列になります。

f@ ... TUhQ:1と0のこのリストを、反転するインデックスのリストに変換します。

1インデックスの場合、dをa に変更し、先頭にk置きmhdます。


0

CJam、53 51バイト

l~z:X,,La\{1$f++}/{,}${X\{_X=:!t}/z{_&,(},,}$0=:)S*

これは、STDINから0と1の2次元配列を読み取ります。たとえば、質問の例は

[[0 0 1 0 0] [0 0 1 0 0] [0 0 1 1 0] [0 0 0 1 1] [0 0 0 1 1]]

ここでテストしてください。

これはまず、列の可能なすべてのサブセットを長さの昇順で取得し、次に各サブセットのフリップを実行し、まだ0と1の両方がある行数でソートします。最後に、最初のそのようなサブセットを返します。これは、安定したソートに依存しているため、長さが増加する最初の順序でタイブレーカーが処理されます。


0

ハスケル、98

g s=snd$maximum[((sum[1|o<-s,o==r||o==map(1-)r],-sum r),[i|(i,1)<-zip[1..]r])|r<-s++map(map(1-))s]

入力形式は、intのリストのリストです。テストには文字列バージョンを使用できます。

gg = g . map (map (\c -> case c of 'T' -> 0 ; _ -> 1) ) . lines

ああ、スペースはありません!それは痛い!

これは、行を反復して、この行がポイントを獲得するように列を反転させた場合に得られるポイントの数を計算することによって機能します。

最初に気づくのは、行をすべてTrueまたはすべてに反転することですFalse切り替えることは重要ではないということです。なぜなら、グリッドは相互に正確に逆になり、まったく同じスコアになるからです。

特定の行がポイントを獲得したときにカウントを計算する方法は次のとおりです。行を再度反復し、行が同一または正確に逆のときに正確に行うという事実を使用して、各行が与えるポイントを合計します。

例えば、我々が反転している行があるならばTPPTP、我々は反復処理されている現在の行があるPTTPTか、TPPTPその行の利益は、私たちのポイントが、それは、他の行のとき、それは私たちにどのポイントを得ることはありません。


@MartinBüttnerはい、すぐに(願わくば)それを修正します
誇りに思ってhaskeller 14

0

CJam、37

q~_{:!}%+:T{T1$a-,\0-+}$0={U):U*}%0-`

入力形式:

[[0 0 1 0 0] [0 0 1 0 0] [0 0 1 1 0] [0 0 0 1 1] [0 0 0 1 1]]


0

Python 2、234

from itertools import *
A=input()
n=len(A[0])
R=range(n)
S=(0,)
for p in[q for i in R[:-1] for q in combinations(R,i)]:
    s=[sum([(l[q]+(q in p))%2 for q in R])for l in A]
    m=s.count(n)+s.count(0)
    if m>S[0]:S=(m,p)
print S[1]

入力はリストのリストです:

[[0,0,1,0,0],[0,0,1,0,0],[0,0,1,1,0],[0,0,0,1,1],[0,0,0,1,1]]

出力は、0からのPythonインデックスを使用したフリップのタプルです。

(2,)

出力のインデックスを1から作成する必要がある場合、コードは272文字であり、0はフリップなしを示します。

print 0 if len(S[1])==0 else [p+1 for p in S[1]]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.