2009-04-22 11 views
0

Ich möchte ein Skript schreiben, das ein Argument, die wie folgt aussehen könnte:Wie kann ich eine Zeichenfolge analysieren, die Platzhalter und Zeichenklassen in Ruby enthält?

abc(ag)de* 

a, b, c sind wörtliche Zeichen.

(ag) bedeutet "ein 'a' oder ein 'g'".

* bedeutet einen Buchstaben oder eine Zahl.

Ich möchte das Skript ein Array aller möglichen Zeichenfolgen erstellen, die die Eingabe darstellen könnte. (Der Zweck ist, zu überprüfen, ob sie verfügbare Domain-Namen sind.)

Die Eingabe könnte auch etwas wie abc(ag)de(mnlop) sein, wo es mehr als eine Zeichenklasse gibt.

Scheint, wie die erste Aufgabe es in ein Array oder Arrays aufgeteilt ist, so ist das erste Beispiel wäre ...

[ 
    ['a'], 
    ['b'], 
    ['c'], 
    ['a', 'g'], 
    ['d'], 
    ['e'], 
    [ 
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 
    # etc... 
    ] 
] 

Dies ist, wo ich stecken. Ich weiß nicht, wie ich es in Stücke aufteilen soll.

Irgendwelche Vorschläge, wie man es angehen kann?

+0

Im Titel fehlt zwischen "a" und "that" ein Wort. Ich bin nicht sicher, was das richtige Wort wäre ("String"?), Also sollten Sie das beheben;) – OregonGhost

+0

Sie können die C# -Antwort finden, die ich unter http://stackoverflow.com/questions/710670/c-permutation veröffentlicht habe -von-einem-Array-of-arraylists/710716 # 710716 hilfreich. In Ihrem Fall würden die Arrays diejenigen sein, die Sie bereits für Ihren ersten Sask generieren. Der grundlegende rekursive Algorithmus sollte relativ einfach in eine Lösung für Ihr Problem übersetzt werden können. Aber ich kenne Ruby nicht, also überlasse ich es dir oder jemand anderem. – Brian

Antwort

5

Hier ist eine ziemlich kompakte Lösung. Es ist in keiner Weise für die Leistung optimiert, die die Muster, die Sie z. Zu viele Wildcards sind wahrscheinlich nicht die beste Idee.

Hier ist der Code

input1 = "abc(ag)de*" 
input2 = "abc(ag)de(mnlop)" 

class Array 
    def append_suffixes!(suffixes) 
    self.replace suffixes.map { |a| self.map { |p| p + a }}.flatten 
    end 
end 

def generate_combinations(pattern) 
    combinations = [""] 
    pattern.scan(/\(([^)]+)\)|(\*)|(\w+)/) do |group,wildcard,other| 
    new_suffixes = case 
     when group : group.split('') 
     when wildcard : [*'a'..'z'] 
     when other : other 
     else raise "Unknown match!" 
    end 
    combinations.append_suffixes! new_suffixes 
    end 
    combinations 
end 

p generate_combinations(input1) 
p generate_combinations(input2) 
p generate_combinations("**").size 

Der Ausgang vom Laufen Sie den Code oben ist (leicht bearbeitet):

["abcadea", "abcgdea", "abcadeb", "abcgdeb", "abcadec", 
"abcgdec", "abcaded", "abcgded", "abcadee", "abcgdee", 
"abcadef", "abcgdef", "abcadeg", "abcgdeg", "abcadeh", 
"abcgdeh", "abcadei", "abcgdei", "abcadej", "abcgdej", 
"abcadek", "abcgdek", "abcadel", "abcgdel", "abcadem", 
"abcgdem", "abcaden", "abcgden", "abcadeo", "abcgdeo", 
"abcadep", "abcgdep", "abcadeq", "abcgdeq", "abcader", 
"abcgder", "abcades", "abcgdes", "abcadet", "abcgdet", 
"abcadeu", "abcgdeu", "abcadev", "abcgdev", "abcadew", 
"abcgdew", "abcadex", "abcgdex", "abcadey", "abcgdey", 
"abcadez", "abcgdez"] 

["abcadem", "abcgdem", "abcaden", "abcgden", "abcadel", 
"abcgdel", "abcadeo", "abcgdeo", "abcadep", "abcgdep"] 

676 # The number of two letter words i.e. 26*26 

Bitte sprechen Sie uns bitte, wenn Sie irgendwelche Fragen über über den Code haben.

1

Wenn dein * nur ein einzelnes Zeichen bedeutet, dann ist das zumindest lösbar. Wenn es "null oder mehr irgendeines Zeichens" bedeutet, dann fühlt es sich an, als ob dein Lösungsraum an das Unendliche grenzt, und daher wird es schwierig sein, als ein konkreter konkreter Wert zurückzukehren.

Ich denke, ich würde das annähern, indem ich die variablen Teile irgendwie aufspalte, herausfinde, wie viele Varianten jeder unterstützt, dann (konzeptionell) alle Variablen verschachtelt überstreiche und für jede Iteration des innersten eine Ausgabekette bildet Schleife.

Für das Beispiel String von "abc (ag) de *", würde dies lässt sich auf diese (Python-ish Pseudo-Code ist mein Rubin nicht zur öffentlichen Nutzung):

results = [] 
for x in "ag": 
    for y in "abcdefghijklmnopqrstuvwxyz": 
    results.append("abc%sde%s" % (x, y)) 

Die % s in der Zeichenfolge in der letzten Zeile ist ein Formatbezeichner, s bedeutet einfach "Zeichenfolge" und bewirkt, dass der entsprechende Wert aus dem Tupel rechts vom Operator% angezeigt wird, nachdem die Zeichenfolge an dieser Position interpoliert wurde.

+0

Der Stern bedeutet nur ein Zeichen. – Ethan

1

Was Sie im Wesentlichen fragen, ist eine Regexp zu nehmen und alle Zeichenfolgen zu generieren, die es entspricht.

Das war Ruby Quiz #143. Schauen Sie sich die Lösungen auf der linken Seite an.

Verwandte Themen