줄이 쌍둥이 셔플인지 확인


10

설명

두 개의 줄을 섞어서 새 줄을 만들면 두 줄을 섞을 수 있습니다. 마치 두 장의 카드 더미를 섞어서 하나의 말뚝을 만들 수 있습니다.

예를 들어 문자열 HELLOWORLD섞어서 HWEOLRLLOD, 또는 HEWORLLLDO, 또는 간단히HELLOWORLD 있습니다.

그것은이다 없는 글자의 원래 순서가 유지되지 않으면 셔플. 예를 들어, 뒤를 뒤섞기 전에 Din WORLD을 표시 할 수 없습니다 R. 이 수단 EHLLOWRDLO, 예를 들어,의 셔플 아니다, HELLO그리고 WORLD그것은 모두 원래의 문자를 포함하더라도.

스트링은 두 개의 동일한 스트링을 섞어서 형성 될 수 있다면 쌍둥이셔플입니다 . 예를 들어, ABACBDECDE쌍둥이 셔플은 셔플 링 ABCDE및을 사용 하여 형성 할 수 있기 때문 ABCDE입니다. DBEACBCADE두 개의 동일한 줄을 섞어서 형성 할 수 없기 때문에 쌍둥이의 셔플은 아닙니다.

프로그램 세부 사항

입력 문자열이 주어지면 0쌍둥이 셔플이 아닌 경우 출력 하고 쌍둥이 셔플 인 경우 쌍둥이 문자열 중 하나를 출력합니다.

입력 문자열의 길이는 4 자에서 20 자 사이이며 전체적으로 대문자 알파벳 문자로 구성되어 있다고 가정 할 수 있습니다. 합리적인 시간 (예 : 10 분 미만)으로 실행할 수 있어야합니다.

이것은 코드 골프이므로 가장 짧은 솔루션이 승리합니다.

예제 I / O

> ABACBDECDE
ABCDE

> DBEACBCADE
0

> FFFFFF
FFF

> FFGGG
0

> ABBA
0

> AABB
AB

> AABAAB
AAB

골퍼가 아닌 구현 예제 가 있습니다 .


문자열 FGG 예제가 어설 션을 위반 that the input string has a length inclusively between four and twenty characters하고 "사용자 입력을 절대 신뢰하지 마십시오!", "사양을 신뢰하지 마십시오!"
사용자가 알 수 없음

@userunknown 너무 당황 스럽습니다! FFGGG일관성을 유지하기 위해 편집했습니다 .
피터 올슨

1
호기심만으로도 누구나 기하 급수적으로 최악의 시간 복잡성을 가진 솔루션을 만들 수 있습니까, 아니면 아무것도 없다는 것을 증명할 수 있습니까?
Ilmari Karonen

답변:


4

하스켈, 114

main=getLine>>=putStrLn.f.p;f x=head$[a|(a,b)<-x,a==b]++["0"]
p[]=[([],[])];p(x:y)=do(a,b)<-p y;[(x:a,b),(a,x:b)]

언 골프 드 :

main :: IO ()
main = getLine >>= putStrLn . findMatch . partitions

-- | Find the first partition where the two subsequences are
-- equal. If none are, return "0".
findMatch :: [(String, String)] -> String
findMatch ps = head $ [a | (a,b) <- ps, a == b] ++ ["0"]

-- | Return all possible partitions of the input into two
-- subsequences. Preserves the order of each subsequence.
--
-- Example:
-- partitions "AB" == [("AB",""),("B","A"),("A","B"),("","AB")]
partitions :: [a] -> [([a], [a])]
partitions []     = [([], [])]
partitions (x:xs) = do (a, b) <- partitions xs
                       [(x:a, b), (a, x:b)]

설명:

대부분의 작업은 partitions기능 에서 수행됩니다 . (a, b)목록 꼬리의 모든 파티션 을 재귀 적으로 생성 한 다음 목록 모나드 를 사용 하여 초기 요소 x를 각 요소 앞에 추가하고 모든 결과를 수집합니다.

findMatch하위 시퀀스가 ​​동일한 파티션 만 남아 있도록이 목록을 필터링하여 작동합니다. 그런 다음 첫 번째 파티션의 첫 번째 하위 시퀀스를 반환합니다. 남아 있지 않으면 목록이 비어 있으므로 "0"끝에 추가 된 것이 대신 반환됩니다.

main 입력을 읽고이 두 기능을 통해 공급 한 다음 인쇄합니다.


하스켈을 읽을 수없는 사람들을 위해 설명해 주시겠습니까?
Mr.Wizard

1
@ 미스터 마법사 : 편집을 참조하십시오.
hammar

