Rekursive Akronyme

31

Zielsetzung

Aus Wikipedia :

Ein rekursives Akronym ist ein Akronym, das sich in dem Ausdruck, für den es steht, auf sich selbst bezieht.

Ihr Ziel ist es, zu überprüfen, ob eine Zeichenfolge ein rekursives Akronym ist.

  • Das Akronym ist das erste Wort
  • Bei Wörtern wird nicht zwischen Groß- und Kleinschreibung unterschieden. Sie werden durch ein einzelnes Leerzeichen getrennt.
  • Die angegebene Zeichenfolge enthält weder Interpunktion noch Apostroph.
  • Nur der erste Buchstabe jedes Wortes kann Teil des Akronyms sein.

Sie müssen auch die Funktionswörter angeben . Zur Vereinfachung kann jedes Wort als Funktionswort betrachtet werden.

Beispiel

f("RPM Package Manager")         =>     { true, [] }
f("Wine is not an emulator")     =>     { true, ["an"] }
f("GNU is not Unix")             =>     { true, ["is"] }
f("Golf is not an acronym")      =>     { false }  
f("X is a valid acronym")        =>     { true, ["is","a","valid","acronym"] }  

Sie können ein vollständiges Programm oder eine Funktion angeben.
Die Eingabezeichenfolge kann aus STDIN oder als Funktionsargument übernommen werden.
Das Ausgabeergebnis kann wahr / falsch sein, 0/1, ja / nein ...
Die Liste der Funktionswörter (jedes Format der Liste ist gültig) muss genau dann angegeben werden, wenn dies ein rekursives Akronym ist (auch wenn die Liste leer ist). . Sie müssen die Großschreibung der Funktionswörter nicht beibehalten.

Gewinnkriterien

Dies ist ein , der kürzeste Code gewinnt.

Michael M.
quelle
4
Müssen wir die Großschreibung der Funktionswörter beibehalten?
Algorithmushai
1
Ist es akzeptabel, eine Liste von Zeichenfolgen zu haben, die einen falschen Wert begleiten, oder nein?
bahnmonorail
1
Da die Wortliste selbst den Booleschen Wert durch sein Vorhandensein codiert, können wir den Booleschen weglassen?
John Dvorak
5
Hurd steht für Hird of Unix-Replacing Daemons. Hird steht für Hurd of Interfaces Representing Depth. Warum verstehen die Beispiele hier das nicht und behaupten, dass es sich nicht um rekursive Akronyme handelt?
Konrad Borowski
3
@ xfix, Wikipedia gibt an, dass dies gegenseitig rekursive Akronyme sind.
Michael M.

Antworten:

7

GolfScript, 51 50 Zeichen

{32|}%" "/(1>\{.1<2$1<={;1>}{\}if}/{]!}{]`1" "@}if

Es kann wahrscheinlich weiter Golf gespielt werden. Übernimmt die Eingabe für STDIN. Der Boolesche Wert ist 0/1.

Online testen


Erläuterung:

{32|}%      # change everything to lower-case
" "/        # splits the string by spaces
(1>         # takes the first word out and removes the first letter
\           # moves the list of remaining words in front of the acronym word
{           # for every word:
  .1<2$1<=    # compares the first letter of the word with
              # the next unmatched letter of the acronym
  {;1>}       # if they are the same, discard the word and the now-matched letter
  {\}         # otherwise store the word in the stack
  if          # NB. if all letters have been matched, the comparison comes out as false
}/
{]!}        # if there are still unmatched letters, return 0 (`!` non-empty list)
{]`1" "@}   # otherwise, return 1, and display the list of function words
if
Flüchtigkeit
quelle
22

Regex, .NET-Version, 62 Byte

(?i)(?<=^\w(?<c>\w)*)( \k<c>(?<-c>)\w+| (?<w>\w+))*$(?(c)(?!))

Sie können es hier testen . Wenn die Eingabe ein rekursives Akronym ist, ergibt dies eine Übereinstimmung, und die Erfassungsgruppe wenthält alle Funktionswörter. Wenn nicht, wird es keine Übereinstimmung geben.

Dadurch wird die Groß- und Kleinschreibung der Funktionswörter beibehalten (die Groß- und Kleinschreibung wird jedoch nicht berücksichtigt ).

