Akronimy rekurencyjne


31

Cel

Z Wikipedii :

Akronim rekurencyjny to akronim, który odnosi się do siebie w wyrażeniu, za którym stoi.

Twoim celem jest sprawdzenie, czy łańcuch jest akronimem rekurencyjnym.

  • Akronim to pierwsze słowo
  • W słowach nie jest rozróżniana wielkość liter, oddzielone pojedynczym odstępem.
  • Podany ciąg nie zawiera interpunkcji ani apostrofu.
  • Tylko pierwsza litera każdego słowa może być częścią akronimu.

Musisz także podać słowa funkcyjne . Dla uproszczenia każde słowo można uznać za słowo funkcyjne.

Przykład

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"] }  

Możesz podać pełny program lub funkcję.
Łańcuch wejściowy można pobrać z STDIN lub jako argument funkcji.
Wynik może być prawdziwy / fałszywy, 0/1, tak / nie ...
Lista słów funkcyjnych (każdy format listy jest poprawny) musi być podana tylko wtedy, gdy jest to rekurencyjny akronim (nawet jeśli lista jest pusta) . Nie musisz zachowywać wielkich liter słów funkcyjnych.

Kryteria wygranej

To jest , najkrótszy kod wygrywa.


4
Czy musimy zachować wielkie litery słów funkcyjnych?
algorytmshark

1
Czy dopuszczalne jest posiadanie listy ciągów towarzyszących fałszywej wartości, czy nie?
metro

1
Ponieważ sama lista słów koduje wartość logiczną poprzez jej obecność, czy możemy pominąć wartość logiczną?
John Dvorak

5
Hurd oznacza Hird of Unix-Replacing Daemons. Hird oznacza Hurd of Interfaces Reprezentujących głębię. Dlaczego przykłady tutaj tego nie rozumieją i twierdzą, że nie są to rekurencyjne akronimy?
Konrad Borowski

3
@xfix, wikipedia stwierdza, że ​​są to wzajemnie rekurencyjne akronimy.
Michael M.

Odpowiedzi:


7

GolfScript, 51 50 znaków

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

Prawdopodobnie można go jeszcze pograć w golfa. Pobiera dane wejściowe na STDIN. Wartość logiczna to 0/1.

Przetestuj online


Wyjaśnienie:

{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

22

Regex, smak .NET, 62 bajty

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

Możesz to przetestować tutaj . Jeśli dane wejściowe są akronimem rekurencyjnym, spowoduje to dopasowanie, a grupa przechwytywania wbędzie zawierać wszystkie słowa funkcyjne. Jeśli tak nie jest, to nie będzie dopasowania.

Pozwala to zachować wielkie litery słów funkcyjnych (ale bez rozróżniania wielkości liter).

Niestety tester nie wyświetla całego stosu nazwanej grupy przechwytywania, ale jeśli użyjesz jej w dowolnym miejscu w .NET, wgrupa będzie zawierać wszystkie słowa funkcyjne w kolejności.

Oto fragment kodu C #, aby udowodnić, że:

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

Oto krótkie wyjaśnienie. Korzystam z grup równoważących .NET do zbudowania stosu liter akronimu w nazwanej grupie c, za pomocą tego fragmentu

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

Sztuczka polega na tym, że potrzebuję drugiej litery na górze stosu i ostatniej na dole. Umieściłem to wszystko tak, aby pasowało do pozycji po akronimie. Pomaga to, ponieważ .NET dopasowuje wygląd od prawej do lewej, więc najpierw napotyka ostatnią literę.

Po uzyskaniu stosu dopasowuję resztę łańcucha słowo w słowo. Albo słowo zaczyna się od litery na szczycie stosu akronimów. W takim przypadku usuwam tę literę ze stosu:

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

W przeciwnym razie i tak dopasowuję to słowo i pcham na wstos, który następnie zawiera wszystkie słowa funkcyjne:

 (?<w>\w+)

Na końcu upewniam się, że dotarłem do końca łańcucha, $a także upewniłem się, że zużyłem wszystkie litery z akronimu, sprawdzając, czy stos jest pusty:

(?(c)(?!))

Przetestuj na ideonie.


1
Świetne wyrażenie regularne, ale pytanie wyraźnie mówi „Możesz podać pełny program lub funkcję ”.
Szczoteczka do zębów

4
@toothbrush Jeśli OP zdecyduje się zdyskwalifikować moją odpowiedź na tej podstawie, niech tak będzie. Ale myślę, że mógłbym wskazać, że jest to pełny program w języku, który jest smakiem wyrażeń regularnych .NET (nie jest to pełny język Turinga i taki, który jest nieco kłopotliwy w obsłudze, ale mimo to językiem). W każdym razie podoba mi się fakt, że rozwiązałem go z czysto regexowym podejściem i wolę mieć odpowiedź zdyskwalifikowaną niż zniszczyć tę „elegancję” (jeśli chcesz), czyniąc ją „tylko odpowiedzią C # przy użyciu regex „.
Martin Ender

Dla mnie w porządku. Chciałem tylko to wskazać na wypadek, gdybyś tego przegapił.
Szczoteczka do zębów

1
Lubię to. Regeksy mogą nie być kompletnym językiem programowania Turinga, ale myślę, że to powinno się liczyć.
Paul Draper

@PaulDraper W rzeczywistości nie postawiłbym nawet na to, że smak regularny .NET nie jest Turinga kompletny ... grupy równoważące i wyglądające od prawej do lewej strony są dość potężne. I na przykład wiadomo, że PCRE jest zakończony Turinga (ten ma rekurencję, nie jestem pewien, czy stosy w .NET są wystarczające do emulacji dowolnej iteracji).
Martin Ender

11

Python (158, bez wyrażenia regularnego)

To nie tak, że nie lubię wyrażeń regularnych. Po prostu ich nie znam.

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)

