재귀 약어


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가 될 수 있습니다
. 함수 단어 list (모든 형식의 목록이 유효 함)는 이것이 순환 약어 인 경우에만 (목록이 비어있는 경우에도) 제공되어야합니다. . 함수 단어의 대문자를 유지하지 않아도됩니다.

우승 기준

이것은 , 최단 코드 승리입니다.


4
함수 단어의 대문자를 유지해야합니까?
algorithmshark

1
False 값을 수반하는 문자열 목록을 갖는 것이 허용됩니까?
undergroundmonorail

1
단어 목록 자체는 존재 여부에 따라 부울 값을 인코딩하므로 부울을 생략해도됩니까?
John Dvorak

5
허드는 Hix of Unix-Replacing Daemons의 약자입니다. 허드는 심도를 나타내는 인터페이스의 허드 (Hud of Interfaces)를 나타냅니다. 여기 예제가 왜 이해하지 못하고 재귀 약어가 아니라고 주장합니까?
Konrad Borowski

3
@xfix, Wikipedia는 상호 재귀 약어입니다.
Michael M.

답변:


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

비결은 스택 상단에 두 번째 문자가 있고 하단에 마지막 문자가 필요하다는 것입니다. 그래서 나는이 모든 것을 약어 의 위치와 일치하는 lookbehind에 넣었습니다 . .NET은 lookbehinds를 오른쪽에서 왼쪽으로 일치시키기 때문에 마지막 문자가 먼저 나옵니다.

일단 그 스택을 얻으면 나머지 문자열 단어를 단어와 일치시킵니다. 단어는 약어 스택 맨 위에있는 문자로 시작합니다. 이 경우 스택에서 해당 문자를 팝합니다.

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

그렇지 않으면 어쨌든 단어를 일치시키고 w스택에 밀어 넣고 모든 기능 단어를 포함합니다.

 (?<w>\w+)

마지막으로 문자열 끝에 도달 $했는지 확인하고 스택이 비어 있는지 확인하여 약어의 모든 문자를 모두 사용했는지 확인하십시오.

(?(c)(?!))

이데온에서 테스트하십시오.


1
Great regular expression, but the question clearly states "You can give a full program or a function".
Toothbrush

4
@toothbrush If the OP decides to disqualify my answer based on that, so be it. But I think I could make a point that this is a full program in the language which is .NET's regular expression flavour (not a Turing complete language, and one that is a bit cumbersome to run, but a language nevertheless). In any case, I like the fact that I solved it with a pure-regex approach, and I'd rather have the answer disqualified than destroy that "elegance" (if you will) by making it "just a C#-answer using regex".
Martin Ender

That's fine with me. I just wanted to point it out in case you missed it.
Toothbrush

1
I like it. Regexes may not be a Turing-complete programming language, but I think this should count.
Paul Draper

@PaulDraper In fact, I wouldn't even bet on .NET's regex flavour not being Turing complete... the balancing groups and right-to-left-matched lookbehinds are pretty powerful. And PCRE for instance is known to be Turing complete (that one has recursion, I'm not sure the stacks in .NET are sufficient to emulate arbitrary iteration).
Martin Ender

11

Python (158, without regex)

It's not that I don't like regexes. It's that I don't know them.

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, I also had an 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

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)

Makes a list of letters in the first word of the acronym. Then, for each word in the full string, get rid of the first element of that list we made if it is the same as the first letter of that word. Otherwise, add that word to the list of function words. To output, return not a (In python, any list other than the empty list is True-y, and the list is empty if it's a recursive acronym) and the list if not a.

Thanks to @ace for helping me fix an error/save some bytes.


On Python 2.7.3, I get SyntaxError: invalid syntax at the end of the return line.
pastebin.com slash 0mr8spkT

@ace Huh, I could have sworn it worked when I tested it. I must have changed something and forgot to test again. I'll work on a fix!
undergroundmonorail

You can use for w in s:f+=0*a.pop(0)if a and w[0]==a[0]else[w] which is shorter and doesn't rely on tabs. As for the return statement, I found 0if a else(1,f) which is shorter than your original.
pastebin.com slash 0mr8spkT

Oh and if you use semicolons to put the first two statements in the same line you save one byte of indentation.
pastebin.com slash 0mr8spkT

1
I figured out a way to fix the error, but when I came back here to post it you had golfed it down more in the comments :P
undergroundmonorail

3

Python - 154 characters

First ever code golf attempt. I'm thinking python isn't the best language for it, given all the long keywords. Also, I don't think this function is foolproof. It works for the OP's input, but I'm sure I could think up 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

I count 156 characters (the newline and the tab character both count), but you can get it down to 154 legitimately by removing those two characters since neither are actually required. Welcome to PPCG, btw. :)
undergroundmonorail

3

ECMAScript 6 (105 bytes):

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)

Enter the function in Firefox's browser console, and then just call the function, like this:

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

Doesn't quite comply with the rules: The function words list ... must be given if and only if this is a recursive acronym. This will alert them regardless.
MT0

@MT0 OK. I didn't notice that requirement. I'll see if I can rewrite it.
Toothbrush

@MT0 I've updated the code now.
Toothbrush

2

Haskell - 287 bytes

Not the shortest entry (hey this is Haskell, what did you expect?), but still a lot a fun to write.

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

Tested with

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

Expected output

[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

2

JavaScript (ECMAScript 6) - 97 Characters

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

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

Tested with:

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]

Output:

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

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)

Less Golfed:

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)

The 0 on the end makes it output 0. Otherwise, it outputs an array containing 1 followed by the function words. For example:

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 bytes

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

Try it online!

Outputs the function words through the output variable if the input is a recursive acronym, and fails if it is not.

   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.

Without having to output the function words (treating this as a pure ), it comes out to just 12 bytes, because ∧Zt can be dropped for -3, Y can be replaced with . for -1, and most importantly ;0zpᵐz{ċ₂ˢ}ᵐZh can be replaced with for a whopping -13: ḷṇ₁Xh.∧X⊇hᵐc


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

0

Ruby - 173

Could be better...

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

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

Output :

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

0

Java - 195

Unfortunately, Java does not have built in tuple support.

So, this is a class that stores the boolean in 'b' and the function word list in 'x'.

Here, the function is the constructor of the class.

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# has tuples but I came up with this while working on my solution: just return string[]: null simply means false, empty means true and n elements means true with n function words.
Num Lock

I would like to do that too. However OP specifies that the boolean must be provided regardless. See the reply to Jan Dvorak's comment.
Vectorized

I don't care about the comments as I can't seem to spot a resulted edit in the original post. And even if i did, it clearly just says to "specify the boolean". And even in the answer itself it says "Output result can be true/false, 0/1, yes/no...+" which I might just extend at the ellipsis by "*null/not null" ...
Num Lock

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}

Call it with, for instance: z "GNU is not Unix"

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

It splits the string into words and then loops through each word. If the first character of the word doesn't match the next in the acronym, the word is stored. A counter (g) is used to track how many words have been skipped. If the number of skipped words plus the length of the acronym matches the length of the phrase, it matched, so return 1 and the skipped words. If not, it was not valid, so return 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`
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.