递归首字母缩写词


31

目的

来自维基百科

递归首字母缩写词是在其所代表的表达式中引用自身的首字母缩写词。

您的目标是检查字符串是否为递归首字母缩写。

  • 首字母缩写是第一个词
  • 单词不区分大小写,用单个空格分隔。
  • 给定的字符串不包含任何标点符号或撇号。
  • 首字母缩写只能是每个单词的第一个字母。

您还必须提供功能词。为简单起见,每个词都可以视为功能词。

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

您可以提供完整的程序或功能。
输入字符串可以取自STDIN或作为函数参数。
输出结果可以是true / false,0/1,yes / no ... 仅当这是递归首字母缩略词(即使列表为空)时,也
必须给出功能词列表(列表的任何格式均有效) 。您不必保留功能词的大写形式。

获奖标准

这是一个,最短的代码胜利。


4
我们是否必须保留功能词的大写?
algorithmhark

1
是否可以接受带有False值的字符串列表,或者否?
地下

1
由于单词列表本身通过其存在对布尔值进行编码,我们可以省略布尔值吗?
约翰·德沃夏克

5
Hurd代表Unix替换守护程序的Hird。Hird代表表示深度的接口Hurd。为什么这里的示例不理解这一点,并声称它们不是递归首字母缩写词?
Konrad Borowski

3
维基百科@xfix指出,这些是相互递归的缩写。
Michael M.

Answers:


7

GolfScript,51 50个字符

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

它可能可以打得更远。在STDIN上输入。布尔值为0/1。

在线测试


说明:

{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

正则表达式,.NET风格,62字节

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

您可以在这里进行测试。如果输入是递归首字母缩写词,则将产生匹配项,并且捕获组w将包含所有功能词。如果不是,那么将没有匹配项。

的确保留了功能词的大写形式(但不区分大小写地匹配)。

不幸的是,测试人员不会显示命名捕获组的整个堆栈,但是如果您在.NET中的任何地方使用它,则该w将按顺序包含所有功能词。

这是一个C#代码片段,以证明这一点:

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

这是一个简单的解释。我正在使用.NET的平衡组在此命名组中构建首字母缩写字母的堆栈c,并带有此代码段

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

诀窍是我需要在堆栈顶部放置第二个字母,在底部放置最后一个字母。因此,我将所有这些都放在了与首字母缩写的位置相匹配的后面。这是有帮助的,因为.NET从右到左匹配向后查找,因此它首先遇到最后一个字母。

一旦获得该堆栈,便将字符串的其余部分逐字匹配。单词都以首字母缩写词开头的字母开头。在那种情况下,我从堆栈中弹出那封信:

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

否则,无论如何我都会匹配单词并压入w堆栈,该堆栈将包含所有功能词:

 (?<w>\w+)

最后$,通过检查堆栈是否为空,确保通过到达字符串的末尾,并确保已用完首字母缩写词中的所有字母:

(?(c)(?!))

在ideone上进行测试。


1
很好的正则表达式,但问题明确指出“您可以提供完整的程序功能 ”。
牙刷

4
@toothbrush如果OP决定基于此取消我的回答的资格,那就这样吧。但是我想我可以指出一点,这是一个使用.NET正则表达式风格的语言的完整程序(不是图灵完整的语言,虽然运行起来有点麻烦,但仍然是一种语言)。无论如何,我喜欢我用纯正则表达式方法解决它的事实,我宁愿答案被取消资格,也不愿通过使它“仅使用regex进行C#回答”来破坏“优雅”(如果您愿意)。 ”。
马丁·恩德2014年

这对我来说没问题。我只是想指出一下,以防您错过它。
牙刷

1
我喜欢。正则表达式可能不是图灵完备的编程语言,但我认为这应该算在内。
Paul Draper 2014年

@PaulDraper实际上,我什至不会打赌.NET的正则表达式风格不会很完善。例如,众所周知,PCRE是图灵完备的(具有递归功能,我不确定.NET中的堆栈足以模拟任意迭代)。
马丁·恩德

11

Python(158,不使用正则表达式)

不是我不喜欢正则表达式。是我不认识他们。

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)

哦,我还有一个非高尔夫版本:

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字节

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)

