Создать индекс читабельности


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 примеров, или только для индекса? Если у вас есть, счет слогов будет удобно для сравнения.
Стригоидес

Это может быть функция. На самом деле это должна быть функция.
Джо З.

Ответы:


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 знаков

С измененной спецификацией, чтобы указать функцию, я могу получить большую часть накладных расходов c из подсчета. Также я перешел на использование метода подсчета слогов 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 !или a ?.
  • Логика подсчета слов будет рассматривать сокращения как два слова.
  • Логика подсчета слогов будет рассматривать те же сокращения как один слог. Но, вероятно, превышение в среднем (например there, считается как два, а многие слова, оканчивающиеся на, eбудут считаться слишком много), поэтому я применил постоянный коэффициент коррекции 96,9%.
  • Предполагает набор символов ASCII.
  • Я верю, что обнаружение гласного признается [и {, что явно не правильно.
  • Большая зависимость от семантики K & R делает это уродливым, но эй, это кодовый гольф.

На что посмотреть:

  • Я (на мгновение) опередил оба решения Python здесь, даже если я тяну за Perl.

  • Получите груз ужасной вещи, которую я сделал для обнаружения гласных. Имеет смысл, если вы записываете представления ASCII в двоичном виде и читаете комментарий в длинной версии.


«Мне пришлось немного изменить формулу вручную, чтобы получить приемлемые результаты». Это может быть плохой формой.
Джо З.

1
Теперь я по меньшей мере последовал примеру Стригоида и внес коррективы, основываясь на том, кто допускает ошибки в текстовом понимании, а не на специальной подстройке, чтобы согласовать три тестовых примера.
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')

Слоги состоят из входных данных, разделенных по гласным, с удаленными пробелами. Похоже, что это постоянно немного переоценивает количество слогов, поэтому мы должны уменьшить его (примерно 0,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 О, хорошо. Я превращу это в функцию тогда.
Стригоидес

1

Python 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

Это довольно длинное решение, но оно работает достаточно хорошо, по крайней мере, из трех тестовых случаев, если это так.

Тестовый код

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.