Regex mit eingeschränkter Verwendung bestimmter Zeichen (wie eine Scrabble-Bank von Buchstaben)

8

Ich würde gerne in der Lage sein, eine Regex zu machen, wo ich eine Art von einer Bank von Buchstaben wie [dgos] zum Beispiel identifizieren und diese in meiner Regex benutzen könnte ... aber immer wenn ein Buchstabe davon benutzt wird, dauert es weg von der Bank.

Also sagen wir, dass irgendwie für diese Bank von Buchstaben stehen kann ( dgos ). Ich könnte eine Regex so schreiben wie:

%Vor%

und es würde im Grunde übereinstimmen:
{1} = [dgos]{1}
o
{2} = [dgos]{2} minus was auch immer in der ersten verwendet wurde

Übereinstimmungen könnten good , dosg , sogd usw. enthalten und würden sods nicht einschließen (weil s zweimal verwendet werden müsste) oder sooo (weil o müsste zweimal verwendet werden.

Ich möchte auch Buchstaben identifizieren können, die mehr als einmal verwendet werden können. Ich fing an, das selbst zu schreiben, aber dann merkte ich, dass ich nicht einmal wusste, wo ich damit anfangen sollte, also habe ich auch gesucht und keinen sehr eleganten Weg gefunden, dies zu tun, oder einen Weg, dies zu tun Stark> Flexibel genug, dass die Regex mit minimaler Eingabe einfach erzeugt werden kann.

Ich habe unten eine Lösung mit einer Kombination aus Bedingungen und mehreren Regexs (Sie können Gedanken zu dieser Antwort kommentieren - vielleicht ist es die Art, wie ich es tun muss?), aber ich würde eine einzelne Regex-Lösung bevorzugen, wenn möglich ... und etwas eleganter und effizienter, wenn möglich.

Beachten Sie, dass das höhere Niveau von Eleganz und Single Regex Teil nur meine Vorlieben sind, das Wichtigste ist, dass es funktioniert und die Leistung gut genug ist.

    
smerny 22.07.2013, 15:44
quelle

5 Antworten

1

Angenommen, Sie verwenden Javascript Version 1.5+ (damit Sie Lookaheads verwenden können), hier ist meine Lösung:

%Vor%

Nachdem also jeder Buchstabe gefunden wurde, führen Sie eine negative Vorausschau durch, um sicherzustellen, dass dieser übereinstimmende Buchstabe nie wieder erscheint.

Diese Methode würde nicht funktionieren (oder zumindest viel komplizierter gemacht werden müssen), wenn Sie jedoch einige Buchstaben wiederholen lassen wollen. (Z. B. wenn Ihre Buchstaben "Beispiel" sind).

EDIT: Ich habe gerade ein wenig nachgedacht, und hier ist eine viel elegantere Lösung:

%Vor%     
Tom Lord 22.07.2013 17:01
quelle
1

Nachdem ich darüber nachgedacht habe, habe ich überlegt, dass dies möglich ist, obwohl diese Lösung ziemlich hässlich ist! Angenommen, Sie möchten die Buchstaben "Waren" (d. H. Einschließlich ZWEI "o" s) abgleichen:

%Vor%

- Also habe ich Vorwärts-Lookaheads verwendet, um zu überprüfen, ob alle diese Buchstaben irgendwo im Text stehen, und dann einfach überprüft, dass es genau 5 Buchstaben gibt.

Oder als ein anderes Beispiel, nehmen wir an, wir wollen die Buchstaben "Banane" mit einem Buchstaben "a" in Position 2 des Wortes übereinstimmen. Dann könnten Sie passen:

%Vor%     
Tom Lord 23.07.2013 08:02
quelle
1

Aufbauend auf @ TomLords Antwort, unter Berücksichtigung, dass Sie die Buchstabenbank nicht unbedingt ausschöpfen müssen, können Sie Negative Lookahead-Aussagen anstelle von positiven. Für Ihr Beispiel D<2 from bank>R<0-5 from bank> wäre diese Regex

%Vor%

Erläuterung:

%Vor%

Sie könnten auch (?!.*o.*o) anstelle von (?![^o]*o[^o]*o) schreiben, aber Letzteres ist schneller, nur schwerer zu lesen. Eine andere Möglichkeit, dies zu schreiben, ist (?!(?:[^o]*o){2}) (nützlich, wenn die Anzahl der Wiederholungen zunimmt).

Und natürlich müssen Sie die Anzahl der Buchstaben in Ihrem "festen" Teil des Strings berücksichtigen (die in diesem Fall ( d und r ) die Bank nicht stören, aber sie könnten es tun so in anderen Beispielen).

    
Tim Pietzcker 23.07.2013 13:19
quelle
0

Etwas wie das wäre ziemlich einfach zu spezifizieren, nur sehr lang

%Vor%

Sie würden grundsätzlich jede Permutation angeben. Schreiben Sie einfach einen Code, um jede Permutation zu generieren, kombinieren Sie ihn mit dem alternativen Operator und Sie sind fertig!

Obwohl ... Es könnte sich lohnen, den Entscheidungsbaum zu kodieren, der zum Erzeugen der Permutationen verwendet wurde ...

Ich schwöre, ich glaube, ich habe das schon vorher auf stackoverflow beantwortet. Lass mich zu dir zurückkommen ...

    
JayC 22.07.2013 17:15
quelle
0

Ich konnte mir keinen Weg vorstellen, dies komplett in einer Regex zu tun, aber ich konnte mir folgendes einfallen lassen: Ссылка

Da jsfiddle auf post size beschränkt ist, konnte ich dort das größere Wörterbuch nicht machen. Hier finden Sie für ein besseres Beispiel mit einem 180k Wörterbuch.

Hauptfunktion:

%Vor%

Verwendung:

%Vor%

Um das Erstellen von Szenarien zu erleichtern, habe ich auch Folgendes erstellt:

%Vor%

Dies wäre in Scrabble nützlich, also sagen wir, dass Sie in einer Position sind, wo ein Wort mit einem "D" beginnen muss, dass zwischen einem "D" und einem "R" zwei Leerzeichen stehen Sie haben OAEES für Ihre Briefbank. Im Builder konnte ich D,<2>,R,<0-3> setzen, weil es mit einem D beginnen muss, dann muss es 2 Buchstaben von der Bank haben, dann gibt es ein R, dann müsste ich bis zu 3 Buchstaben verwenden (da ich es benutze 2 zwischen D und R).

Der Ersteller würde die Buchstabenbank verwenden und D,<2>,R,<0-3> in ^(D)([OAEES]{2})(R)([OAEES]{0,5})$ umwandeln, die verwendet würde, um nach möglichen Übereinstimmungen zu filtern. Dann wird mit diesen möglichen Übereinstimmungen die Erfassungsgruppen betrachtet, die Buchstabe für Buchstabe die Buchstabenbank verwenden und Buchstaben aus dieser Regex entfernen, wenn sie gefunden werden, so dass sie nicht übereinstimmen, wenn mehr Buchstabenbankbriefe als dort verwendet werden ist in der Briefbank.

Testen Sie das obige Szenario hier .

    
smerny 22.07.2013 15:44
quelle

Tags und Links