Xây dựng một chỉ số dễ đọc


13

Các Flesch-Kincaid dễ đọc thuật toán phụ thuộc vào các biện pháp của số từ và số lượng âm tiết, không ai trong số đó là hoàn toàn khách quan, hoặc dễ dàng automatable sử dụng máy tính. Ví dụ: "code-golf", với dấu gạch nối, được tính là một hoặc hai từ? Là từ "triệu" hai hoặc ba âm tiết? Trong tác vụ này, bạn sẽ cần xấp xỉ, vì việc đếm chính xác sẽ tốn quá nhiều thời gian, không gian và quan trọng nhất là mã.

Nhiệm vụ của bạn là xây dựng chương trình nhỏ nhất có thể (nghĩa là một hàm) bằng bất kỳ ngôn ngữ nào sẽ có một đoạn đọc tiếng Anh (được giả sử là trong các câu hoàn chỉnh) và tính toán chỉ số Flesch Reading Easy với dung sai tám điểm (để tính các biến thể trong đếm âm tiết và đếm từ). Nó được tính như sau:

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

Chương trình của bạn phải được căn chỉnh theo các đoạn tham chiếu bên dưới, có chỉ số được tính bằng cách sử dụng tính thủ công:

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!

Chỉ số: 111,38 (64 âm tiết trong 62 từ trong 8 câu)

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.

Chỉ số: 65,09 (74 âm tiết trong 55 từ trong 2 câu)

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.

Chỉ số: 3,70 (110 âm tiết trong 71 từ trong 1 câu)

Nếu bạn có bất kỳ đoạn nào khác mà bạn đã đếm thủ công các âm tiết và từ và tính chỉ số, bạn có thể hiển thị chúng dưới dạng xác minh.


Nó có thể là một chức năng? Hay nó phải dùng STDIN?
Brigand

2
Bạn có số lượng âm tiết có sẵn cho 3 đoạn ví dụ, hoặc chỉ mục? Nếu bạn có nó, số lượng âm tiết sẽ có ích để so sánh.
Strigoides

Nó có thể là một chức năng. Trong thực tế, nó phải là một chức năng.
Joe Z.

Câu trả lời:


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

Mẫu 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

Việc đếm các âm tiết được thực hiện bằng cách giả sử rằng mỗi cụm nguyên âm là một âm tiết duy nhất, ngoại trừ các nguyên âm đơn độc ở cuối một từ, chỉ được tính hai phần ba thời gian; một heuristic dường như khá chính xác.


3

K & R c - 188 196 199 229 ký tự

Với thông số kỹ thuật được thay đổi để chỉ định một chức năng, tôi có thể nhận được rất nhiều chi phí c ngoài tổng số. Đồng thời thay đổi để sử dụng hack đếm âm tiết của Strigoides, tốt hơn so với tinh chỉnh công thức của tôi và được mở rộng để đối phó với việc vượt quá các từ.

Sau khi tôi tìm thấy một cách ngắn hơn để thực hiện phát hiện nguyên âm mà đáng buồn là dựa vào đó stdchr, tôi đã có động lực để vắt kiệt thêm một chút trong sự ghê tởm đôi chút mà tôi đã sử dụng để tôi không phải nhàm chán.

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

Logic ở đây là một máy trạng thái đơn giản. Nó chỉ đếm câu theo thời gian, từ theo chuỗi ký tự chữ cái và âm tiết dưới dạng chuỗi nguyên âm (bao gồm cả y).

Tôi đã phải điều chỉnh các hằng số một chút để đưa ra những con số phù hợp, nhưng tôi đã mượn mánh khóe của Strigoides khi chỉ vượt qua các âm tiết theo một phân số cố định.

Un-golfed , với các bình luận và một số công cụ sửa lỗi:

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

Đầu ra: (sử dụng giàn giáo từ phiên bản dài, nhưng chức năng đánh gôn.)

$ 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