Och, miałem też wersję bez golfa:

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

5

Python 2.7 - 131 126 bajtów

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)

Tworzy listę liter w pierwszym słowie akronimu. Następnie, dla każdego słowa w pełnym ciągu, pozbądź się pierwszego elementu listy, który stworzyliśmy, jeśli jest taka sama jak pierwsza litera tego słowa. W przeciwnym razie dodaj to słowo do listy słów funkcyjnych. Aby wyprowadzić, zwróć not a(w pythonie dowolna lista inna niż pusta lista to True-y, a lista jest pusta, jeśli jest to akronim rekurencyjny), a lista if not a.

Dzięki @ace za pomoc w naprawieniu błędu / zapisaniu niektórych bajtów.


W Pythonie 2.7.3 dostaję się SyntaxError: invalid syntaxna końcu returnlinii.
pastebin.com slash 0mr8spkT

@ace Huh, mogłem przysiąc, że zadziałało, kiedy go przetestowałem. Musiałem coś zmienić i zapomniałem przetestować ponownie. Popracuję nad poprawką!
metro

Możesz użyć, for w in s:f+=0*a.pop(0)if a and w[0]==a[0]else[w]który jest krótszy i nie opiera się na kartach. Co do returnoświadczenia, znalazłem 0if a else(1,f)krótszy niż twój oryginał.
pastebin.com slash 0mr8spkT

Aha, a jeśli użyjesz średników do umieszczenia pierwszych dwóch instrukcji w tym samym wierszu, zaoszczędzisz jeden bajt wcięcia.
pastebin.com slash 0mr8spkT

1
Wymyśliłem sposób, aby naprawić błąd, ale kiedy wróciłem tutaj, aby go opublikować, grałeś w golfa bardziej w komentarzach: P
metro

3

Python - 154 znaków

Pierwsza w historii próba gry w golfa. Myślę, że Python nie jest najlepszym językiem do tego, biorąc pod uwagę wszystkie długie słowa kluczowe. Ponadto nie sądzę, aby ta funkcja była niezawodna. Działa dla wkładu OP, ale jestem pewien, że mógłbym wymyślić wyjątki.

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

Zliczam 156 znaków (zarówno nowy znak, jak i tabulator), ale możesz sprowadzić go do 154, usuwając te dwa znaki, ponieważ żaden z nich nie jest wymagany. Witamy w PPCG, btw. :)
undergroundmonorail

3

ECMAScript 6 (105 bajtów):

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)

