Überprüfen Sie, ob eine Zeichenfolge eine Mischung aus Zwillingen ist

10

Erläuterung

Zwei Zeichenfolgen können gemischt werden, indem ihre Buchstaben zu einer neuen Zeichenfolge durchsetzt werden, ähnlich wie zwei Kartenstapel zu einem einzigen Stapel gemischt werden können.

Zum Beispiel können die Saiten HELLOund WORLDgemischt werden, um zu bilden HWEOLRLLOD, oder HEWORLLLDOoder vielleicht einfach HELLOWORLD.

Es ist kein Shuffle, wenn die ursprüngliche Reihenfolge der Buchstaben nicht beibehalten wird. Zum Beispiel kann das DIn WORLDniemals vor dem RNach dem Mischen erscheinen. Dies bedeutet, dass es sich EHLLOWRDLObeispielsweise nicht um ein Mischen von HELLOund handelt WORLD, obwohl es alle Originalbuchstaben enthält.

Eine Saite ist eine Mischung aus Zwillingen, wenn sie durch Mischen zweier identischer Saiten gebildet werden kann. Zum Beispiel ABACBDECDEist ein Mischen von Zwillingen, weil es durch Mischen ABCDEund gebildet werden kann ABCDE. DBEACBCADEist kein Mischen von Zwillingen, da es nicht durch Mischen von zwei identischen Saiten gebildet werden kann.

Programmdetails

Geben Sie bei einer Eingabezeichenfolge eine Ausgabe aus, 0wenn es sich nicht um eine Mischung aus Zwillingen handelt, und geben Sie eine der Zwillingszeichenfolgen aus, wenn es sich um eine Mischung aus Zwillingen handelt.

Sie können davon ausgehen, dass die Eingabezeichenfolge eine Länge zwischen vier und zwanzig Zeichen hat und vollständig aus alphabetischen Großbuchstaben besteht. Es sollte in einer angemessenen Zeitspanne von beispielsweise weniger als 10 Minuten ausgeführt werden können.

Dies ist Code Golf, also gewinnt die kürzeste Lösung.

Beispiel E / A.

> ABACBDECDE
ABCDE

> DBEACBCADE
0

> FFFFFF
FFF

> FFGGG
0

> ABBA
0

> AABB
AB

> AABAAB
AAB

Ich habe eine Beispielimplementierung (ohne Golf) .

Peter Olson
quelle
Die Beispielzeichenfolge FGG verstößt gegen die Behauptung that the input string has a length inclusively between four and twenty charactersund sagt mir nicht "Vertraue niemals Benutzereingaben!", "Vertraue niemals den Spezifikationen!"
Benutzer unbekannt
@userunknown Das ist so peinlich! Ich habe es bearbeitet FFGGG, um es konsistent zu machen.
Peter Olson
1
Kann jemand aus Neugier eine Lösung mit subexponentieller Worst-Case-Zeitkomplexität finden oder beweisen, dass es keine gibt?
Ilmari Karonen

Antworten:

4

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

Ungolfed:

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

Erläuterung:

Der größte Teil der Arbeit wird in der partitionsFunktion erledigt . Es funktioniert , indem rekursiv alle Partitionen erzeugen , (a, b)des Schwanzes der Liste, und dann mit der Liste Monade das anfängliche Element vorangestellt wird xzu jedem von ihnen und alle , die Ergebnisse zu sammeln.

findMatchFiltert diese Liste so, dass nur Partitionen übrig bleiben, bei denen die Teilsequenzen gleich sind. Es gibt dann die erste Teilsequenz in der ersten Partition zurück. Wenn keine mehr vorhanden ist, ist die Liste leer, sodass die "0"am Ende angehängte Liste stattdessen zurückgegeben wird.

main Liest einfach die Eingabe, führt sie durch diese beiden Funktionen und druckt sie aus.

Hammar
quelle
Geben Sie für diejenigen von uns, die Haskell nicht lesen können, eine Erklärung?
Mr.Wizard
1
@ Mr.Wizard: Siehe Bearbeiten.
Hammar
Ich glaube, ich habe mir etwas ziemlich Ähnliches ausgedacht, wenn auch nicht so kurz, aber ich habe eine dumme Art hineingeworfen, die es zu einem völligen Misserfolg gemacht hat. Stört es Sie, wenn ich diesen Algorithmus in Mathematica implementiere?
Mr.Wizard
4

R, 113 Zeichen

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 (und stattdessen eine Funktion, die den String übernimmt):

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

Die Lösung basiert auf der combnFunktion, die alle Kombinationen von Indizes als Spalten in einer Matrix generiert. applyWendet dann eine Funktion auf jede Spalte (Dimension 2) in der Matrix an und gibt einen Vektor aus Zeichenfolgen oder Nullen zurück. maxFinden Sie dann die größte Zeichenfolge (die 0 übertrumpft).

Ein cooles Merkmal in R ist die Fähigkeit, eine Teilmenge eines Vektors bei einem gegebenen Vektor von Indizes auszuwählen und dann das Komplement dieser Teilmenge durch Negieren der Indizes auszuwählen :x[i] == x[-i]

Tommy
quelle
Einige inkrementelle Verbesserungen und reduzierte Zeichenanzahl.
Tommy
3

Mathematica, 87

Dies basiert direkt auf Hammars Post, ist aber hoffentlich deutlich genug, um eine Veröffentlichung zu verdienen.

<<Combinatorica`

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

Prüfung:

f /@ {"ABACBDECDE", "DBEACBCADE", "FFFFFF", "FGG", "ABBA", "AABB", "AABAAB"}
{"ABCDE", 0, "FFF", 0, 0, "AB", "AAB"}
Mr.Wizard
quelle
1

D.

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));}

Verwenden der ersten rekursiven Tiefensuche

Ich kann es mit einer int i = min(a.length,b.length);if(a[0..i]!=b[0..i])return "0";Schutzklausel schneller machen

Ratschenfreak
quelle
Auf IDEONE konnte ich nicht versuchen, das Programm zu starten void main(){writeln(c("ABCADABCAD"));}- nur eine andere Version von D, meine Schuld, etwas anderes? Was ist mit "ABCABCA"?
Benutzer unbekannt
Sie müssen std.stdio importieren. für den IO
Ratschenfreak
1

Ruby, 89 Zeichen

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

Dieser Code implementiert einen einfachen rekursiven Suchalgorithmus. Die Eingabe muss auf STDIN erfolgen.

Howard
quelle
1

Perl, 68 Zeichen

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

Die Eingabezeichenfolge wird als in der $_Variablen angenommen, die Ausgabe ist der Wert des Ausdrucks. Nachgestellte Zeilenumbrüche in der Eingabe werden ignoriert. Sie können dies über die Befehlszeile wie folgt ausführen:

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

Dieser Code verwendet die Regexp-Engine von Perl (und insbesondere die Ausführungsfunktion für eingebetteten Code ), um das Backtracking durchzuführen . Grundsätzlich wird die Eingabezeichenfolge mit dem regulären Ausdruck abgeglichen ^((.+))+$, wobei die ungeraden und geraden Submatches in $xund verfolgt $,werden und die Übereinstimmung am Ende abgelehnt wird , wenn die beiden nicht gleich sind.

Ilmari Karonen
quelle
Hat dies das richtige Ergebnis für AABAAB?
Peter Olson
Ja tut es. (Tatsächlich AABAABist dies ein einfacher Fall für diese Lösung, da die äußere Gruppe nur zweimal übereinstimmen muss. Ich habe viel länger AABB
gebraucht
1

Python, 168 Zeichen

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())
Steven Rumbalski
quelle