Buat indeks keterbacaan

13

The Flesch-Kincaid pembacaan algoritma tergantung pada kebijakan dari jumlah kata dan jumlah suku kata, baik yang sepenuhnya objektif, atau dengan mudah automatable menggunakan komputer. Misalnya, apakah "kode-golf", dengan tanda hubung, dihitung sebagai satu atau dua kata? Apakah kata "juta" dua atau tiga suku kata? Dalam tugas ini, Anda perlu memperkirakan, karena penghitungan yang tepat akan memakan terlalu banyak waktu, ruang, dan yang paling penting, kode.

Tugas Anda adalah untuk membangun program sekecil mungkin (yaitu fungsi) dalam bahasa apa pun yang akan menggunakan bacaan berbahasa Inggris (diasumsikan dalam kalimat lengkap), dan menghitung indeks Kemudahan Membaca Flesch hingga toleransi delapan poin (untuk memperhitungkan variasi dalam penghitungan suku kata dan penghitungan kata). Itu dihitung sebagai berikut:

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

Program Anda harus disejajarkan dengan bagian referensi di bawah ini, yang indeksnya dihitung menggunakan penghitungan manual:

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!

Indeks: 111,38 (64 suku kata dalam 62 kata dalam 8 kalimat)

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.

Indeks: 65,09 (74 suku kata dalam 55 kata dalam 2 kalimat)

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.

Indeks: 3,70 (110 suku kata dalam 71 kata dalam 1 kalimat)

Jika Anda memiliki bagian-bagian lain yang secara manual Anda hitung suku kata dan kata-katanya dan menghitung indeksnya, Anda dapat memperlihatkannya sebagai verifikasi.

Joe Z.
sumber
Bisakah itu menjadi fungsi? Atau harus mengambil STDIN?
Brigand
2
Apakah Anda memiliki jumlah suku kata yang tersedia untuk 3 bagian contoh, atau hanya indeks? Jika Anda memilikinya, jumlah suku kata akan berguna untuk perbandingan.
Strigoides
Ini bisa menjadi fungsi. Bahkan, itu harus menjadi fungsi.
Joe Z.

Jawaban:

6

Perl 120 byte

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

Sampel I / O:

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

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

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

Penghitungan suku kata dilakukan dengan mengasumsikan bahwa setiap kluster vokal adalah suku kata tunggal, kecuali untuk vokal tunggal di akhir kata, yang hanya dihitung dua pertiga waktu; heuristik yang tampaknya cukup akurat.

primo
sumber
3

K&R c - 188 196 199 229 229 karakter

Dengan spek berubah untuk menentukan fungsi saya bisa mendapatkan banyak c overhead di luar hitungan. Juga berubah untuk menggunakan hack penghitungan suku kata Strigoides yang lebih baik daripada tweak formula saya dan diperluas untuk menangani penghitungan kata yang terlalu banyak.

Setelah saya menemukan cara yang lebih singkat untuk melakukan pendeteksian vokal yang sayangnya berdasarkan stdchr, saya memiliki insentif untuk memeras beberapa lagi dari kekejian yang sedikit-banyak yang telah saya gunakan sehingga saya tidak harus bosan.

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

Logikanya di sini adalah mesin keadaan sederhana. Ini menghitung kalimat dengan periode saja, kata-kata dengan string karakter alfabet, dan suku kata sebagai string vokal (termasuk y).

Saya harus sedikit menipu konstanta untuk mengeluarkannya dengan angka yang tepat, tetapi saya telah meminjam trik Strigoides untuk hanya menghitung suku kata dengan fraksi tetap.

Hapus golf , dengan komentar dan beberapa alat debugging:

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

Output: (menggunakan perancah dari versi panjang, tetapi fungsi golf.)

$ 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

