clean code
This commit is contained in:
parent
d8211a1dc4
commit
952b5f1b2f
@ -27,7 +27,9 @@ let _ =
|
||||
with End_of_file -> close_in chan ) ;
|
||||
let lines = List.rev !lines in
|
||||
let generator = Omg.init () in
|
||||
List.iter (fun el -> Omg.feed generator el) lines ;
|
||||
let generator =
|
||||
List.fold_left (fun generator el -> Omg.feed generator el) generator lines
|
||||
in
|
||||
for _ = 0 to 30 do
|
||||
Format.fprintf Format.std_formatter "GEN: %s@."
|
||||
(Omg.generate_markov_text generator 50 (None, None) false)
|
||||
|
||||
80
src/omg.ml
80
src/omg.ml
@ -1,18 +1,20 @@
|
||||
let _ = Random.self_init ()
|
||||
let () = Random.self_init ()
|
||||
|
||||
type generator =
|
||||
{ forward_cache: (string * string, (string, int) Hashtbl.t) Hashtbl.t
|
||||
; backward_cache: (string * string, (string, int) Hashtbl.t) Hashtbl.t
|
||||
; words: (int, string) Hashtbl.t
|
||||
; last_two_words: (string * string) ref }
|
||||
; last_two_words: string * string }
|
||||
|
||||
let list_random_el l = List.nth l (Random.int (List.length l))
|
||||
|
||||
let add_word generator w =
|
||||
generator.last_two_words := (snd !(generator.last_two_words), w) ;
|
||||
let n = Hashtbl.length generator.words in
|
||||
Hashtbl.add generator.words n w
|
||||
Hashtbl.add generator.words n w ;
|
||||
{generator with last_two_words= (snd generator.last_two_words, w)}
|
||||
|
||||
let get_last_two_words generator =
|
||||
match !(generator.last_two_words) with
|
||||
match generator.last_two_words with
|
||||
| "", "" ->
|
||||
[]
|
||||
| x, "" | "", x ->
|
||||
@ -25,9 +27,9 @@ let init () =
|
||||
{ forward_cache= Hashtbl.create 4096
|
||||
; backward_cache= Hashtbl.create 4096
|
||||
; words= Hashtbl.create 4096
|
||||
; last_two_words= ref ("", "") }
|
||||
; last_two_words= ("", "") }
|
||||
in
|
||||
add_word gen "\n" ; gen
|
||||
add_word gen "\n"
|
||||
|
||||
let triples = function
|
||||
| w1 :: w2 :: s ->
|
||||
@ -57,43 +59,44 @@ let feed generator msg =
|
||||
let splitted = splitted @ ["\n"] in
|
||||
let triples = triples (get_last_two_words generator @ splitted) in
|
||||
List.iter
|
||||
(fun (w1, w2, w3) -> add_key generator.forward_cache (w1, w2) w3)
|
||||
(fun (w1, w2, w3) ->
|
||||
add_key generator.forward_cache (w1, w2) w3 ;
|
||||
add_key generator.backward_cache (w3, w2) w1)
|
||||
triples ;
|
||||
List.iter
|
||||
(fun (w1, w2, w3) -> add_key generator.backward_cache (w3, w2) w1)
|
||||
triples ;
|
||||
List.iter (fun el -> add_word generator el) splitted
|
||||
List.fold_left (fun generator el -> add_word generator el) generator splitted
|
||||
|
||||
let select_seed generator seed_word backward =
|
||||
let dir = if backward then -1 else 1 in
|
||||
match seed_word with
|
||||
| None ->
|
||||
let seed_word = ref "\n" in
|
||||
let next_word = ref "\n" in
|
||||
while !seed_word = "\n" || !next_word = "\n" do
|
||||
let seed = 1 + Random.int (Hashtbl.length generator.words - 2) in
|
||||
seed_word := Hashtbl.find generator.words seed ;
|
||||
next_word := Hashtbl.find generator.words (seed + dir)
|
||||
done ;
|
||||
(!seed_word, !next_word)
|
||||
let rec loop = function
|
||||
| "\n", _ | _, "\n" ->
|
||||
let seed =
|
||||
if backward then
|
||||
1 + Random.int (Hashtbl.length generator.words - 1)
|
||||
else Random.int (Hashtbl.length generator.words - 1)
|
||||
in
|
||||
loop
|
||||
( Hashtbl.find generator.words seed
|
||||
, Hashtbl.find generator.words (seed + dir) )
|
||||
| seed_word, next_word ->
|
||||
(seed_word, next_word)
|
||||
in
|
||||
loop ("\n", "\n")
|
||||
| Some w ->
|
||||
let possible_indexes =
|
||||
Hashtbl.fold
|
||||
(fun k v acc -> if v = w then k :: acc else acc)
|
||||
generator.words []
|
||||
in
|
||||
if possible_indexes = [] then failwith "select_seed" ;
|
||||
let index = Random.int (List.length possible_indexes) in
|
||||
let index = List.nth possible_indexes index in
|
||||
(w, Hashtbl.find generator.words (index + dir))
|
||||
let index = list_random_el possible_indexes + dir in
|
||||
(w, Hashtbl.find generator.words index)
|
||||
|
||||
let generate_markov_text generator max_size seed backward =
|
||||
let seed_word, next_word =
|
||||
match seed with
|
||||
| None, None ->
|
||||
select_seed generator None backward
|
||||
| Some x, None | None, Some x ->
|
||||
select_seed generator (Some x) backward
|
||||
| None, x | x, None ->
|
||||
select_seed generator x backward
|
||||
| Some x, Some y ->
|
||||
(x, y)
|
||||
in
|
||||
@ -113,11 +116,7 @@ let generate_markov_text generator max_size seed backward =
|
||||
for _ = 0 to max_size do
|
||||
gen_words := !w1 :: !gen_words ;
|
||||
let tbl =
|
||||
match Hashtbl.find cache (!w1, !w2) with
|
||||
| exception Not_found ->
|
||||
raise Stop
|
||||
| tbl ->
|
||||
tbl
|
||||
try Hashtbl.find cache (!w1, !w2) with Not_found -> raise Stop
|
||||
in
|
||||
let cache_n = Hashtbl.fold (fun _ v acc -> acc + v) tbl 0 in
|
||||
let i = if cache_n = 0 then 0 else Random.int cache_n in
|
||||
@ -139,16 +138,13 @@ let generate_markov_text generator max_size seed backward =
|
||||
w2 := new_word
|
||||
done
|
||||
with Stop -> () ) ;
|
||||
if not (!w2 = "\n") then gen_words := !w2 :: !gen_words ;
|
||||
let gen_words = !gen_words in
|
||||
let gen_words = List.filter (fun el -> not (el = "\n")) gen_words in
|
||||
if !w2 <> "\n" then gen_words := !w2 :: !gen_words ;
|
||||
let gen_words = List.filter (fun el -> el <> "\n") !gen_words in
|
||||
let buff = Buffer.create 512 in
|
||||
( match if not backward then List.rev gen_words else gen_words with
|
||||
| [x] ->
|
||||
Buffer.add_string buff x
|
||||
( match if backward then gen_words else List.rev gen_words with
|
||||
| [] ->
|
||||
()
|
||||
| x :: s ->
|
||||
Buffer.add_string buff x ;
|
||||
List.iter (fun el -> Buffer.add_string buff (" " ^ el)) s
|
||||
| [] ->
|
||||
() ) ;
|
||||
List.iter (fun el -> Buffer.add_string buff (" " ^ el)) s ) ;
|
||||
Buffer.contents buff
|
||||
|
||||
18
test/test.ml
18
test/test.ml
@ -9,14 +9,14 @@ let test_forward () =
|
||||
let wanted = ["foo bar baz qux"; "bar baz qux"; "baz qux"] in
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated = Omg.generate_markov_text generator 30 (None, None) false in
|
||||
assert (List.mem generated wanted)
|
||||
done ;
|
||||
let seen = List.map (fun el -> (el, ref false)) wanted in
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated = Omg.generate_markov_text generator 30 (None, None) false in
|
||||
List.iter (fun (el, seen) -> if el = generated then seen := true) seen
|
||||
done ;
|
||||
@ -29,14 +29,14 @@ let test_backward () =
|
||||
let wanted = ["foo bar baz qux"; "foo bar baz"; "foo bar"] in
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated = Omg.generate_markov_text generator 30 (None, None) true in
|
||||
assert (List.mem generated wanted)
|
||||
done ;
|
||||
let seen = List.map (fun el -> (el, ref false)) wanted in
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated = Omg.generate_markov_text generator 30 (None, None) true in
|
||||
List.iter (fun (el, seen) -> if el = generated then seen := true) seen
|
||||
done ;
|
||||
@ -49,7 +49,7 @@ let test_force_seed_forward () =
|
||||
let wanted = "bar baz qux" in
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated =
|
||||
Omg.generate_markov_text generator 30 (Some "bar", None) false
|
||||
in
|
||||
@ -59,7 +59,7 @@ let test_force_seed_forward () =
|
||||
done ;
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated =
|
||||
Omg.generate_markov_text generator 30 (Some "bar", Some "baz") false
|
||||
in
|
||||
@ -72,7 +72,7 @@ let test_force_seed_backward () =
|
||||
let wanted = "foo bar" in
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated =
|
||||
Omg.generate_markov_text generator 30 (Some "bar", None) true
|
||||
in
|
||||
@ -82,7 +82,7 @@ let test_force_seed_backward () =
|
||||
done ;
|
||||
for _ = 1 to 1000 do
|
||||
let generator = Omg.init () in
|
||||
Omg.feed generator source ;
|
||||
let generator = Omg.feed generator source in
|
||||
let generated =
|
||||
Omg.generate_markov_text generator 30 (Some "bar", Some "foo") true
|
||||
in
|
||||
@ -91,7 +91,7 @@ let test_force_seed_backward () =
|
||||
(Format.sprintf "generated = #%s# and wanted = #%s#@." generated wanted)
|
||||
done
|
||||
|
||||
let _ =
|
||||
let () =
|
||||
Format.printf "testing triples...@." ;
|
||||
test_triples () ;
|
||||
Format.printf "testing forward...@." ;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user