Execute a Markov algorithm: Difference between revisions
m tidy up description of task a little |
→Tcl: Added implementation |
||
Line 29: | Line 29: | ||
}) |
}) |
||
end</lang> |
end</lang> |
||
=={{header|Tcl}}== |
|||
{{works with|Tcl|8.5}} |
|||
<lang tcl>package require Tcl 8.5 |
|||
if {$argc < 3} {error "usage: $argv0 ruleFile inputFile outputFile"} |
|||
lassign $argv ruleFile inputFile outputFile |
|||
# Read the file of rules |
|||
set rules {} |
|||
set f [open $ruleFile] |
|||
foreach line [split [read $f] \n[close $f]] { |
|||
if {[string match "#*" $line] || $line eq ""} continue |
|||
if {[regexp {^(.+)\s+->\s+(\.?)(.*)$} $line -> from final to]} { |
|||
lappend rules $from $to [string equal "." $to] [string length $from] |
|||
} else { |
|||
error "Syntax error: \"$line\"" |
|||
} |
|||
} |
|||
# Apply the rules |
|||
set f [open $inputFile] |
|||
set out [open $outputFile w] |
|||
foreach line [split [read $f] \n[close $f]] { |
|||
set any 1 |
|||
while {$any} { |
|||
set any 0 |
|||
foreach {from to stop fl} $rules { |
|||
# If we match the 'from' pattern... |
|||
if {[set idx [string first $from $line]] < 0} { |
|||
continue |
|||
} |
|||
# Change for the 'to' replacement |
|||
set line [string replace $line $idx [expr {$idx+$fl-1}] $to] |
|||
# Stop if we terminate, otherwise note that we've more work to do |
|||
if {$stop} { |
|||
set any 0 |
|||
break |
|||
} else { |
|||
set any 1 |
|||
} |
|||
} |
|||
} |
|||
# Output the processed line |
|||
puts $out $line |
|||
} |
|||
close $out</lang> |
Revision as of 14:24, 15 December 2009
This page uses content from Wikipedia. The original article was at Markov_algorithm. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
You are encouraged to solve this task according to the task description, using any language you may know.
Create an interpreter for a Markov Algorithm. Rules have the syntax:
<comment> ::= # {<any character>} <rule> ::= <pattern> <whitespace> -> <whitespace> [.] <replacement> <whitespace> ::= (<tab> | <space>) [<whitespace>]
There is one rule per line. If there is a . present before the <replacement>, then this is a terminating rule in which case the interpreter must halt execution.
Ruby
<lang Ruby>raise "Please input an input code file, an input data file, and an output file." if ARGV.size < 3
rules = File.readlines(ARGV[0]).inject([]) do |rules, line|
if line =~ /^\s*#/ rules elsif line =~ /^(.+)\s+->\s+(\.?)(.*)$/ rules << [$1, $3, $2 != ""] else raise "Syntax error: #{line}" end
end
File.open(ARGV[2], "w") do |file|
file.write(File.read(ARGV[1]).tap { |input_data| while (matched = rules.find { |match, replace, term| input_data[match] and input_data.sub!(match, replace) }) and !matched[2] end })
end</lang>
Tcl
<lang tcl>package require Tcl 8.5 if {$argc < 3} {error "usage: $argv0 ruleFile inputFile outputFile"} lassign $argv ruleFile inputFile outputFile
- Read the file of rules
set rules {} set f [open $ruleFile] foreach line [split [read $f] \n[close $f]] {
if {[string match "#*" $line] || $line eq ""} continue if {[regexp {^(.+)\s+->\s+(\.?)(.*)$} $line -> from final to]} {
lappend rules $from $to [string equal "." $to] [string length $from]
} else {
error "Syntax error: \"$line\""
}
}
- Apply the rules
set f [open $inputFile] set out [open $outputFile w] foreach line [split [read $f] \n[close $f]] {
set any 1 while {$any} {
set any 0 foreach {from to stop fl} $rules { # If we match the 'from' pattern... if {[set idx [string first $from $line]] < 0} { continue }
# Change for the 'to' replacement set line [string replace $line $idx [expr {$idx+$fl-1}] $to]
# Stop if we terminate, otherwise note that we've more work to do if {$stop} { set any 0 break } else { set any 1 } }
}
# Output the processed line puts $out $line
} close $out</lang>