Рекурсивні абревіатури


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 або як аргумент функції.
Результат виводу може бути істинним / хибним, 0/1, так / ні ...
Список функціональних слів (будь-який формат списку є дійсним) потрібно наводити лише тоді, якщо це рекурсивна абревіатура (навіть якщо список порожній) . Вам не потрібно зберігати великі літери функціональних слів.

Критерії виграшу

Це , найкоротший виграш коду.


4
Чи потрібно зберігати великі літери функціональних слів?
алгоритм

1
Чи прийнятно мати список рядків, що супроводжують значення False, чи ні?
підземниймонорельс

1
Оскільки сам список слів кодує булеве значення своєю присутністю, може ми опустити булеве значення?
Джон Дворак

5
Hurd розшифровується як Hird of Unix-Zamens Daemons. Hird означає Hurd інтерфейсів, що представляють глибину. Чому приклади тут не розуміють цього, і стверджують, що вони не є рекурсивними абревіатурами?
Конрад Боровський

3
@xfix, wikipedia зазначає, що це взаємно рекурсивні абревіатури.
Майкл М.

Відповіді:


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

Regex, аромат .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 Якщо ОП вирішить дискваліфікувати мою відповідь на основі цього, так і нехай буде. Але я думаю, я міг би зазначити, що це повна програма на мові, яка є смаком регулярного вираження .NET (не повною мовою Тюрінга, а мовою, яка трохи громіздка, але мова все ж таки). У будь-якому випадку мені подобається те, що я вирішив це з чисто-регулярним підходом, і я вважаю за краще дискваліфікувати відповідь, ніж знищити цю "елегантність" (якщо ви хочете), зробивши її "просто C # -відповідачем за допомогою regex ".
Мартін Ендер

Зі мною це добре. Я просто хотів це вказати на випадок, якщо ви пропустили його.
Зубна щітка

1
Мені це подобається. Regexes може бути не повною мовою програмування Тьюрінга, але я думаю, що це має бути розраховано.
Пол Дрейпер

@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, а список порожній, якщо це рекурсивна абревіатура) та список if not a.

Дякуємо @ace, що допомагає мені виправити помилку / зберегти кілька байт.


На Python 2.7.3 я потрапляю SyntaxError: invalid syntaxв кінці returnрядка.
користувач12205

@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)що він коротший, ніж ваш оригінал.
користувач12205

Так, і якщо ви використовуєте крапки з комою, щоб помістити перші два твердження в один рядок, ви збережете один байт відступу.
користувач12205

1
Я придумав спосіб виправити помилку, але коли я повернувся сюди, щоб опублікувати її, ти переграв її більше в коментарях: P
undergroundmonorail

3

Пітон - 154 символи

Перша в історії спроба гольфу. Я думаю, що python - це не найкраща мова для цього, враховуючи всі довгі ключові слова. Крім того, я не вважаю, що ця функція є надійною. Це працює на внесок ОП, але я впевнений, що міг би придумати винятки.

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, btw. :)
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 байт

Не найкоротший запис (ага, це Хаскелл, що ти очікував?), Але все-таки дуже весело писати.

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

Ребол - 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

Брахілог , 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))]}

Виклик функції:

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 # є кортежі, але я придумав це під час роботи над своїм рішенням: просто поверніться string[]: nullпросто означає помилковий, порожній означає істинний, а nелементи означає істинне з nфункціональними словами.
Num Lock

Я також хотів би це зробити. Однак ОП вказує, що булева інформація повинна надаватися незалежно. Дивіться відповідь на коментар Яна Дворака.
Векторизований

Мене не хвилюють коментарі, оскільки я не можу помітити результативну редакцію в оригінальній публікації. І навіть якщо я це зробив , він чітко говорить про " уточнення булевого ". І навіть у самій відповіді написано: " Результат виходу може бути істинним / хибним, 0/1, так / ні ... +", який я міг би просто розширити в еліпсі на "* 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

Кофескрипт - 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`
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.