Побудуйте індекс читабельності


13

Флеш-Кинкейд читаність алгоритм залежить від заходів кількості слів і складів підрахунку, ні один з яких є повністю об'єктивним, або легко автоматизований з допомогою комп'ютера. Наприклад, чи «Код-гольф» з дефісом вважається одним чи двома словами? Це слово "мільйон" два чи три склади? У цьому завданні вам потрібно буде наблизитись, оскільки підрахунок точно займе занадто багато часу, місця та, головне, коду.

Ваше завдання полягає в тому, щоб скласти найменшу можливу програму (тобто функцію) на будь-якій мові, яка буде приймати англійський уривок читання (припускається, що це в повному реченні), і обчислити індекс легкості читання Flesch до допуску до восьми балів (для врахування варіації підрахунку складів і підрахунку слів). Він розраховується так:

FRE = 206.835 - 1.015 * (words per sentence) - 84.6 * (syllables per word)

Ваша програма повинна бути узгоджена з еталонними уривками нижче, індекси яких були обчислені за допомогою ручного підрахунку:

I would not, could not, in the rain.
Not in the dark, not on a train.
Not in a car, not in a tree.
I do not like them, Sam, you see.
Not in a house, not in a box.
Not with a mouse, not with a fox.
I will not eat them here or there.
I do not like them anywhere!

Індекс: 111,38 (64 склади з 62 слів у 8 реченнях)

It was a bright cold day in April, and the clocks were striking thirteen.
Winston Smith, his chin nuzzled into his breast in an effort to escape
the vile wind, slipped quickly through the glass doors of Victory Mansions,
though not quickly enough to prevent a swirl of gritty dust from entering
along with him.

Індекс: 65,09 (74 склади з 55 слів у 2 реченнях)

When in the Course of human events, it becomes necessary for one people to
dissolve the political bands which have connected them with another, and to
assume among the powers of the earth, the separate and equal station to
which the Laws of Nature and of Nature's God entitle them, a decent respect
to the opinions of mankind requires that they should declare the causes
which impel them to the separation.

Індекс: 3,70 (110 складів з 71 словом в 1 реченні)

Якщо у вас є інші уривки, для яких ви вручну порахували склади та слова та обчислили індекс, ви можете показати їх як перевірку.


Чи може це бути функцією? Або потрібно приймати STDIN?
Бриганд

2
Чи є в наявності кількість складів для 3-х прикладних уривків чи просто індекс? Якщо у вас є, кількість складів буде корисною для порівняння.
Strigoides

Це може бути функцією. Насправді це має бути функцією.
Джо З.

Відповіді:


6

Perl 120 байт

