1 people like it.

Calculate Flesch Reading Ease Score (FRES)

Calculate the Flesch Reading Ease Score for a string or a file. https://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_tests

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
#if INTERACTIVE
#else
module Readability
#endif

open System.Text.RegularExpressions
open System

module Seq =
    let IntAverage = 
        Seq.map float
        >> Seq.average

[<AutoOpen>]
module private __ =
    // Naive but good-enough for syllable count:
    let reSyllables = Regex(@"([aeiouy])+([^aeiouy])?", RegexOptions.IgnoreCase)
    let reWords =  Regex(@"(\w+)", RegexOptions.IgnoreCase)
    
let CountSyllables s =
    let ms = reSyllables.Matches(s)
    ms.Count

let Words s =
    let matches = reWords.Matches(s)
    seq { for m in matches -> m.Value }

let WordsPerSentence =
    Seq.map Words
    >> Seq.map Seq.length

let SyllablesPerWord =
    Seq.map CountSyllables

let MinLength n seq =
    seq |> Seq.length > n

let Sentences (s : string) =
    // Assumes \n or \r\n ends a sentence (e.g. titles). Consider removing \n and \r\n
    // for line-split formats like Gutenberg.
    s.Split([|". "; "! "; "? "; "\n"; "\r\n"|], StringSplitOptions.RemoveEmptyEntries)
    |> Seq.filter (MinLength 1)

let AvgWordsPerSentence =
    Sentences
    >> WordsPerSentence
    >> Seq.IntAverage

let AvgSyllablesPerWord =
    Words
    >> SyllablesPerWord
    >> Seq.IntAverage

let Flesch s =
    let wps = s |> AvgWordsPerSentence
    let spw = s |> AvgSyllablesPerWord
    206.835 - (1.015 * wps) - (84.6 * spw)

let FileFlesch =
    IO.File.ReadAllText
    >> Flesch

do Flesch "The cat sat on the mat." |> printfn "%f" // 116.14
namespace System
namespace System.Text
namespace System.Text.RegularExpressions
module Seq

from Microsoft.FSharp.Collections
val IntAverage : (seq<int> -> float)

Full name: Script.Seq.IntAverage
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val average : source:seq<'T> -> 'T (requires member ( + ) and member DivideByInt and member get_Zero)

Full name: Microsoft.FSharp.Collections.Seq.average
Multiple items
type AutoOpenAttribute =
  inherit Attribute
  new : unit -> AutoOpenAttribute
  new : path:string -> AutoOpenAttribute
  member Path : string

Full name: Microsoft.FSharp.Core.AutoOpenAttribute

--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
val private reSyllables : Regex

Full name: Script.__.reSyllables
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
Regex(pattern: string) : unit
Regex(pattern: string, options: RegexOptions) : unit
type RegexOptions =
  | None = 0
  | IgnoreCase = 1
  | Multiline = 2
  | ExplicitCapture = 4
  | Compiled = 8
  | Singleline = 16
  | IgnorePatternWhitespace = 32
  | RightToLeft = 64
  | ECMAScript = 256
  | CultureInvariant = 512

Full name: System.Text.RegularExpressions.RegexOptions
field RegexOptions.IgnoreCase = 1
val private reWords : Regex

Full name: Script.__.reWords
val CountSyllables : s:string -> int

Full name: Script.CountSyllables
val s : string
val ms : MatchCollection
Regex.Matches(input: string) : MatchCollection
Regex.Matches(input: string, startat: int) : MatchCollection
property MatchCollection.Count: int
val Words : s:string -> seq<string>

Full name: Script.Words
val matches : MatchCollection
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val m : Match
property Capture.Value: string
val WordsPerSentence : (seq<string> -> seq<int>)

Full name: Script.WordsPerSentence
Multiple items
module Seq

from Script

--------------------
module Seq

from Microsoft.FSharp.Collections
val length : source:seq<'T> -> int

Full name: Microsoft.FSharp.Collections.Seq.length
val SyllablesPerWord : (seq<string> -> seq<int>)

Full name: Script.SyllablesPerWord
val MinLength : n:int -> seq:seq<'a> -> bool

Full name: Script.MinLength
val n : int
Multiple items
val seq : seq<'a>

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val Sentences : s:string -> seq<string>

Full name: Script.Sentences
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
type StringSplitOptions =
  | None = 0
  | RemoveEmptyEntries = 1

Full name: System.StringSplitOptions
field StringSplitOptions.RemoveEmptyEntries = 1
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter
val AvgWordsPerSentence : (string -> float)

Full name: Script.AvgWordsPerSentence
val AvgSyllablesPerWord : (string -> float)

Full name: Script.AvgSyllablesPerWord
val Flesch : s:string -> float

Full name: Script.Flesch
val wps : float
val spw : float
val FileFlesch : (string -> float)

Full name: Script.FileFlesch
namespace System.IO
type File =
  static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
  static member AppendAllText : path:string * contents:string -> unit + 1 overload
  static member AppendText : path:string -> StreamWriter
  static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
  static member Create : path:string -> FileStream + 3 overloads
  static member CreateText : path:string -> StreamWriter
  static member Decrypt : path:string -> unit
  static member Delete : path:string -> unit
  static member Encrypt : path:string -> unit
  static member Exists : path:string -> bool
  ...

Full name: System.IO.File
IO.File.ReadAllText(path: string) : string
IO.File.ReadAllText(path: string, encoding: Text.Encoding) : string
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Raw view Test code New version

More information

Link:http://fssnip.net/tp
Posted:9 years ago
Author:Kit Eason
Tags: text precessing , function composition