Leider hat der Tester nicht den gesamten Stapel von einer benannten Erfassung Gruppe angezeigt werden , aber wenn man es überall in .NET verwendet, die wGruppe würde alle Funktionsworte enthält , um.

Hier ist ein C # -Snippet, um dies zu beweisen:

var pattern = @"(?i)(?<=^\w(?<c>\w)*)( \k<c>(?<-c>)\w+| (?<w>\w+))*$(?(c)(?!))";
var input = new string[] {
    "RPM Package Manager",
    "Wine is not an emulator",
    "GNU is not Unix",
    "Golf is not an acronym",
    "X is a valid acronym"
};

var r = new Regex(pattern);
foreach (var str in input)
{
    var m = r.Match(str);
    Console.WriteLine(m.Success);
    for (int i = 0; i < m.Groups["w"].Captures.Count; ++i)
        Console.WriteLine(m.Groups["w"].Captures[i].Value);
}

Hier ist eine kurze Erklärung. Ich verwende die .NET- Bilanzgruppen , um cmit diesem Snippet einen Stapel der Akronymbuchstaben in der benannten Gruppe zu erstellen

^\w(?<c>\w)*

Der Trick ist, dass ich den zweiten Buchstaben oben auf dem Stapel und den letzten unten brauche. Also habe ich das alles in einen Lookbehind gesetzt, der der Position nach dem Akronym entspricht. Dies ist hilfreich, da .NET Lookbehinds von rechts nach links abgleicht und den letzten Buchstaben zuerst findet.

Sobald ich diesen Stapel habe, passe ich den Rest der Zeichenkette Wort für Wort an. Entweder beginnt das Wort mit dem Buchstaben oben auf dem Akronymstapel. In diesem Fall lösche ich diesen Brief aus dem Stapel:

 \k<c>(?<-c>)\w+

Ansonsten passe ich das Wort trotzdem an und schiebe es auf den wStapel, der dann alle Funktionswörter enthält:

 (?<w>\w+)

Am Ende stelle ich sicher, dass ich mit das Ende der Zeichenkette erreicht habe $und dass ich alle Buchstaben des Akronyms aufgebraucht habe, indem ich überprüfe, dass der Stapel leer ist:

(?(c)(?!))

Teste es auf ideone.

Martin Ender
quelle
1
Großartiger regulärer Ausdruck, aber die Frage lautet eindeutig "Sie können ein vollständiges Programm oder eine Funktion angeben ".
Zahnbürste
4
@toothbrush Wenn das OP beschließt, meine Antwort auf dieser Grundlage zu disqualifizieren, soll es so sein. Aber ich denke, ich könnte darauf hinweisen, dass dies ein vollständiges Programm in der Sprache ist, die den regulären Ausdruck von .NET darstellt (keine vollständige Sprache von Turing, die etwas umständlich in der Ausführung ist, aber dennoch eine Sprache). Auf jeden Fall mag ich die Tatsache, dass ich es mit einem reinen Regex-Ansatz gelöst habe, und ich würde die Antwort lieber disqualifizieren lassen, als diese "Eleganz" (wenn Sie so wollen) zu zerstören, indem ich sie "nur eine C # -Antwort mit Regex" mache ".
Martin Ender
Das ist okay für mich. Ich wollte Sie nur darauf hinweisen, falls Sie es verpasst haben.
Zahnbürste
1
Ich mag das. Regexes mögen keine Turing-vollständige Programmiersprache sein, aber ich denke, das sollte zählen.
Paul Draper
@PaulDraper Tatsächlich würde ich nicht einmal darauf wetten, dass .NETs Regex-Geschmack nicht vollständig ist ... die Balancing Groups und von rechts nach links aufeinander abgestimmten Lookbehinds sind ziemlich mächtig. Und PCRE zum Beispiel ist dafür bekannt, dass Turing vollständig ist (da es eine Rekursion gibt, bin ich mir nicht sicher, ob die Stapel in .NET ausreichen, um eine willkürliche Iteration zu emulieren).
Martin Ender
11

Python (158, ohne Regex)

Es ist nicht so, dass ich Regex nicht mag. Es ist so, dass ich sie nicht kenne.