#!perl -pa0
s@\w+|([.!?])@$s+=$#-,lc($&)=~s![aeiou]+\B|([aeiouy]$)!$y+=1-$#-/3!ger@ge}
{$_=206.835-1.015*@F/$s-84.6*$y/@F

Зразок вводу / виводу:

$ perl flesch-kincaid.pl < input1.dat
110.730040322581

$ perl flesch-kincaid.pl < input2.dat
65.6097727272728

$ perl flesch-kincaid.pl < input2.dat
1.71366197183096

Підрахунок складів здійснюється, якщо припустити, що кожен голосний скупчення є одним складом, за винятком одиноких голосних в кінці слова, які рахуються лише дві третини часу; евристика, яка здається досить точною.


3

K&R c - 188 196 199 229 символів

При зміні специфікації, щоб вказати функцію, я можу отримати велику кількість накладних витрат з рахунку. Також змінюється, щоб використовувати зловмисний лічильник складних ліній Strigoides, який кращий, ніж налаштування моєї формули, і розширений для боротьби з перерахунком слів.

Після того, як я знайшов більш короткий спосіб виявлення голосних, на якому грунтувався stdchr, я змусив витіснити ще кілька моторошних мерзот, якими я користувався, щоб мені не було нудно.

d,a,v,s,t,w;float R(char*c){for(;*c;++c){s+=*c=='.';if(isalpha(*c)){
w+=!a++;d=(*c&30)>>1;if(*c&1&(d==7|((!(d&1))&(d<6|d>8)))){t+=!v++;}
else v=0;}else v=a=0;}return 206.835-1.*w/s-82.*t/w;}

Логіка тут - це проста державна машина. Він зараховує речення лише за періодами, слова за рядками алфавітних символів та склади як рядки голосних (включаючи y).

Мені довелося трохи відхилити константи, щоб вийти з правильними цифрами, але я запозичив фокус Стригойда - лише заниження складів фіксованою часткою.

Без гольфу , з коментарями та інструментами налагодження:

#include <stdlib.h>
#include <stdio.h>
d,a,/*last character was alphabetic */
  v,/*lastcharacter was a vowel */
  s, /* sentences counted by periods */
  t, /* syllables counted by non-consequtive vowels */
  w; /* words counted by non-letters after letters */
float R/*eadability*/(char*c){
  for(;*c;++c){
    s+=*c=='.';
    if(isalpha(*c)){ /* a letter might mark the start of a word or a
               vowel string */
      w+=!a++; /* It is only the start of a word if the last character
              wasn't a letter */
      /* Extract the four bits of the character that matter in determining
       * vowelness because a vowel might mark a syllable */
      d=(*c&30)>>1;
      if( *c&1  & ( d==7 | ( (!(d&1)) & (d<6|d>8) ) ) 
      ) { /* These bits 7 or even and not 6, 8 make for a
         vowel */
    printf("Vowel: '%c' (mangled as %d [0x%x]) counts:%d\n",*c,d,d,!v);
    t+=!v++;
      } else v=0; /* Not a vowel so set the vowel flag to zero */
    }else v=a=0; /* this input not alphabetic, so set both the
            alphabet and vowel flags to zero... */
  }
  printf("Syllables: %3i\n",t);
  printf("Words:     %3i       (t/w) = %f\n",w,(1.0*t/w));
  printf("Sentences: %3i       (w/s) = %f\n",s,(1.0*w/s));
  /* Constants tweaked here due to bad counting behavior ...
   * were:       1.015     84.6 */
  return 206.835-1.   *w/s-82. *t/w;
}
main(c){
  int i=0,n=100;
  char*buf=malloc(n);
  /* Suck in the whole input at once, using a dynamic array for staorage */
  while((c=getc(stdin))!=-1){
    if(i==n-1){ /* Leave room for the termination */
      n*=1.4;
      buf=realloc(buf,n);
      printf("Reallocated to %d\n",n);
    }
    buf[i++]=c;
    printf("%c %c\n",c,buf[i-1]);
  }
  /* Be sure the string is terminated */
  buf[i]=0;
  printf("'%s'\n",buf);
  printf("%f\n",R/*eadability*/(buf));
}

Вихід: (використовуючи ешафот з довгої версії, але функцію для гольфу.)

$ gcc readability_golf.c
readability_golf.c:1: warning: data definition has no type or storage class
$ ./a.out < readability1.txt 
'I would not, could not, in the rain.
Not in the dark, not on a train.
Not in a car, not in a tree.
I do not like them, Sam, you see.
Not in a house, not in a box.
Not with a mouse, not with a fox.
I will not eat them here or there.
I do not like them anywhere!
'
104.074631    
$ ./a.out < readability2.txt
'It was a bright cold day in April, and the clocks were striking thirteen.
Winston Smith, his chin nuzzled into his breast in an effort to escape
the vile wind, slipped quickly through the glass doors of Victory Mansions,
though not quickly enough to prevent a swirl of gritty dust from entering
along with him.
'
63.044090
$ ./a.out < readability3.txt 
'When in the Course of human events, it becomes necessary for one people to
dissolve the political bands which have connected them with another, and to
assume among the powers of the earth, the separate and equal station to
which the Laws of Nature and of Nature's God entitle them, a decent respect
to the opinions of mankind requires that they should declare the causes
which impel them to the separation.
'
-1.831667

Дефіцити:

  • Логіка підрахунку речень помилкова, але я відходжу від неї, тому що лише на одному з входів є " !a" ?.
  • Логіка підрахунку слів трактуватиме скорочення як два слова.
  • Логіка підрахунку складів буде розглядати ті самі скорочення, як і один склад. Але, ймовірно, в середньому перевитрати (наприклад there, рахуються як два, і багато слів, що закінчуються, eбуде зараховано один занадто багато), тому я застосував постійний коефіцієнт корекції 96,9%.
  • Передбачає набір символів ASCII.
  • Я вважаю, що визнання голосних визнається [і {, що явно не правильно.
  • Багато опори на семантику K&R робить це потворним, але ей, це кодовий гольф.

Що слід подивитися:

  • Я (на мить) випереджую обидва рішення пітона тут, навіть якщо я переслідую перл.

  • Завантажте жахливе, що я зробив для виявлення голосних. Це має певний сенс, якщо виписуєте представлення ASCII у двійковій формі та читаєте коментар у довгій версії.


"Мені довелося трохи змінити формулу вручну, щоб отримати прийнятні результати". Це може бути погана форма.
Джо З.

1
Я зараз щонайменше дотримувався слів Strigoides і вносив корективи, виходячи з того, хто в розумінні тексту робить помилки, а не суто спеціальним підключенням, щоб зв'язати три тестові випадки на узгодження.
dmckee --- кошеня колишнього модератора

2

Пітон, 202 194 188 184 171 167 символів

import re
def R(i):r=re.split;w=len(r(r'[ \n]',i));s=r('\\.',i);y=r('[^aeiou](?i)+',i);return 206.835-1.015*w/(len(s)-s.count('\n'))-84.6*(len(y)-y.count(' ')-2)*.98/w

Спочатку отримайте загальну кількість слів, розділивши пробіли та нові рядки:

w=len(r(r'[ \n]',i))

Потім формула. Підрахунок речень і складів використовуються лише один раз, тому вони вбудовані в цей вираз.

Речення - це просто розділений вхід ., а нові рядки відфільтровані:

s=r('\\.',i);s=len(s)-s.count('\n')

Склади складаються з вхідного поділу вздовж неголосних, з пробілами. Здається, це послідовно дещо переоцінює кількість складів, тому нам потрібно відкоригувати її (приблизно, так, як це робиться приблизно .98):

y=r('[^aeiou](?i)+',i);y=len(y)-y.count(' ')-2;

202 -> 194: len(x)-2 а не len(x[1:-1]). Вилучені непотрібні дужки. Зроблено складний регулярний вираз, нечутливий до регістру

194 -> 188: Файл раніше був збережений як dos, а не як формат файлу Unix, внаслідок чого wc -cнові рядки вважаються двома символами. Уопс.

188 -> 184: Позбавтеся від тих неприємних x for x in ... if x!=...моментів, зберігаючи проміжний результат і віднімаючиx.count(...)

184 -> 171: Видаліть введення / виведення та перетворите на функцію

171 -> 167: Вставте len(x)-x.count(...)s у формулу


Ваша відповідь не повинна включати процедури введення та виводу.
Джо З.

@JoeZeng О, добре. Я тоді перетворять його у функцію.
Strigoides

1

Пітон 380 символів

import re
def t(p):
 q=lambda e: e!=''
 w=filter(q,re.split('[ ,\n\t]',p))
 s=filter(q,re.split('[.?!]',p))
 c=len(w)*1.0
 f=c/len(s)
 return w,f,c
def s(w):
 c= len(re.findall(r'([aeiouyAEIOUY]+)',w))
 v='aeiouAEIOU'
 if len(w)>2 and w[-1]=='e'and w[-2]not in v and w[-3]in v:c-= 1
 return c
def f(p):
 w,f,c=t(p)
 i=0
 for o in w:
  i+=s(o)
 x=i/c
 return 206.835-1.015*f-84.6*x

Це досить довге рішення, але воно працює досить добре, принаймні з 3-х тестових випадків за умови, що це робиться.

Код тестування

def test():
 test_cases=[['I would not, could not, in the rain.\
        Not in the dark, not on a train.\
        Not in a car, not in a tree.\
        I do not like them, Sam, you see.\
        Not in a house, not in a box.\
        Not with a mouse, not with a fox.\
        I will not eat them here or there.\
        I do not like them anywhere!', 111.38, 103.38, 119.38],\
        ['It was a bright cold day in April, and the clocks were striking thirteen.\
        Winston Smith, his chin nuzzled into his breast in an effort to escape\
        the vile wind, slipped quickly through the glass doors of Victory Mansions,\
        though not quickly enough to prevent a swirl of gritty dust from entering\
        along with him.', 65.09, 57.09, 73.09],\
        ["When in the Course of human events, it becomes necessary for one people to\
        dissolve the political bands which have connected them with another, and to\
        assume among the powers of the earth, the separate and equal station to\
        which the Laws of Nature and of Nature's God entitle them, a decent respect\
        to the opinions of mankind requires that they should declare the causes\
        which impel them to the separation.", 3.70, -4.70, 11.70]]
 for case in test_cases:
  fre= f(case[0])
  print fre, case[1], (fre>=case[2] and fre<=case[3])

if __name__=='__main__':
 test()

Результат -

elssar@elssar-laptop:~/code$ python ./golf/readibility.py
108.910685484 111.38 True
63.5588636364 65.09 True
-1.06661971831 3.7 True

Я використовував лічильник складів звідси - Підрахунок складів

Більш читана версія доступна тут


1
if len(w)>2 and w[-1]=='e'and w[-2]not in v and w[-3]in v:c-= 1Простодушний, але хороший наближення. Мені це подобається.
dmckee --- кошеня колишнього модератора

0

Javascript, 191 байт

t=prompt(q=[]);s=((t[m="match"](/[!?.]+/g)||q)[l="length"]||1);y=(t[m](/[aeiouy]+/g)||q)[l]-(t[m](/[^aeiou][aeiou][s\s,'.?!]/g)||q)[l]*.33;w=(t.split(/\s+/g))[l];alert(204-1.015*w/s-84.5*y/w)

Перший тестовий випадок дає 112,9 (правильна відповідь - 111,4, вимкнено на 1,5 бала)

Другий тестовий випадок дає 67,4 (правильна відповідь - 65,1, відключена на 2,3 бала)

Третій тестовий випадок дає 1,7 (правильна відповідь 3,7, вимкнено на 2,0 бала)

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