Wprowadź funkcję w konsoli przeglądarki Firefox, a następnie po prostu wywołaj funkcję w następujący sposób:

f('ABC Black Cats')     // 1,,
f('ABC is Black Cats')  // 1,IS,,
f('ABC Clapping Cats')  // 0

Nie całkiem zgodne z zasadami: The function words list ... must be given if and only if this is a recursive acronym. To ostrzeże ich niezależnie.
MT0

@ MT0 OK. Nie zauważyłem tego wymogu. Zobaczę, czy mogę to przepisać.
Szczoteczka do zębów

@ MT0 Zaktualizowałem kod teraz.
Szczoteczka do zębów

2

Haskell - 287 bajtów

Nie jest to najkrótszy wpis (hej, to jest Haskell, czego się spodziewałeś?), Ale nadal dużo zabawy w pisaniu.

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

Testowane z

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

Oczekiwany wynik

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

Bez golfa

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

2

JavaScript (ECMAScript 6) - 97 znaków

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)

Testy:

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

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

Nie golfowany:

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

Testowane z:

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]

Wydajność:

[true []]
[true ["an"]]
[true ["is"]]
[false]
[true ["is" "a" "valid" "acronym"]]

1

Julia - 116 bajtów

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)

Mniej gra w golfa:

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)

Na 0końcu wyświetla wynik 0. W przeciwnym razie wyświetla tablicę zawierającą 1słowa funkcyjne. Na przykład:

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"

1

Brachylog , 29 bajtów

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

Wypróbuj online!

Wysyła słowa funkcyjne przez zmienną wyjściową, jeśli dane wejściowe są akronimem rekurencyjnym, i kończy się niepowodzeniem, jeśli nie jest.

   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.

Bez konieczności wypisywania słów funkcyjnych (traktując to jako czysty ), powstaje tylko 12 bajtów, ponieważ ∧Ztmożna je pominąć dla -3, Ymożna je zastąpić .przez -1, a co najważniejsze ;0zpᵐz{ċ₂ˢ}ᵐZhmożna zastąpić przez a -13:ḷṇ₁Xh.∧X⊇hᵐc


0

Kobra - 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,'')

0

Rubin - 173

Może być lepiej...

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

Wywoływanie func:

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

Wyjście:

[true, []]
[true, ["an"]]
[true, ["is"]]
[false]
[true, ["is", "a", "valid", "acronym"]]

0

Java - 195

Niestety Java nie ma wbudowanej obsługi krotek.

Jest to klasa przechowująca wartość logiczną w „b” i listę słów funkcyjnych w „x”.

Tutaj funkcja jest konstruktorem klasy.

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

Test

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

C # ma krotki, ale wymyśliłem to podczas pracy nad moim rozwiązaniem: po prostu powróć string[]: nullpo prostu oznacza fałsz, puste oznacza prawda, a nelementy oznaczają prawda ze nsłowami funkcyjnymi.
Num Lock

Też chciałbym to zrobić. Jednak OP określa, że ​​wartość logiczna musi zostać podana niezależnie. Zobacz odpowiedź na komentarz Jana Dvoraka.
Vectorized

Nie dbam o komentarze, ponieważ nie mogę znaleźć poprawionej edycji w oryginalnym poście. I nawet jeśli tak , to wyraźnie mówi „ określić wartość logiczną ”. I nawet w samej odpowiedzi mówi: „ Wynik może być prawdziwy / fałszywy, 0/1, tak / nie ... +”, który mógłbym po prostu rozszerzyć na elipsie o „* null / not null ” ...
Num Zablokuj

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}'

Test:

$ 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|

0

Coffeescript - 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}

Nazwij to na przykład: z "GNU is not Unix"

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

Dzieli ciąg na słowa, a następnie zapętla każde słowo. Jeśli pierwszy znak słowa nie pasuje do następnego w akronimie, słowo zostanie zapisane. Licznik ( g) służy do śledzenia, ile słów zostało pominiętych. Jeśli liczba pominiętych słów plus długość akronimu odpowiada długości frazy, to pasuje, więc zwróć 1 i pominięte słowa. Jeśli nie, to nie jest poprawny, więc zwróć 0.


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

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`
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.