Acronymes récursifs

31

Objectif

De Wikipédia :

Un acronyme récursif est un acronyme qui se réfère à lui-même dans l'expression qu'il représente.

Votre objectif est de vérifier si une chaîne est un acronyme récursif.

  • L'acronyme est le premier mot
  • Les mots ne sont pas sensibles à la casse, séparés par un seul espace.
  • La chaîne donnée ne contient aucune ponctuation ni apostrophe.
  • Seule la première lettre de chaque mot peut faire partie de l'acronyme.

Vous devez également donner les mots de fonction . Par souci de simplicité, chaque mot peut être considéré comme un mot fonction.

Exemple

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

Vous pouvez donner un programme complet ou une fonction.
La chaîne d'entrée peut être extraite de STDIN ou comme argument de fonction.
Le résultat de sortie peut être vrai / faux, 0/1, oui / non ...
La liste des mots de fonction (n'importe quel format de liste est valide) doit être donnée si et seulement s'il s'agit d'un acronyme récursif (même si la liste est vide) . Il n'est pas nécessaire de conserver la capitalisation des mots de fonction.

Critères gagnants

Ceci est un , le code le plus court gagne.

Michael M.
la source
4
Faut-il conserver la capitalisation des mots de fonction?
algorithmshark
1
Est-il acceptable d'avoir une liste de chaînes accompagnant une valeur False, ou non?
métro
1
Puisque la liste de mots elle-même code la valeur booléenne par sa présence, pouvons-nous omettre le booléen?
John Dvorak
5
Hurd est l'abréviation de Hird of Unix-Replacing Daemons. Hird signifie Hurd of Interfaces Representing Depth. Pourquoi les exemples ici ne comprennent pas cela et prétendent que ce ne sont pas des acronymes récursifs?
Konrad Borowski
3
@xfix, wikipedia indique que ce sont des acronymes mutuellement récursifs .
Michael M.

Réponses:

7

GolfScript, 51 50 caractères

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

Il peut probablement être joué plus loin. Prend entrée sur STDIN. Le booléen est 0/1.

Testez en ligne


Explication:

{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
Volatilité
la source
22

Regex, saveur .NET, 62 octets

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

Vous pouvez le tester ici . Si l'entrée est un acronyme récursif, cela donnera une correspondance et le groupe de capture wcontiendra tous les mots de fonction. Si ce n'est pas le cas, il n'y aura pas de correspondance.

Cela fait préserver la capitalisation des mots de fonction (mais correspond insensible à la casse).

Malheureusement, le testeur ne montre pas l'ensemble de la pile d'un groupe de capture nommé, mais si vous l' avez utilisé partout dans .NET, le wgroupe ne contient tous les mots de fonction dans l' ordre.

Voici un extrait C # pour prouver que:

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

Voici une explication rapide. J'utilise les groupes d'équilibrage de .NET pour créer une pile de lettres acronymes dans le groupe nommé c, avec cet extrait

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

L'astuce est que j'ai besoin de la deuxième lettre en haut de la pile et la dernière en bas. J'ai donc mis tout cela dans un lookbehind qui correspond à la position après l'acronyme. Cela aide, car .NET fait correspondre les regards de droite à gauche, donc il rencontre d'abord la dernière lettre.

Une fois que j'ai obtenu cette pile, je fais correspondre le reste de la chaîne mot à mot. Soit le mot commence par la lettre en haut de la pile des acronymes. Dans ce cas, je pop cette lettre de la pile:

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

Sinon, je fais quand même correspondre le mot et je pousse sur la wpile qui contiendra alors tous les mots de fonction:

 (?<w>\w+)

À la fin, je m'assure d'avoir atteint la fin de la chaîne avec $et je m'assure également d'avoir utilisé toutes les lettres de l'acronyme, en vérifiant que la pile est vide:

(?(c)(?!))

Testez-le sur ideone.

Martin Ender
la source
1
Grande expression régulière, mais la question indique clairement "Vous pouvez donner un programme complet ou une fonction ".
Brosse à dents
4
@toothbrush Si l'OP décide de disqualifier ma réponse sur cette base, qu'il en soit ainsi. Mais je pense que je pourrais faire valoir qu'il s'agit d'un programme complet dans le langage qui est l'arôme d'expression régulière de .NET (pas un langage complet de Turing, et un peu lourd à exécuter, mais un langage néanmoins). En tout cas, j'aime le fait que je l'ai résolu avec une approche pure-regex, et je préfère avoir la réponse disqualifiée plutôt que de détruire cette "élégance" (si vous voulez) en en faisant "juste une réponse C # en utilisant regex ".
Martin Ender
Ça me va. Je voulais juste le signaler au cas où vous l'auriez manqué.
Brosse à dents
1
Je l'aime. Les regex ne sont peut-être pas un langage de programmation complet de Turing, mais je pense que cela devrait compter.
Paul Draper
@PaulDraper En fait, je ne parierais même pas sur la saveur regex de .NET qui n'est pas complète Turing ... les groupes d'équilibrage et les lookbehinds assortis de droite à gauche sont assez puissants. Et PCRE par exemple est connu pour être Turing complet (celui-ci a une récursivité, je ne suis pas sûr que les piles dans .NET soient suffisantes pour émuler une itération arbitraire).
Martin Ender
11

Python (158, sans regex)

Ce n'est pas que je n'aime pas les regex. C'est que je ne les connais pas.

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, j'avais aussi une version non golfée:

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
la source
5

Python 2.7 - 131 126 octets

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)

Fait une liste de lettres dans le premier mot de l'acronyme. Ensuite, pour chaque mot de la chaîne complète, supprimez le premier élément de cette liste que nous avons créé s'il est identique à la première lettre de ce mot. Sinon, ajoutez ce mot à la liste des mots de fonction. Pour afficher, renvoyer not a(en python, toute liste autre que la liste vide est True-y, et la liste est vide s'il s'agit d'un acronyme récursif) et la liste if not a.

Merci à @ace de m'avoir aidé à corriger une erreur / enregistrer quelques octets.

métro monorail
la source
Sur Python 2.7.3, j'arrive SyntaxError: invalid syntaxen fin de returnligne.
user12205
@ace Huh, j'aurais juré que ça fonctionnait quand je l'ai testé. J'ai dû changer quelque chose et j'ai oublié de tester à nouveau. Je vais travailler sur un correctif!
métro monorail
Vous pouvez utiliser for w in s:f+=0*a.pop(0)if a and w[0]==a[0]else[w]ce qui est plus court et ne repose pas sur des onglets. Quant à la returndéclaration, j'ai trouvé celle 0if a else(1,f)qui est plus courte que l'original.
user12205
Oh et si vous utilisez des points-virgules pour mettre les deux premières instructions dans la même ligne, vous enregistrez un octet d'indentation.
user12205
1
J'ai trouvé un moyen de corriger l'erreur, mais quand je suis revenu ici pour le poster, vous l'aviez plus bas dans les commentaires: P
undergroundmonorail
3

Python - 154 caractères

Première tentative de golf par code. Je pense que le python n'est pas le meilleur langage pour cela, étant donné tous les mots-clés longs. De plus, je ne pense pas que cette fonction soit infaillible. Cela fonctionne pour l'entrée du PO, mais je suis sûr que je pourrais imaginer des exceptions.

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é
la source
Je compte 156 caractères (la nouvelle ligne et le caractère de tabulation comptent tous les deux), mais vous pouvez le réduire à 154 légitimement en supprimant ces deux caractères car aucun n'est réellement requis. Bienvenue chez PPCG, btw. :)
undergroundmonorail
3

ECMAScript 6 (105 octets):

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)

Entrez la fonction dans la console du navigateur de Firefox, puis appelez simplement la fonction, comme ceci:

f('ABC Black Cats')     // 1,,
f('ABC is Black Cats')  // 1,IS,,
f('ABC Clapping Cats')  // 0
Brosse à dents
la source
Ne pas tout à fait conforme aux règles: The function words list ... must be given if and only if this is a recursive acronym. Cela les alertera malgré tout.
MT0
@ MT0 OK. Je n'ai pas remarqué cette exigence. Je vais voir si je peux le réécrire.
Brosse à dents
@ MT0 J'ai mis à jour le code maintenant.
Brosse à dents
2

Haskell - 287 octets

Pas l'entrée la plus courte (hé c'est Haskell, à quoi vous attendiez-vous?), Mais toujours très amusante à écrire.

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

