Akronim rekursif


31

Objektif

Dari Wikipedia :

Akronim rekursif adalah akronim yang merujuk pada dirinya sendiri dalam ekspresi yang digunakannya.

Tujuan Anda adalah untuk memeriksa apakah string adalah akronim rekursif.

  • Akronim adalah kata pertama
  • Kata-kata tidak peka huruf besar kecil, dipisahkan dengan satu spasi tunggal.
  • String yang diberikan tidak mengandung tanda baca atau apostrof.
  • Hanya huruf pertama dari setiap kata yang dapat menjadi bagian dari akronim.

Anda juga harus memberikan kata-kata fungsi . Untuk kesederhanaan, setiap kata dapat dianggap sebagai kata fungsi.

Contoh

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

Anda dapat memberikan program atau fungsi lengkap.
String input dapat diambil dari STDIN atau sebagai argumen fungsi.
Hasil keluaran bisa benar / salah, 0/1, ya / tidak ...
Daftar kata-kata fungsi (format daftar apa pun valid) harus diberikan jika dan hanya jika ini adalah akronim rekursif (bahkan jika daftar itu kosong) . Anda tidak harus mempertahankan penggunaan huruf besar untuk kata fungsi.

Kriteria menang

Ini adalah , kode terpendek menang.


4
Apakah kita harus mempertahankan penggunaan huruf besar dari kata fungsi?
algoritme

1
Apakah dapat diterima untuk memiliki daftar string yang menyertai nilai False, atau tidak?
undergroundmonorail

1
Karena daftar kata itu sendiri mengkodekan nilai boolean dengan kehadirannya, dapatkah kita menghilangkan boolean?
John Dvorak

5
Hurd adalah singkatan dari Hird of Unix-Replacing Daemon. Hird adalah singkatan dari Hurd of Interfaces Representing Depth. Mengapa contoh di sini tidak memahami hal itu, dan mengklaim bahwa itu bukan singkatan rekursif?
Konrad Borowski

3
@xfix, wikipedia menyatakan bahwa itu adalah akronim yang saling rekursif .
Michael M.

Jawaban:


7

GolfScript, 51 50 karakter

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

Mungkin bisa bermain golf lebih lanjut. Mengambil input pada STDIN. Boolean adalah 0/1.

Tes online


Penjelasan:

