Execute a Markov algorithm: Difference between revisions

Added OCaml solution
(Add Déjà Vu example)
(Added OCaml solution)
Line 2,059:
 
Under the rules of left 4 registers, under the word has 8 character cells, the alphabet of the digits from 1 to 8. Rules are placed in "123,456", where "123" is a fragment, and "456" is to be replaced, in the registers of the РA to РD. The number of rules is stored in Р0, the initial word is in Р9. Number triggered rule is the last digit registration Р4 (0 to 3), if no rule did not work, the indicator 0, otherwise the current word to be processed. In РE is stored 10.
 
=={{header|OCaml}}==
 
I'm not familiar with string processing, or parsing, so there are probably better ways to express this in OCaml. One might be with the mikmatch library which allows pattern-matching with regexps. Here I've only used the OCaml stdlib...
 
<lang OCaml>(* Useful for resource cleanup (such as filehandles) *)
let try_finally x f g =
try let res = f x in g x; res
with e -> g x; raise e
 
(* Substitute string 'b' for first occurance of regexp 'a' in 's';
* Raise Not_found if there was no occurance of 'a'. *)
let subst a b s =
ignore (Str.search_forward a s 0); (* to generate Not_found *)
Str.replace_first a b s
 
(* At their simplest, modules can function like namespaces... though they're much more. *)
module Markov = struct
let parse_rules cin =
let open Str in
let rule = regexp "\\(.+\\)[ \t]+->[ \t]+\\(.*\\)" in
let leader s c = String.length s > 0 && s.[0] = c in
let parse_b s = if leader s '.' then (string_after s 1,true) else (s,false) in
let rec parse_line rules =
try
let s = input_line cin in
if leader s '#' then parse_line rules
else if string_match rule s 0 then
let a = regexp_string (matched_group 1 s) in
let b,terminate = parse_b (matched_group 2 s) in
parse_line ((a,b,terminate)::rules)
else failwith ("parse error: "^s)
with End_of_file -> rules
in List.rev (parse_line [])
 
let rec run rules text =
let rec apply s = function
| [] -> s
| (a,b,term)::next ->
try
let s' = subst a b s in
if term then s' else run rules s'
with Not_found -> apply s next
in apply text rules
end
 
let _ =
if Array.length Sys.argv <> 2 then
print_endline "Expecting one argument: a filename where rules can be found."
else
let rules = try_finally (open_in Sys.argv.(1)) Markov.parse_rules close_in in
(* Translate lines read from stdin, until EOF *)
let rec translate () =
print_endline (Markov.run rules (input_line stdin));
translate ()
in try translate () with End_of_file -> ()</lang>
 
With the above compiled to an executable 'markov', and the five rule-sets in files, strings are accepted on stdin for translation:
<pre>
<~/rosetta$> markov rules1
I bought a B of As from T S.
I bought a bag of apples from my brother.
 
<~/rosetta$> markov rules2
I bought a B of As from T S.
I bought a bag of apples from T shop.
 
<~/rosetta$> markov rules3
I bought a B of As W my Bgage from T S.
I bought a bag of apples with my money from T shop.
 
<~/rosetta$> markov rules4
_1111*11111_
11111111111111111111
 
<~/rosetta$> markov rules5
000000A000000
00011H1111000
</pre>
 
=={{header|Perl}}==
Anonymous user