def f(x):
 s=x.lower().split();w=list(s[0][1:]);s=s[1:];o=[]
 if not w:return 1,s
 [w.pop(0)if i[0]==w[0]else o.append(i)for i in s]
 return(0,)if w else(1,o)

Oh, ich hatte auch eine ungolfed Version:

def acronym(string):
    scentence = string.lower().split()
    word = scentence[0][1:]
    scentence = scentence[1:]
    over = []
    if not word: return 1, scentence
    for item in scentence:
        if item[0] == word[0]:
            word = word[1:]
        else:
            over.append(item)
    if word:
        return 0,
    return 1,over
ɐɔıɐɔuʇǝɥʇs
quelle
5

Python 2.7 - 131 126 Bytes

def f(s):
 s=s.lower().split();a,f=list(s[0]),[]
 for w in s:f+=0*a.pop(0)if a and w[0]==a[0]else[w]
 return(0,)if a else(1,f)

Erstellt eine Liste der Buchstaben im ersten Wort des Akronyms. Entfernen Sie dann für jedes Wort in der vollständigen Zeichenfolge das erste Element der Liste, die wir erstellt haben, wenn es mit dem ersten Buchstaben dieses Wortes identisch ist. Andernfalls fügen Sie dieses Wort zur Liste der Funktionswörter hinzu. Für die Ausgabe geben Sie not aFolgendes zurück (In Python ist jede Liste außer der leeren Liste True-y und die Liste ist leer, wenn es sich um ein rekursives Akronym handelt) und die Liste if not a.

Vielen Dank an @ace, der mir geholfen hat, einen Fehler zu beheben / einige Bytes zu speichern.

untergrundbahn
quelle
Auf Python 2.7.3 komme ich SyntaxError: invalid syntaxam Ende der returnZeile an.
pastebin.com Schrägstrich 0mr8spkT
@ace Huh, ich hätte schwören können, dass es funktioniert hat, als ich es getestet habe. Ich muss etwas geändert und vergessen haben, noch einmal zu testen. Ich werde an einer Lösung arbeiten!
undergroundmonorail
Sie können verwenden, for w in s:f+=0*a.pop(0)if a and w[0]==a[0]else[w]was kürzer ist und nicht auf Registerkarten angewiesen ist. Was die returnAussage betrifft, habe ich festgestellt, 0if a else(1,f)welche kürzer ist als dein Original.
pastebin.com Schrägstrich 0mr8spkT
Oh und wenn Sie Semikolons verwenden, um die ersten beiden Anweisungen in dieselbe Zeile zu setzen, sparen Sie ein Byte Einzug.
pastebin.com Schrägstrich 0mr8spkT
1
Ich habe einen Weg gefunden, um den Fehler zu beheben, aber als ich hierher zurückkam, um ihn zu posten, haben Sie ihn in den Kommentaren genauer beschrieben: P
undergroundmonorail
3

Python - 154 Zeichen

Erster Code Golf Versuch. Ich denke, dass Python nicht die beste Sprache dafür ist, wenn man die langen Schlüsselwörter bedenkt. Ich denke auch nicht, dass diese Funktion narrensicher ist. Es funktioniert für den OP-Eingang, aber ich bin sicher, ich könnte mir Ausnahmen ausdenken.

def f(s):
    w=s.lower().split();r=list(w[0]);return(True,[x for x in w if x[0]not in r])if len(r)==1 or[x for x in[y[0]for y in w]if x in r]==r else False
Obversität
quelle
Ich zähle 156 Zeichen (sowohl die Zeilenvorschub- als auch die Tabulatorzeichen), aber Sie können es zu Recht auf 154 reduzieren, indem Sie diese beiden Zeichen entfernen, da keines der beiden Zeichen tatsächlich erforderlich ist. Willkommen bei PPCG, übrigens. :)
undergroundmonorail
3

ECMAScript 6 (105 Byte):

f=s=>(r=(a=s.toUpperCase(i=1).split(' ')).map((w,c)=>c?a[0][i]==w[0]?(i++,''):w:''),a[0].length==i?1+r:0)

Geben Sie die Funktion in die Browserkonsole von Firefox ein und rufen Sie die Funktion wie folgt auf:

f('ABC Black Cats')     // 1,,
f('ABC is Black Cats')  // 1,IS,,
f('ABC Clapping Cats')  // 0
Zahnbürste
quelle
Nicht ganz den Vorschriften: The function words list ... must be given if and only if this is a recursive acronym. Dies wird sie trotzdem alarmieren.
MT0
@ MT0 OK. Ich habe diese Anforderung nicht bemerkt. Ich werde sehen, ob ich es umschreiben kann.
Zahnbürste
@ MT0 Ich habe den Code jetzt aktualisiert.
Zahnbürste
2

Haskell - 287 Bytes

Nicht der kürzeste Eintrag (hey das ist Haskell, was hast du erwartet?), Aber trotzdem viel Spaß beim Schreiben.

import Data.Char
import Data.List
f""w=map((,)False)w
f _[]=[]
f(a:as)(cs@(c:_):w) 
 |toLower a==toLower c=(True,cs):f as w
 |True=(False,cs):f(a:as)w
g s=if(length$filter(fst)d)==length v
  then Just$map(snd)$snd$partition(fst)d 
  else Nothing
 where 
  w=words s
  v=head w
  d=f v w

Getestet mit

map (g) ["RPM Package Manager","Wine is not an emulator","GNU is not Unix","Golf is not an acronym","X is a valid acronym"]

Erwartete Ausgabe

[Just [],Just ["an"],Just ["is"],Nothing,Just ["is","a","valid","acronym"]]

Ungolfed

import Data.Char
import Data.List

f :: String -> [String] -> [(Bool, String)]
f "" w = map ((,) False) w
f _ [] = []
f (a:as) ((c:cs):w) | toLower a == toLower c = (True, c:cs) : f as w
                    | otherwise = (False, c:cs) : f (a:as) w

g :: String -> Maybe [String]
g s = if (length $ filter (fst) d) == (length v)
          then Just $ map (snd) $ snd $ partition (fst) d 
          else Nothing
  where w = words s
        v = head w
        d = f v w
Gxtaillon
quelle
2

JavaScript (ECMAScript 6) - 97 Zeichen

f=x=>(r=(a=x.toLowerCase(i=0).split(' ')).filter(y=>y[0]!=a[0][i]||i-i++),i==a[0].length?[1,r]:0)

Tests:

f("RPM Package Manager")
[1, []]

f("GNU is not Unix")
[1, ["is"]]

f("X is an acronym")
[1, ["is", "an", "acronym"]]

f("Golf is not an acronym")
0

f("Wine is not an emulator")
[1, ["an"]]
MT0
quelle
1

Rebol - 133

f: func[s][w: next take s: split s" "y: collect[foreach n s[either n/1 = w/1[take w][keep n]]]reduce either/only w: empty? w[w y][w]]

Ungolfed:

f: func [s] [
    w: next take s: split s " "
    y: collect [
        foreach n s [
            either n/1 = w/1 [take w][keep n]
        ]
    ]
    reduce either/only w: empty? w [w y][w]
]

Getestet mit:

foreach t [
    "RPM Package Manager"  "Wine is not an emulator"  
    "GNU is not Unix"      "Golf is not an acronym"  
    "X is a valid acronym"
][probe f t]

Ausgabe:

[true []]
[true ["an"]]
[true ["is"]]
[false]
[true ["is" "a" "valid" "acronym"]]
draegtun
quelle
1

Julia - 116 Bytes

f(w)=(a=split(lowercase(w));L=1;A=a[];while a!=[];a[][1]==A[1]?A=A[2:]:(L=[L,a[]]);a=a[2:];A>""||return [L,a];end;0)

Weniger Golf:

f(w)=(
 a=split(lowercase(w))
 L=1
 A=a[]
 while a!=[]
  if a[][1]==A[1]
   A=A[2:]
  else
   L=[L,a[]]
  end
  a=a[2:]
  if !(A>"")
   return [L,a]
  end
 end
0)

Am 0Ende wird 0 ausgegeben. Andernfalls wird ein Array mit 1den folgenden Funktionswörtern ausgegeben . Beispielsweise:

julia> f("RPM Package Manager")
1-element Array{Any,1}:
 1

julia> f("Golf is not an acronym")
0

julia> f("GNU is not Unix")
2-element Array{Any,1}:
 1    
  "is"

julia> f("X is a valid acronym")
5-element Array{Any,1}:
 1         
  "is"     
  "a"      
  "valid"  
  "acronym"