{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, .NET flavor, 62 byte

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

Anda bisa mengujinya di sini . Jika input adalah akronim rekursif, ini akan menghasilkan kecocokan, dan menangkap grup wakan berisi semua kata fungsi. Jika tidak, maka tidak akan ada kecocokan.

Ini memang mempertahankan kapitalisasi kata fungsi (tetapi cocok dengan case-insensitive).

Sayangnya, tester tidak menampilkan seluruh tumpukan grup penangkap bernama, tetapi jika Anda menggunakannya di mana saja di .NET, wgrup akan berisi semua kata fungsi secara berurutan.

Berikut ini cuplikan C # untuk membuktikan bahwa:

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

Berikut ini penjelasan singkatnya. Saya menggunakan grup penyeimbang .NET untuk membuat tumpukan akronim dalam grup yang diberi nama c, dengan cuplikan ini

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

Triknya adalah saya membutuhkan huruf kedua di atas tumpukan dan yang terakhir di bagian bawah. Jadi saya menempatkan semua ini di belakang yang cocok dengan posisi setelah akronim. Ini membantu, karena .NET cocok terlihat di belakang dari kanan ke kiri, sehingga ia menemukan huruf terakhir terlebih dahulu.

Setelah saya mendapatkan tumpukan itu, saya mencocokkan sisa kata string demi kata. Entah kata itu dimulai dengan huruf di atas tumpukan akronim. Dalam hal ini saya mengeluarkan surat itu dari tumpukan:

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

Jika tidak, saya tetap mencocokkan kata dan mendorong ke wtumpukan yang kemudian akan berisi semua kata fungsi:

 (?<w>\w+)

Pada akhirnya saya memastikan saya mencapai akhir string dengan $dan juga memastikan bahwa saya telah menggunakan semua huruf dari akronim, dengan memeriksa bahwa tumpukan kosong:

(?(c)(?!))

Uji di ideone.


1
Ekspresi reguler yang bagus, tetapi pertanyaannya dengan jelas menyatakan "Anda dapat memberikan program lengkap atau fungsi ".
Sikat gigi

4
@ sikat gigi Jika OP memutuskan untuk mendiskualifikasi jawaban saya berdasarkan itu, biarlah. Tapi saya pikir saya bisa membuat titik bahwa ini adalah program lengkap dalam bahasa yang merupakan rasa ekspresi reguler .NET (bukan bahasa lengkap Turing, dan yang agak rumit untuk dijalankan, tetapi bahasa tetap). Bagaimanapun, saya menyukai kenyataan bahwa saya menyelesaikannya dengan pendekatan regex murni, dan saya lebih suka jawabannya didiskualifikasi daripada menghancurkan "keanggunan" itu (jika Anda mau) dengan membuatnya "hanya C # - jawab menggunakan regex ".
Martin Ender

Tidak masalah dengan saya. Saya hanya ingin menunjukkannya jika Anda melewatkannya.
Sikat gigi

1
Saya suka itu. Regex mungkin bukan bahasa pemrograman Turing-lengkap, tapi saya pikir ini harus diperhitungkan.
Paul Draper

@PaulDraper Bahkan, saya bahkan tidak akan bertaruh pada. Regex rasa NET tidak lengkap Turing ... kelompok penyeimbang dan tampilan dari kanan ke kiri cocok cukup kuat. Dan PCRE misalnya dikenal sebagai Turing lengkap (yang satu memiliki rekursi, saya tidak yakin tumpukan di. NET cukup untuk meniru iterasi sewenang-wenang).
Martin Ender

11

Python (158, tanpa regex)

Bukannya saya tidak suka regex. Itu karena saya tidak mengenal mereka.

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, saya juga punya versi tanpa ungolfed:

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 byte

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)

Membuat daftar huruf dalam kata pertama dari akronim. Kemudian, untuk setiap kata dalam string penuh, singkirkan elemen pertama dari daftar yang kami buat jika sama dengan huruf pertama dari kata itu. Kalau tidak, tambahkan kata itu ke daftar kata fungsi. Untuk menghasilkan, kembali not a(Dalam python, daftar apa pun selain daftar kosong adalah True-y, dan daftar kosong jika itu adalah singkatan rekursif) dan daftar jika not a.

Terima kasih kepada @ace untuk membantu saya memperbaiki kesalahan / menyimpan beberapa byte.


Pada Python 2.7.3, saya mendapatkan SyntaxError: invalid syntaxdi akhir returnbaris.
user12205

@ace Huh, saya berani bersumpah itu berhasil ketika saya mengujinya. Saya pasti telah mengubah sesuatu dan lupa untuk menguji lagi. Saya akan memperbaiki!
undergroundmonorail

Anda dapat menggunakan for w in s:f+=0*a.pop(0)if a and w[0]==a[0]else[w]mana yang lebih pendek dan tidak bergantung pada tab. Adapun returnpernyataan itu, saya menemukan 0if a else(1,f)yang lebih pendek dari aslinya.
user12205

Oh dan jika Anda menggunakan titik koma untuk meletakkan dua pernyataan pertama di baris yang sama Anda menyimpan satu lekukan indentasi.
user12205

1
Saya menemukan cara untuk memperbaiki kesalahan, tetapi ketika saya kembali ke sini untuk mempostingnya, Anda telah mencatatnya lebih dalam komentar: P
undergroundmonorail

3

Python - 154 karakter

Usaha kode golf pertama kali. Saya pikir python bukan bahasa terbaik untuk itu, mengingat semua kata kunci panjang. Juga, saya tidak berpikir fungsi ini sangat mudah. Ini berfungsi untuk input OP, tapi saya yakin saya bisa memikirkan pengecualian.

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

