Masalah kotak ajaib

15

Anda memiliki larik input dengan ukuran m * n. Setiap sel dalam array diisi dengan P atau T. Satu-satunya operasi yang dapat Anda lakukan pada array adalah kolom flip. Ketika Anda membalik kolom, huruf-huruf di semua sel dari kolom itu berganti (P ​​menjadi T dan sebaliknya). Jika Anda memiliki jumlah baris 'x' dengan huruf yang sama (mis. PPPP) maka Anda mendapat poin. Desain algoritma yang mengambil dalam array dan mengembalikan solusi (kolom mana yang flip) sehingga array yang dihasilkan memiliki jumlah poin maksimum yang mungkin.

Catatan: Jika ada beberapa solusi yang menghasilkan skor tertinggi, pilih satu dengan jumlah flips terendah. Contoh:

Input Array:

PPTPP
PPTPP
PPTTP
PPPTT
PPPTT

Keluaran:

3

Penjelasan:
Solusi yang menghasilkan poin tertinggi: Flip kolom no. 3
Maka array aslinya adalah:

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

//Total: 2 points

Perhatikan bahwa seseorang juga dapat membalik kolom 4 dan 5 untuk mendapatkan skor dua, tetapi itu membutuhkan flip tambahan.

Anda dapat menggunakan format input yang mudah untuk mewakili array dua dimensi, dan Anda juga dapat dua nilai yang berbeda, tetapi tetap, untuk mewakili PdanT .

Ini kode golf, jadi jawaban tersingkat (dalam byte) menang.

bruhhhhh
sumber
6
Selamat datang di PPCG. Ini adalah tantangan besar, tetapi perlu kriteria kemenangan untuk menjadi topik.
Ypnypn
Bisakah saya mengontrol format input? Dapatkah saya mengatakan P salah dan T benar? Jika tidak, apa format inputnya?
haskeller bangga
Tentu, format input tidak masalah. Katakanlah Anda memiliki dua array arahan arah atau int atau boolean atau jenis apa pun yang Anda pilih.
bruhhhhh
3
Anda memerlukan kriteria kemenangan untuk memutuskan mana jawaban yang valid adalah yang terbaik. Dengan asumsi jawaban yang valid harus memberikan poin maksimum untuk kisi input (Anda harus menyatakan ini), harus dimungkinkan untuk memaksa 32 kisi kolom dalam waktu yang wajar. Karena itu saya sarankan Anda membuat ia codegolf (menang kode terpendek)
Level River St
1
Saya telah bekerja dalam saran pertama Peter. Jangan ragu untuk mengubah kata-kata jika Anda tidak menyukainya.
Martin Ender

Jawaban:

3

APL, 37

{x/1+⍳⍴x←y[↑⍋(+/∘.≠⍨2⊥⍉y),¨+/y←⍵⍪~⍵]}

Contoh:

{x/1+⍳⍴x←y[↑⍋(+/∘.≠⍨2⊥⍉y),¨+/y←⍵⍪~⍵]} 5 5⍴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

Diuji di sini.

jimmy23013
sumber
1

Pyth , 28

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

Mengambil input dalam bentuk daftar bersarang, mis

[[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]]

Memberikan output 0-diindeks, misalnya

[2]

^U2lhQ: Menghasilkan semua daftar kemungkinan 0s dan 1s dengan panjang yang tepat.

_osZ: Pesan daftar ini dari paling 1 hingga paling sedikit.

+/QN/Qm!dN: Menghitung berapa kali setiap daftar ( N) dan kebalikannya, 0s dan 1s bertukar ( m!dN) terjadi pada input. Yang pertama sesuai dengan serangkaian flips meninggalkan semua nol, yang kedua meninggalkan semua.

eo: Memerintahkan daftar dengan tombol di atas, dan mengambil elemen terakhirnya, yang akan menjadi hasil dengan kolom paling cocok, dan di antara mereka yang paling sedikit.

f@ ... TUhQ: Mengonversi daftar 1 dan 0 ini ke daftar indeks yang akan dibalik.

Untuk pengindeksan 1, ubah dmenjadi k, lalu masukkan mhddi awal.

isaacg
sumber
0

CJam, 53 51 byte

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

Ini membaca array dua dimensi 0s dan 1s dari STDIN. Misalnya contoh dalam pertanyaannya adalah

[[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]]

Uji di sini.

Ini pertama-tama mendapatkan semua himpunan bagian kolom yang mungkin, dalam urutan bertambah panjang, kemudian melakukan membalik untuk masing-masing himpunan bagian dan mengurutkannya dengan berapa banyak baris yang masih memiliki 0s dan 1s di dalamnya. Akhirnya, kami hanya mengembalikan subset pertama tersebut. Ini bergantung pada penyortiran yang stabil, sehingga urutan awal penambahan panjang menangani tie-breaker.

Martin Ender
sumber
0

Haskell, 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]

format input adalah daftar daftar int. Anda dapat menggunakan versi string untuk pengujian:

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

oh tidak, spasi! itu menyakitkan!

ini bekerja dengan mengulangi baris dan menghitung jumlah poin yang akan kita dapatkan jika kita membalik kolom sedemikian rupa sehingga baris ini memberi kita poin.

Hal pertama yang perlu diperhatikan adalah bahwa membalik baris ke semua Trueatau semua Falsetidak masalah, karena kisi-kisi akan menjadi kebalikan satu sama lain dan dengan demikian akan memiliki skor yang sama persis.

cara kita menghitung penghitungan ketika suatu baris tertentu memperoleh satu poin adalah begitu: kita mengulangi lagi baris, dan menjumlahkan poin yang diberikan setiap baris kepada kita, menggunakan fakta bahwa mereka melakukan tepat ketika baris-baris itu identik atau sama persis terbalik.

misalnya, jika baris yang kita membalik adalah TPPTPdan baris saat ini yang kita iterasi adalah PTTPTatau TPPTPkemudian baris mendapatkan kita satu poin, tetapi ketika itu baris lain, itu tidak memberi kita poin.

haskeller bangga
sumber
@ MartinBüttner Ya, saya akan segera memperbaikinya (semoga)
bangga haskeller
0

CJam, 37

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

Masukkan format:

[[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]]
jimmy23013
sumber
0

Mathematica - 76

{
{P, P, T, P, P},
{P, P, T, P, P},
{P, P, T, T, P},
{P, P, P, T, T},
{P, P, P, T, T}
}/.{P -> 1, T -> 0};
First@MaximalBy[
  Subsets@Range@Length[%],
  MapAt[1-#&,%,{All,#}]~Count~{1..}&
]
desir
sumber
Kecuali ditentukan selain potongan tidak kiriman yang valid. Anda harus menulis suatu fungsi atau program penuh yang mengambil input.
Martin Ender
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]

Input adalah daftar daftar:

[[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]]

Output adalah tuple of flips menggunakan pengindeksan python dari 0:

(2,)

Jika output harus diindeks dari 1, maka kodenya adalah 272 karakter dengan 0 menunjukkan no flips:

print 0 if len(S[1])==0 else [p+1 for p in S[1]]
pengguna2487951
sumber