在首字母缩写词的第一个单词中列出字母列表。然后,对于完整字符串中的每个单词,如果它与该单词的第一个字母相同,则摆脱该列表中的第一个元素。否则,将该单词添加到功能单词列表中。要输出,请返回not a(在python中,空列表以外的任何列表都是True-y,如果是递归首字母缩写,则列表为空),如果列表为,则返回not a

感谢@ace帮助我解决错误/保存一些字节。


在Python 2.7.3上,我到SyntaxError: invalid syntaxreturn行尾。
pastebin.com斜线0mr8spkT 2014年

@ace Huh,当我测试它时,我可以宣誓它可以工作。我一定已经改变了一些,忘了再次测试。我会修复的!
地下

您可以使用for w in s:f+=0*a.pop(0)if a and w[0]==a[0]else[w]更短且不依赖标签的标签。至于return声明,我发现0if a else(1,f)它比您原来的要短。
pastebin.com斜线0mr8spkT 2014年

哦,如果您使用分号将前两个语句放在同一行中,则会节省一个缩进字节。
pastebin.com斜线0mr8spkT 2014年

1
我想出了一个办法修正这个错误,但是当我回到这里张贴你有golfed下来更多的意见:P
undergroundmonorail

3

Python-154个字符

第一次尝试打高尔夫球。考虑到所有长关键字,我认为python并不是最佳语言。另外,我认为此功能并非万无一失。它适用于OP的输入,但是我敢肯定我会考虑例外情况。

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

我数了156个字符(换行符和制表符都算在内),但是您可以通过删除这两个字符将其合法地减少到154个,因为实际上这两个字符都不是必需的。欢迎来到PPCG,顺便说一句。:)
Undergroundmonorail

3

ECMAScript 6(105字节):

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)

在Firefox的浏览器控制台中输入该函数,然后像下面这样调用该函数:

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

不太符合以下规则:The function words list ... must be given if and only if this is a recursive acronym。无论如何,这都会提醒他们。
MT0

@ MT0好。我没有注意到那个要求。我看看是否可以重写它。
牙刷

@ MT0我现在更新了代码。
牙刷

2

Haskell-287字节

不是最短的条目(嘿,这是Haskell,您期望什么?),但是编写仍然很有趣。

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

经过测试

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

预期产量

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

不打高尔夫球

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个字符

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)

测试:

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

取消高尔夫:

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

经过测试:

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]

输出:

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

1

朱莉娅-116字节

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)

少打高尔夫球:

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)

所述0在端部使得输出0。否则,它输出包含数组1后跟函数的话。例如:

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个字节

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

在线尝试!

如果输入是递归首字母缩略词,则通过输出变量输出功能词,如果输入不是,则失败。

   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.

无需输出功能词(将此作为纯),它只有12个字节,因为∧Zt可以将其丢弃为-3,Y可以将其替换.为-1,最重要的是;0zpᵐz{ċ₂ˢ}ᵐZh可以将其替换为高达-13:ḷṇ₁Xh.∧X⊇hᵐc


0

眼镜蛇-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

红宝石-173

有待改善...

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

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

输出:

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

0

爪哇-195

不幸的是,Java没有内置的元组支持。

因此,这是一个将布尔值存储在“ b”中并将功能词列表存储在“ x”中的类。

在这里,函数是类的构造函数。

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

测试

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#有元组,但是我在解决方案时想到了这一点:return string[]null简单地表示false,空表示true,而n元素则表示带有n函数词的true 。
Num Lock

我也想这样做。但是OP指定无论如何都必须提供布尔值。请参阅对Jan Dvorak的评论的答复。
2014年

我不在乎评论,因为我似乎无法在原始帖子中发现结果编辑。即使我做了,它显然只是说要“ 指定布尔值 ”。甚至在答案本身中也说“ 输出结果可以是true / false,0/1,yes / no ... +”,我可能会在省略号处使用“ * null / not null ” ...
Num锁定

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

测试:

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

调用它,例如: z "GNU is not Unix"

编译后的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
    };
  }
};

它将字符串拆分成单词,然后遍历每个单词。如果单词的第一个字符与首字母缩写的下一个字符不匹配,则会存储单词。计数器(g)用于跟踪已跳过多少个单词。如果跳过的单词数加上首字母缩写的长度与短语的长度匹配,则表示匹配,因此返回1和跳过的单词。如果不是,则无效,因此返回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

巨蟒(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`
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.