Kekurangan:

  • Logika penghitungan kalimat itu salah, tetapi saya lolos karena hanya satu dari input yang memiliki a !atau a ?.
  • Logika penghitungan kata akan memperlakukan kontraksi sebagai dua kata.
  • Logika penghitungan suku kata akan memperlakukan kontraksi yang sama sebagai satu suku kata. Tapi mungkin kelebihan jumlah rata-rata (misalnya theredihitung sebagai dua dan banyak kata yang diakhirie akan dihitung satu terlalu banyak), jadi saya telah menerapkan faktor konstan koreksi 96,9%.
  • Mengasumsikan set karakter ASCII.
  • Saya percaya deteksi vokal akan mengakui [dan{ , yang jelas tidak benar.
  • Banyak ketergantungan pada semantik K&R membuat ini jelek, tapi hei, ini golf kode.

Hal-hal untuk dilihat:

  • Saya (sesaat) di depan kedua solusi python di sini, bahkan jika saya tertinggal perl.

  • Dapatkan banyak hal mengerikan yang saya lakukan untuk mendeteksi vokal. Masuk akal jika Anda menulis representasi ASCII dalam biner dan membaca komentar dalam versi panjang.

dmckee --- mantan kucing moderator
sumber
"Saya harus mengubah formula sedikit demi sedikit untuk mendapatkan hasil yang dapat diterima." Ini mungkin bentuk yang buruk.
Joe Z.
1
Sekarang saya memiliki setidaknya diikuti memimpin Strigoides' dan membuat penyesuaian atas dasar yang pemahaman teks membuat kesalahan daripada murni ad hoc Tweak untuk membunyikan tiga kasus uji perjanjian.
dmckee --- ex-moderator kitten
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

Pertama, dapatkan jumlah total kata dengan memisahkan spasi dan baris baru:

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

Lalu, rumusnya. Kalimat dan jumlah suku kata hanya digunakan satu kali, sehingga dimasukkan dalam ungkapan ini.

Kalimat hanyalah pemisahan input ., dengan baris baru disaring:

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

Suku kata terdiri dari pemisahan input di sepanjang non-vokal, dengan spasi dihapus. Ini tampaknya secara konsisten sedikit melebih-lebihkan jumlah suku kata, jadi kita perlu menyesuaikannya (sekitar 0,98 tampaknya melakukannya):

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

202 -> 194: len(x)-2 daripada len(x[1:-1]). Kurung yang tidak perlu dihapus. Membuat suku kata regex tidak sensitif huruf

194 -> 188: File sebelumnya disimpan sebagai dos daripada format file unix, menyebabkan wc -cmenghitung baris baru sebagai dua karakter. Aduh.

188 -> 184: Singkirkan orang-orang jahat x for x in ... if x!=...dengan menyimpan hasil antara dan mengurangix.count(...)

184 -> 171: Hapus input / output, dan konversikan ke fungsi

171 -> 167: Masukkan huruf len(x)-x.count(...)s ke dalam rumus

Strigoides
sumber
Jawaban Anda tidak harus menyertakan prosedur input dan output.
Joe Z.
@ JoZeng Oh, oke. Saya akan mengubahnya menjadi fungsi kalau begitu.
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

Ini adalah solusi yang agak panjang, tetapi bekerja dengan cukup baik, setidaknya dari 3 kasus uji yang disediakan.

Kode pengujian

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

Hasil -

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

Saya menggunakan penghitung suku kata dari sini - Menghitung suku kata

Versi yang lebih mudah dibaca tersedia di sini

elssar
sumber
1
if len(w)>2 and w[-1]=='e'and w[-2]not in v and w[-3]in v:c-= 1Berpikir sederhana tetapi pendekatan yang bagus. Saya suka itu.
dmckee --- mantan moderator kucing
0

Javascript, 191 byte

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)

Test case pertama memberi 112,9 (jawaban yang benar adalah 111,4, dimatikan 1,5 poin)

Test case kedua memberi 67,4 (jawaban yang benar adalah 65,1, dimatikan oleh 2,3 poin)

Test case ketiga memberi 1,7 (jawaban yang benar adalah 3,7, off dengan 2,0 poin)

SuperJedi224
sumber