나는 짧지는 않지만 상당히 비슷한 것을 생각해 냈지만 어리석은 종류로 던져서 완전히 실패했습니다. Mathematica에서이 알고리즘을 구현해도 될까요?
Mr.Wizard

4

R, 113 자

l=length(x<-charToRaw(scan(,'')));max(apply(combn(l,l/2),2,function(i)if(all(x[i]==x[-i]))rawToChar(x[i])else 0))

ungolfed (대신 문자열을받는 함수) :

untwin <- function(x) {
  x <- charToRaw(x)
  indMtx <- combn(length(x),length(x)/2)
  res <- apply(indMtx, 2, function(i) {
    if (all(x[i]==x[-i]))
      rawToChar(x[i])
    else
      0
  })
  max(res)
}

untwin("ABACBDECDE") # "ABCDE"
untwin("DBEACBCADE") # 0

이 솔루션은 combn모든 인덱스 조합을 행렬의 열로 생성 하는 함수 에 의존합니다 . apply그런 다음 2행렬의 각 열 (dimension )에 함수를 적용하고 문자열 또는 0으로 구성된 벡터를 반환합니다. max그런 다음 가장 큰 문자열을 찾으십시오 (0보다 큼).

R의 멋진 기능은 인덱스 벡터로 주어진 벡터의 서브 세트를 선택한 다음 인덱스를 무시하여 해당 서브 세트 의 보수 를 선택하는 기능 입니다.x[i] == x[-i]


점진적으로 개선하고 문자 수를 줄였습니다.
Tommy

3

매스 매 티카, 87

이것은 hammar의 게시물을 직접 기반으로하지만 게시를할만한 가치가 있기를 바랍니다.

<<Combinatorica`

f=Catch[Cases[Characters@#~KSetPartitions~2,{x_,x_}:>Throw[""<>x]];0]&

테스트:

f /@ {"ABACBDECDE", "DBEACBCADE", "FFFFFF", "FGG", "ABBA", "AABB", "AABAAB"}
{ "ABCDE", 0, "FFF", 0, 0, "AB", "AAB"}

1

string c(string in,string a=[],string b=[]){
    if(in.length==0)return a==b?a;"0";
    auto r=c(in[1..$],a~in[0],b);
    return r=="0"?c(in[1..$],a,b~in[0]):r;
}
void main(){writeln(c(readline));}

깊이 우선 재귀 검색 사용

int i = min(a.length,b.length);if(a[0..i]!=b[0..i])return "0";가드 절로 더 빨리 만들 수 있습니다


IDEONE에서 void main(){writeln(c("ABCADABCAD"));}다른 버전의 D, 내 잘못 등으로 프로그램을 시작하지 못했습니다 . "ABCABCA"는 무엇입니까?
사용자가 알 수 없음

std.stdio를 가져와야합니다. IO를 위해
래칫 괴물

1

루비, 89 자

s=->a,x,y{a=="\n"?x==y ?x:?0:[s[b=a[1..-1],x+c=a[0],y],s[b,x,y+c]].max}
$><<s[gets,'','']

이 코드는 일반 재귀 검색 알고리즘을 구현합니다. 입력은 STDIN에 제공되어야합니다.


1

펄, 68 자

/^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0

입력 문자열이 $_변수 에 있다고 가정 하면 출력은 표현식의 값입니다. 입력의 후행 줄 바꿈은 무시됩니다. 다음과 같이 명령 행에서이를 실행할 수 있습니다.

perl -lne 'print /^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0'

이 코드는 Perl의 정규식 엔진 (특히 포함 된 코드 실행 기능)을 사용하여 역 추적을 수행합니다. 기본적으로, 정규 표현식에 대해 입력 된 문자열과 일치 ^((.+))+$에 홀수 및 짝수 submatches의 트랙을 유지 $x하고 $,, 상기 두 개의 동일하지 않은 경우, 마지막에 일치 거부.


이것에 대한 올바른 결과가 AABAAB있습니까?
피터 올슨

그렇습니다. (실제로 AABAAB외부 그룹이 두 번만 일치하면되기 때문에이 솔루션의 경우는 쉬운 경우입니다. AABB올바르게 처리하는 데 훨씬 오래 걸렸습니다 .)
Ilmari Karonen

1

파이썬, 168 자

def f(s):
 c=s[0]
 d=i=r=0
 if s==c+c:r=c
 while i+1 and i<=len(s)/2 and not r:
  if i:d=f(s[1:i]+s[i+1:])
  if d:r=c+d
  i=s.find(c,i+1)
 return r
print f(raw_input())
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.