마법 상자 문제


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 점을 얻을 수도 있지만 추가적인 뒤집기가 필요합니다.

편리한 입력 형식을 사용하여 2 차원 배열을 나타낼 수도 있고, 두 개의 고유하지만 고정 된 값을 나타내 P거나 를 나타낼 수도 T있습니다.

이것은 코드 골프이므로 가장 짧은 대답 (바이트)이 이깁니다.


6
PPCG에 오신 것을 환영합니다. 이것은 큰 도전이지만, 주제에 관한 성공적인 기준이 필요합니다.
Ypnypn December

입력 형식을 제어 할 수 있습니까? P가 False이고 T가 True라고 말할 수 있습니까? 그렇지 않은 경우 입력 형식은 무엇입니까?
자부심을 가지고 Haskeller

물론, 입력 형식은 중요하지 않습니다. 문자, 정수 또는 부울 또는 원하는 유형의 두 방향 배열이 있다고 가정하십시오.
bruhhhhh

3
어떤 정답이 가장 적합한 지 결정하려면이기는 기준이 필요합니다. 유효한 답변이 입력 그리드에 대한 최대 점수를 제공해야한다고 가정하면 (BTW에 명시해야 함) 합리적인 시간에 32 열 그리드를 무차별화할 수 있어야합니다. 따라서 나는 당신이 아이오와 codegolf (짧은 코드 승)를 만들 제안
레벨 강 세인트

1
나는 베드로의 첫 제안에서 일했다. 마음에 들지 않으면 언제든지 문구를 변경하십시오.
Martin Ender

답변:


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. 전자는 모든 0을 남기는 일련의 플립에 해당하고 후자는 모든 0을 남기는 것에 해당합니다.

eo: 위의 키로 목록을 정렬하고 마지막 요소를 가져옵니다. 가장 일치하는 열이 있고 그중 가장 적은 열이있는 결과가됩니다.

f@ ... TUhQ:이 1과 0의 목록을 뒤집을 인덱스 목록으로 변환합니다.

1 인덱스를 들어, 변경 dA와를 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]

입력 형식은 정수 목록입니다. 테스트를 위해 문자열 버전을 사용할 수 있습니다.

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

오 공간이 없어! 아파요!

이것은 행을 반복 하고이 행이 우리에게 포인트를 얻는 방식으로 열을 뒤집 으면 얻을 수있는 포인트 수를 계산하여 작동합니다.

가장 먼저 주목해야 할 것은 그리드가 서로 정확히 역수이므로 정확하게 같은 점수를 가지기 때문에 행을 모두 True또는 모두 로 뒤집는 False것은 중요하지 않습니다.

주어진 행이 점을 얻을 때 카운트를 계산하는 방식은 다음과 같습니다. 우리는 행을 다시 반복하고 행이 동일하거나 정확한 역일 때 정확하게 행한다는 사실을 사용하여 각 행이 우리에게주는 점을 합합니다.

예를 들어, 뒤집고있는 행 TPPTP이 반복되는 현재 행 PTTPT이거나 그렇지 TPPTP않으면 행이 우리에게 포인트를 얻지 만 다른 행일 때는 어떤 포인트도 얻지 못합니다.


@ MartinBüttner 예, 곧 수정하겠습니다.
자랑 haskeller

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

파이썬 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에서 파이썬 인덱싱을 사용하는 플립의 튜플입니다.

(2,)

출력을 1에서 색인화해야하는 경우 코드는 뒤집기가 없음을 나타내는 272 자입니다.

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.