Thiếu sót:

  • Logic đếm câu là sai, nhưng tôi tránh xa nó vì chỉ một trong những đầu vào có a !hoặc a ?.
  • Logic đếm từ sẽ coi các cơn co thắt là hai từ.
  • Logic đếm âm tiết sẽ coi những cơn co thắt tương tự như một âm tiết. Nhưng có lẽ số lượng vượt quá trung bình (ví dụ: theređược tính là hai và nhiều từ kết thúc esẽ được tính quá nhiều), vì vậy tôi đã áp dụng hệ số không đổi là 96,9%.
  • Giả sử một bộ ký tự ASCII.
  • Tôi tin rằng việc phát hiện nguyên âm sẽ thừa nhận [{rõ ràng là không đúng.
  • Rất nhiều sự phụ thuộc vào ngữ nghĩa K & R làm cho điều này trở nên xấu xí, nhưng hey, đó là môn đánh gôn.

Những điều cần xem xét:

  • Tôi (trong giây lát) đi trước cả hai giải pháp python ở đây, ngay cả khi tôi đang theo dõi perl.

  • Nhận một tải của điều khủng khiếp tôi đã làm để phát hiện các nguyên âm. Sẽ có ý nghĩa nếu bạn viết các biểu diễn ASCII ra dưới dạng nhị phân và đọc nhận xét trong phiên bản dài.


"Tôi đã phải thay đổi công thức một chút bằng tay để có kết quả chấp nhận được." Đây có thể là hình thức xấu.
Joe Z.

1
Bây giờ tôi có một tiếp nhất chì và làm Strigoides' những điều chỉnh trên cơ sở người hiểu văn bản làm cho lỗi chứ không phải là hoàn toàn quảng cáo hoc tinh chỉnh để rung ba trường hợp thử nghiệm thành thỏa thuận.
dmckee --- ex-moderator mèo con

2

Python, 202 194 188 184 171 167 ký tự

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

Đầu tiên, lấy tổng số từ bằng cách chia dọc theo khoảng trắng và dòng mới:

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

Sau đó, công thức. Số lượng câu và âm tiết chỉ được sử dụng một lần, vì vậy chúng được nhúng trong biểu thức này.

Các câu chỉ đơn giản là phân tách đầu vào cùng .với các dòng mới được lọc ra:

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

Các âm tiết bao gồm phân chia đầu vào dọc theo các nguyên âm, với các khoảng trắng được loại bỏ. Điều này dường như liên tục ước tính quá mức số lượng âm tiết, vì vậy chúng ta cần điều chỉnh nó xuống (khoảng .98 dường như để làm điều đó):

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

202 -> 194: len(x)-2 chứ không phải len(x[1:-1]). Loại bỏ dấu ngoặc không cần thiết. Thực hiện regex âm tiết trường hợp không nhạy cảm

194 -> 188: Tệp trước đây được lưu dưới dạng dos thay vì định dạng tệp unix, gây ra wc -ctính dòng mới là hai ký tự. Rất tiếc.

188 -> 184: Loại bỏ những x for x in ... if x!=...s khó chịu đó bằng cách lưu trữ kết quả trung gian và trừx.count(...)

184 -> 171: Xóa đầu vào / đầu ra và chuyển đổi thành chức năng

171 -> 167: Chèn len(x)-x.count(...)s vào công thức


Câu trả lời của bạn không phải bao gồm các thủ tục đầu vào và đầu ra.
Joe Z.

@JoeZeng ơi, được rồi. Tôi sẽ biến nó thành một chức năng sau đó.
Strigoides

1

Python 380 ký tự

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

Đây là một giải pháp khá dài, nhưng nó hoạt động đủ tốt, ít nhất là trong 3 trường hợp thử nghiệm miễn là nó hoạt động.

Mã kiểm tra

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

Kết quả -

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

Tôi đã sử dụng bộ đếm âm tiết từ đây - Đếm các âm tiết

Một phiên bản dễ đọc hơn có sẵn ở đây


1
if len(w)>2 and w[-1]=='e'and w[-2]not in v and w[-3]in v:c-= 1Đầu óc đơn giản nhưng gần đúng. Tôi thích nó.
dmckee --- ex-moderator mèo con

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)

Trường hợp kiểm tra đầu tiên cho 112,9 (câu trả lời đúng là 111,4, giảm 1,5 điểm)

Trường hợp kiểm tra thứ hai cho 67,4 (câu trả lời đúng là 65,1, giảm 2,3 điểm)

Trường hợp kiểm tra thứ ba cho 1.7 (câu trả lời đúng là 3.7, giảm 2.0 điểm)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.