Saya menghitung 156 karakter (baris baru dan karakter tab sama-sama diperhitungkan), tetapi Anda dapat menurunkannya ke 154 secara sah dengan menghapus kedua karakter tersebut karena tidak ada yang benar-benar diperlukan. Selamat datang di PPCG, btw. :)
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)

Masukkan fungsi di konsol browser Firefox, lalu panggil fungsi tersebut, seperti ini:

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

Tidak cukup mematuhi aturan: The function words list ... must be given if and only if this is a recursive acronym. Ini akan mengingatkan mereka bagaimanapun.
MT0

@ MT0 OKE Saya tidak memperhatikan persyaratan itu. Saya akan melihat apakah saya bisa menulis ulang.
Sikat gigi

@ MT0 Saya sudah memperbarui kodenya sekarang.
Sikat gigi

2

Haskell - 287 byte

Bukan entri terpendek (hei ini Haskell, apa yang Anda harapkan?), Tapi masih banyak yang menyenangkan untuk ditulis.

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

Diuji dengan

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

Output yang diharapkan

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

Tidak disatukan

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 Karakter

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)

Tes:

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

Tidak Disatukan:

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

Diuji dengan:

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]

Keluaran:

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

1

Julia - 116 byte

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)

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

Pada 0akhirnya membuatnya menjadi 0. Jika tidak, itu menghasilkan array yang berisi 1diikuti oleh kata-kata fungsi. Sebagai contoh:

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 byte

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

Cobalah online!

Output kata-kata fungsi melalui variabel output jika input adalah singkatan rekursif, dan gagal jika tidak.

   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.

Tanpa harus menampilkan kata-kata fungsi (memperlakukan ini sebagai masalah murni ), hasilnya hanya 12 byte, karena ∧Ztdapat dijatuhkan untuk -3, Ydapat diganti dengan .untuk -1, dan yang paling penting ;0zpᵐz{ċ₂ˢ}ᵐZhdapat diganti dengan untuk a kekalahan -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

Dapat menjadi lebih baik...

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

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

Keluaran:

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

0

Jawa - 195

Sayangnya, Java tidak memiliki dukungan tuple bawaan.

Jadi, ini adalah kelas yang menyimpan boolean di 'b' dan daftar kata fungsi di 'x'.

Di sini, fungsinya adalah konstruktor kelas.

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

Uji

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 # memiliki tupel tetapi saya datang dengan ini saat mengerjakan solusi saya: hanya kembali string[]: nullberarti salah, kosong berarti benar dan nelemen berarti benar dengan nkata-kata fungsi.
Num Lock

Saya juga ingin melakukannya. Namun OP menetapkan bahwa boolean harus disediakan apa pun. Lihat balasan untuk komentar Jan Dvorak.
Vektor

Saya tidak peduli dengan komentar tersebut karena sepertinya saya tidak dapat menemukan hasil edit pada posting asli. Dan bahkan jika saya melakukannya , itu jelas hanya mengatakan untuk " tentukan boolean ". Dan bahkan dalam jawaban itu sendiri tertulis " Hasil keluaran bisa benar / salah, 0/1, ya / tidak ... +" yang mungkin saya memperpanjang di ellipsis dengan "* null / not null " ...
Num Kunci

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

Uji:

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

Sebut saja dengan, misalnya: z "GNU is not Unix"

JS yang dikompilasi:

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

Ini membagi string menjadi kata-kata dan kemudian loop melalui setiap kata. Jika karakter pertama kata tidak cocok dengan yang berikutnya dalam akronim, kata tersebut disimpan. Penghitung ( g) digunakan untuk melacak berapa banyak kata yang dilewati. Jika jumlah kata yang dilewati ditambah panjang akronim cocok dengan panjang frasa, itu cocok, jadi kembalikan 1 dan kata-kata yang dilewati. Jika tidak, itu tidak valid, jadi kembalikan 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`
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.