Glen O
quelle
1

Brachylog , 29 Bytes

ḷṇ₁XhY∧X;0zpᵐz{ċ₂ˢ}ᵐZhhᵐcY∧Zt

Probieren Sie es online!

Gibt die Funktionswörter über die Ausgabevariable aus, wenn die Eingabe ein rekursives Akronym ist, und schlägt fehl, wenn dies nicht der Fall ist.

   X                             X is
ḷ                                the input lowercased
 ṇ₁                              and split on spaces,
    hY                           the first element of which is Y
      ∧                          (which is not X).
       X  z                      X zipped
        ;0                       with zero,
           pᵐ                    with all pairs permuted (creating a choicepoint),
             z                   zipped back,
              {   }ᵐ             and with both resulting lists
               ċ₂ˢ               losing all non-string elements,
                    Z            is Z.
                      hᵐ         The first elements of the elements of
                    Zh           the first element of Z
                        cY       concatenated are Y
                          ∧      (which is not Z).
                           Zt    The last element of Z is the output.

Ohne die Funktionswörter ausgeben zu müssen (dies als reines behandeln zu müssen ), sind es nur 12 Bytes, da ∧Ztsie für -3 fallengelassen werden Ykönnen, durch .-1 ersetzt werden können und vor allem ;0zpᵐz{ċ₂ˢ}ᵐZhdurch for ersetzt werden können eine satte -13:ḷṇ₁Xh.∧X⊇hᵐc

Nicht verwandte Zeichenfolge
quelle
0

Cobra - 187

def f(s as String)
    l=List<of String>(s.split)
    a=l[0]
    l.reverse
    o=0
    for c in a,for w in l.reversed
        if c==w[0]
            l.pop
            o+=1
            break
    x=o==a.length
    print x,if(x,l,'')
Οurous
quelle
0

Rubin - 173

