Okunabilirlik dizini oluşturma


13

Flesch-Kincaid okunabilirliği algoritması tamamen objektif veya bir bilgisayar kullanarak kolayca automatable ikisi de kelime sayısı ve hece sayısı, ölçümleri bağlıdır. Örneğin, kısa çizgi ile "kod golf" bir veya iki kelime olarak sayılır mı? "Milyon" kelimesi iki veya üç hece midir? Tam olarak saymak çok fazla zaman, alan ve en önemlisi kod gerektireceğinden, bu görevde yaklaşık olarak yapmanız gerekir.

Göreviniz, İngilizce okuma pasajı (tam cümlelerde olduğu varsayılır) alacak herhangi bir dilde mümkün olan en küçük programı (yani bir işlevi) oluşturmak ve Flesch Reading Ease endeksini sekiz noktaya (hesaba katmak için) hesaplamaktır. hece sayımı ve kelime sayımındaki değişimler). Aşağıdaki gibi hesaplanır:

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

Programınız, endeksleri manuel sayım kullanılarak hesaplanan aşağıdaki referans pasajlarla hizalanmalıdır:

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!

Dizin: 111.38 (8 cümlede 62 kelimede 64 hece)

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.

Dizin: 65.09 (2 cümlede 55 kelimede 74 hece)

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.

Dizin: 3.70 (1 cümlede 71 kelimede 110 hece)

Heceleri ve kelimeleri manuel olarak saydığınız ve dizini hesapladığınız başka pasajlarınız varsa, bunları doğrulama olarak gösterebilirsiniz.


Bir işlev olabilir mi? Yoksa STDIN alması mı gerekiyor?
Brigand

2
3 örnek pasaj için hece sayımınız var mı, yoksa yalnızca dizin mi var? Elinizde varsa, hece sayısı karşılaştırma için kullanışlı olacaktır.
Ocak'ta Strigoides

Bir işlev olabilir. Aslında, bu bir işlev olmalıdır.
Joe Z.

Yanıtlar:


6

Perl 120 bayt

#!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

Örnek G / Ç:

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

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

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

Hecelerin sayımı, bir sözcüğün sonundaki yalnız sesli harfler dışında, zamanın sadece üçte ikisi sayılan her sesli harf kümesinin tek bir hece olduğu varsayılarak yapılır; oldukça doğru görünen bir buluşsal yöntem.


3

K ve R ° - 188 196 199 229 karakter

Spec bir işlevi belirtmek için değiştiğinde ben c ek yükü çok sayıdan alabilirsiniz. Ayrıca Strigoides'in heceli sayma kesmek için değişiyor.

Ne yazık ki temelli sesli harf algılamasını yapmanın daha kısa bir yolunu bulduktan sonra stdchr, sıkıcı olmamam için kullandığım bit-twomling iğnelemesinden birkaç tane daha sıkmak için teşvik ettim.

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

Buradaki mantık basit bir durum makinesidir. Cümleleri yalnızca noktalara, alfabetik karakterlerden oluşan dizelere ve heceleri ünlüler (y dahil) dizeleri olarak sayar.

Doğru rakamlarla ortaya çıkması için sabitleri biraz kandırmak zorunda kaldım, ama Strigoides'in heceleri sabit bir kesirle az sayma hünerini aldım.

Golfsüz , yorumlar ve bazı hata ayıklama araçlarıyla:

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

Çıktı: (uzun versiyondaki iskele kullanarak, ancak golf fonksiyonu.)

$ 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

eksiklikler:

  • Cümle sayma mantığı yanlış, ama ben ondan kaçıyorum çünkü girişlerden sadece birinde a !veya a var ?.
  • Kelime sayma mantığı kasılmaları iki kelime olarak ele alacaktır.
  • Hece sayma mantığı, aynı kasılmaları bir hece ile ele alacaktır. Ancak muhtemelen ortalama thereolarak fazla sayılır (örneğin , iki ile sayılır ve biten birçok kelime eçok fazla sayılır), bu yüzden% 96,9'luk sabit bir faktör uyguladım.
  • ASCII karakter kümesini varsayar.
  • Sesli harf algılamanın kabul edeceğine inanıyorum [ve {bu kesinlikle doğru değil.
  • K & R anlambilimine çok güvenmek bu çirkinleşiyor, ama hey, bu kod golf.

Bakılması gerekenler:

  • Perl'i takip ediyor olsam bile, burada her iki python çözümünün (anlık) önündeyim.

  • Sesli harfleri tespit etmek için yaptığım korkunç bir şey alın. ASCII gösterimlerini ikili olarak yazar ve uzun versiyondaki yorumu okursanız bir anlam ifade eder.


"Kabul edilebilir sonuçlar elde etmek için formülü biraz değiştirmek zorunda kaldım." Bu kötü bir form olabilir .
Joe Z.

1
Metin anlama hataları ziyade tamamen daha yapar kim şimdi bir az izlenen Strigoides' kurşun ve yapılan temelinde ayarlamalar var ad hoc çimdik anlaşma üç test durumları çalacak.
dmckee --- eski moderatör yavru kedi

2

Python, 202 194 188 184 171 167 karakter

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

İlk olarak, boşluklar ve yeni satırlar boyunca bölünerek toplam kelime sayısını elde edin:

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

Sonra formül. Cümle ve hece sayımları yalnızca bir kez kullanılır, bu nedenle bu ifadeye gömülürler.

Cümleler basitçe bir araya getirilmiş girişlerdir .ve yeni satırlar filtrelenir:

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

Heceler, boşluklar kaldırılmış, sesli harfler olmayan girişlerden oluşur. Bu, hecelerin sayısını sürekli olarak biraz fazla tahmin ediyor gibi görünüyor, bu yüzden onu ayarlamamız gerekiyor (yaklaşık .98 bunu yapıyor gibi görünüyor):

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

202 -> 194: len(x)-2 yerine len(x[1:-1]). Gereksiz parantez kaldırıldı. Hece normal ifade büyüklüğüne duyarsız hale getirildi

194 -> 188: Dosya daha önce unix dosya formatı yerine dos olarak kaydedilmiş ve wc -csatırsonlarını iki karakter olarak saymıştı. Whoops.

188 -> 184:x for x in ... if x!=... Ara sonucu saklayıp çıkararak bu kötü durumlardan kurtulunx.count(...)

184 -> 171: Giriş / çıkışı kaldırın ve işleve dönüştürün

171 -> 167:len(x)-x.count(...) Formüle s ekle


Cevabınızın giriş ve çıkış prosedürlerini içermesi gerekmez.
Joe Z.

@JoeZeng Oh, tamam. O zaman onu bir fonksiyona dönüştüreceğim.
Strigoides

1

Python 380 karakter

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

Bu oldukça uzun bir çözümdür, ancak en azından 3 test vakasından yeterince iyi çalışır.

Test kodu

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

Sonuç -

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

Hece sayacını buradan kullandım - Heceleri saymak

Bir daha okunabilir sürümü mevcut burada


1
if len(w)>2 and w[-1]=='e'and w[-2]not in v and w[-3]in v:c-= 1Basit fikirli ama iyi bir yaklaşım. Bunu sevdim.
dmckee --- eski moderatör yavru kedi

0

Javascript, 191 bayt

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)

İlk test durumu 112.9 verir (doğru cevap 111.4, 1.5 puan kapalıdır)

İkinci test durumu 67.4 verir (doğru cevap 65.1, 2.3 puan kapalı)

Üçüncü test vakası 1.7 verir (doğru cevap 3.7, 2.0 puan kapalı)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.