魔术盒问题


15

您有一个大小为m * n的输入数组。数组中的每个单元格都用P或T填充。对数组唯一可以执行的操作是翻转列。翻转列时,该列的所有单元格中的字母都会切换(P变为T,反之亦然)。如果具有相同字母(例如PPPP)的行数为“ x”,那么您将得到一个分数。设计一种算法,该算法接受数组并返回解决方案(要翻转的列),以使生成的数组具有最大数量的点。

注意:如果有多个解决方案的得分最高,请选择翻转次数最少的解决方案。例:

输入数组:

PPTPP
PPTPP
PPTTP
PPPTT
PPPTT

输出:

3

说明:
一种产生最高点的解决方案:翻转列号。3
则原始数组为:

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

//Total: 2 points

请注意,也可以翻转第4列和第5列以获得2分,但这需要额外的翻转。

您可以使用任何方便的输入格式来表示二维数组,也可以使用任何两个不同但固定的值来表示PT

这是代码高尔夫球,因此最短的答案(以字节为单位)获胜。


6
欢迎来到PPCG。这是一个巨大的挑战,但要成为话题,就需要一个成功的标准。
Ypnypn 2014年

我可以控制输入格式吗?我可以说P是False,T是True吗?如果没有,输入格式是什么?
自豪的haskeller 2014年

当然,输入格式没有关系。假设您有一个chars或int或booleans或任何选择的类型的双向数组。
bruhhhhh 2014年

3
您需要一个获胜标准来决定哪个有效答案是最好的。假设有效答案必须给出输入网格的最大点(顺便说一句,您应该指出),应该有可能在合理的时间内暴力破解32列网格。因此,我建议您使ia codegolf(最短的代码获胜者)
Level River St

1
我已经完成了彼得的第一个建议。如果您不喜欢,可以随时更改措辞。
Martin Ender 2014年

Answers:


3

APL,37

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

例:

{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

在这里测试。


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索引,请将更改dk,然后放在mhd开头。


0

CJam,53 51字节

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

这将从STDIN读取一个0和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和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]

输入格式是整数列表。您可以使用字符串版本进行测试:

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

哦,没有空格!这很痛!

通过对行进行迭代并计算如果我们以使该行获得一个点的方式翻转列,我们将获得的点数可以起作用。

首先要注意的是,将行翻转到全部True或全部False都没有关系,因为网格将彼此完全相反,因此得分完全相同。

当给定的行获得一个点时,我们计算计数的方式是这样的:我们再次遍历这些行,并求和每行给我们的点,这是因为它们在行相同或完全相反时会精确地进行计算。

例如,如果我们要翻转的行是TPPTP并且正在迭代的当前行是PTTPTTPPTP那么该行会为我们获得一个点,但是当它是任何其他行时,它不会获得任何点。


@MartinBüttner是的,我会尽快修复(希望如此)
自豪的haskeller 2014年

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]]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.