Testé avec

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

Production attendue

[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
la source
2

JavaScript (ECMAScript 6) - 97 caractères

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

Testé avec:

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]

Sortie:

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

Julia - 116 octets

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)

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

Le 0sur la fin le fait sortir 0. Sinon, il sort un tableau contenant 1suivi des mots de fonction. Par exemple:

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
la source
1

Brachylog , 29 octets

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

Essayez-le en ligne!

Génère les mots de fonction via la variable de sortie si l'entrée est un acronyme récursif et échoue dans le cas contraire.

   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.

Sans avoir à sortir les mots de fonction (en traitant cela comme un pur ), cela ne fait que 12 octets, car ∧Ztpeut être supprimé pour -3, Ypeut être remplacé par .pour -1, et surtout ;0zpᵐz{ċ₂ˢ}ᵐZhpeut être remplacé par pour un énorme -13:ḷṇ₁Xh.∧X⊇hᵐc

Chaîne non liée
la source
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
la source
0

Rubis - 173

Cela pourrait être mieux...

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

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

Sortie:

[true, []]
[true, ["an"]]
[true, ["is"]]
[false]
[true, ["is", "a", "valid", "acronym"]]
onionpsie
la source
0

Java - 195

Malheureusement, Java n'a pas de support de tuple intégré.

Donc, c'est une classe qui stocke le booléen dans 'b' et la liste des mots de fonction dans 'x'.

Ici, la fonction est le constructeur de la classe.

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

Tester

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);}}}
Vectorisé
la source
C # a des tuples mais je suis venu avec ceci en travaillant sur ma solution: juste retourner string[]: nullsignifie simplement faux, vide signifie vrai et néléments signifie vrai avec ndes mots de fonction.
Verrouillage numérique
J'aimerais le faire aussi. Cependant, OP spécifie que le booléen doit être fourni malgré tout. Voir la réponse au commentaire de Jan Dvorak.
Vectorisé
Je ne me soucie pas des commentaires car je n'arrive pas à repérer une modification résultante dans le message d'origine. Et même si je l'ai fait , cela dit clairement de " spécifier le booléen ". Et même dans la réponse elle-même, il dit " Le résultat de sortie peut être vrai / faux, 0/1, oui / non ... +" que je pourrais simplement étendre aux points de suspension par "* null / not null " ...
Num Écluse
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}'

Tester:

$ 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
la source
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}

Appelez-le avec, par exemple: z "GNU is not Unix"

Le JS compilé:

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

Il divise la chaîne en mots, puis parcourt chaque mot. Si le premier caractère du mot ne correspond pas au suivant dans l'acronyme, le mot est stocké. Un compteur ( g) permet de suivre le nombre de mots ignorés. Si le nombre de mots ignorés plus la longueur de l'acronyme correspond à la longueur de la phrase, il correspond, donc renvoyez 1 et les mots ignorés. Sinon, il n'était pas valide, retournez donc 0.

Johno
la source
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
la source
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
la source