Könnte besser sein...

 f=->s{a=[];o={};s=s.split;r=true;s[0].each_char{|c|s.each{|w| w[0]=~/#{c}/i?(o[c]=1;a<<w if o[c]):(o[c]=0 if !o[c])}};r,a=false,s if o.values&[0]==[0];!r ?[r]:[r,(s-(a&a))]}

Aufruf der Funk:

p f.call('RPM Package Manager')
p f.call('Wine is not an emulator')
p f.call("GNU is not Unix")
p f.call("Golf is not an acronym")
p f.call("X is a valid acronym")

Ausgabe :

[true, []]
[true, ["an"]]
[true, ["is"]]
[false]
[true, ["is", "a", "valid", "acronym"]]
Zwiebel
quelle
0

Java - 195

Leider hat Java keine Tupel-Unterstützung eingebaut.

Dies ist also eine Klasse, die den Booleschen Wert in 'b' und die Funktionswortliste in 'x' speichert.

Hier ist die Funktion der Konstruktor der Klasse.

static class R{boolean b;String[]x;R(String s){String v=" ",i="(?i)",f=s.split(v)[0],r=i+f.replaceAll("(?<=.)",".* ");if(b=(s+=v).matches(r))x=(s.replaceAll(i+"\\b["+f+"]\\S* ","")+v).split(v);}}

Prüfung

public class RecursiveAcronyms {
public static void main(String args[]) {
    String[] tests = {
            "RPM Package Manager",
            "Wine is not an emulator",
            "GNU is not Unix",
            "Golf is not an acronym",
            "X is a valid acronym"
        };
    for (String test:tests) {
        R r = new R(test);
        System.out.print(r.b);
        if (r.b) for (String s:r.x) System.out.print(" "+s);
        System.out.print("\n");
    }
}
static class R{boolean b;String[]x;R(String s){String v=" ",i="(?i)",f=s.split(v)[0],r=i+f.replaceAll("(?<=.)",".* ");if(b=(s+=v).matches(r))x=(s.replaceAll(i+"\\b["+f+"]\\S* ","")+v).split(v);}}}
Vektorisiert
quelle
C # hat Tupel, aber ich bin darauf gekommen, als ich an meiner Lösung gearbeitet habe: einfach zurückkehren string[]: nullbedeutet einfach falsch, leer bedeutet wahr und nElemente bedeuten wahr mit nFunktionswörtern.
Num Lock
Das würde ich auch gerne machen. OP gibt jedoch an, dass der Boolesche Wert unabhängig davon angegeben werden muss. Siehe die Antwort auf Jan Dvoraks Kommentar.
Vectorized
Die Kommentare interessieren mich nicht, da ich eine resultierende Änderung im ursprünglichen Beitrag nicht zu erkennen scheinen kann. Und selbst wenn ich es täte, heißt es eindeutig nur " den Booleschen Wert angeben ". Und selbst in der Antwort selbst steht " Ausgabeergebnis kann wahr / falsch sein, 0/1, ja / nein ... +", die ich an der Ellipse einfach um "* null / nicht null " erweitern könnte ...
Num Sperre
0

Awk - 145

awk -v RS=' ' '{c=tolower($0)};NR==1{w=c};{t=substr(c,1,1)!=substr(w,NR-s,1);if(t){f=f" "c;s++};a=a||t};END{print a&&(s>NR-length(w))?"N":"Y|"f}'

Prüfung:

$ cat gcp.sh
#!/bin/sh
f() {
echo "$1:"
echo "$1"|awk -v RS=' ' '{c=tolower($0)};NR==1{w=c};{t=substr(c,1,1)!=substr(w,NR-s,1);if(t){f=f" "c;s++};a=a||t};END{print a&&(s>NR-length(w))?"N":"Y|"f}'
}
f "RPM Package Manager"
f "Wine is not an emulator"
f "Wine is not an appropriate emulator"
f "GNU is not Unix"
f "Golf is not an acronym"
f "Go is not an acronym"
f "Go is a valid acronym OK"
f "X is a valid acronym"
f "YAML Ain't Markup Language"

$ ./gcp.sh
RPM Package Manager:
Y|
Wine is not an emulator:
Y| an
Wine is not an appropriate emulator:
Y| an appropriate
GNU is not Unix:
Y| is
Golf is not an acronym:
N
Go is not an acronym:
N
Go is a valid acronym OK:
Y| is a valid acronym
X is a valid acronym:
Y| is a valid acronym

YAML Ain't Markup Language:
Y|
hjk
quelle
0

Kaffeeskript - 144

z=(a)->g=" ";b=a.split g;c=b[0];d=[];(d.push(e);g++)for e,f in b when e[0].toLowerCase()!=c[f-g].toLowerCase();if(g+c.length==f)then{1,d}else{0}

Nennen Sie es zum Beispiel mit: z "GNU is not Unix"

Das kompilierte JS:

var z;
z = function(a) {
  var b, c, d, e, f, g, _i, _len;
  g = " ";
  b = a.split(g);
  c = b[0];
  d = [];
  for (f = _i = 0, _len = b.length; _i < _len; f = ++_i) {
    e = b[f];
    if (e[0].toLowerCase() !== c[f - g].toLowerCase()) {
      d.push(e);
      g++;
    }
  }
  if (g + c.length === f) {
    return {
      1: 1,
      d: d
    };
  } else {
    return {
      0: 0
    };
  }
};

Die Zeichenfolge wird in Wörter aufgeteilt und dann durch jedes Wort geschleift. Wenn das erste Zeichen des Wortes nicht mit dem nächsten im Akronym übereinstimmt, wird das Wort gespeichert. Ein Zähler ( g) wird verwendet, um zu verfolgen, wie viele Wörter übersprungen wurden. Wenn die Anzahl der übersprungenen Wörter plus die Länge des Akronyms mit der Länge der Phrase übereinstimmt, stimmt diese überein. Geben Sie also 1 und die übersprungenen Wörter zurück. Wenn nicht, war es ungültig, geben Sie also 0 zurück.

Johno
quelle
0

C # - 234

Tuple<bool,string[]> f(string w) {var l=w.ToLower().Split(' ');var o=new List<string>();int n=0;var a=l[0];foreach(var t in l){if(n>=a.Length||a[n]!=t[0])o.Add(t);else n++;}var r=n>=a.Length;return Tuple.Create(r,r?o.ToArray():null);}
Grax32
quelle
0

Python (108)

l=raw_input().lower().split()
a=l[0]
e=[]
for w in l:d=w[0]!=a[0];a=a[1-d:];e+=[w]*d  
b=a==''
print b,b*`e`
xnor
quelle