class Array def indexof(v) self.each_with_index{|n, i| if n ==v return i end } return -1 end def shuffle! tmp=[] while self.size > 0 do r = (rand*self.size).to_i tmp[tmp.size] = self[r] self.delete_at(r) end tmp.each{|n| self[self.size]=n } end def at_random self[(rand*self.size).to_i] end def append(x) self[self.size]=x end end #class for pseudo-encryption using vig table class Vig def initialize @tbl = Array.new (0..255).each{ |i| @tbl[i] = Array.new (0..255).each{ |j| @tbl[i][j] = (j+i)%255 } } @tbl.shuffle! end def enc(s) prev=0 out=[] s.each_byte{|b| c = @tbl[prev][b] out[out.size] = c prev = c } out end def dec(inp) prev=0 out="" inp.each{|b| c = @tbl[prev].indexof(b) out += c.chr prev = b } out end end #atoms may have semantic information class Atom @value @semantics @section attr :semantics def initialize(c, s) @section = c @semantics = Semantics.new s.split.each{|t| case t when /^\{(.*)\}/ @semantics.apply($1) else if @value @value += " " + t else @value = t end end } end def to_s @value end def apply(s) @semantics.apply(s) end def score(sem) @semantics.score(sem) end end #rules may have predicates class Rule @section @tokens def initialize(c, s) @section = c @tokens = s.split end def each (&pr) @tokens.each{|t| yield t } end def to_s @tokens.to_s end end #the state contains information that is used to pick atoms class Semantics @flags attr :flags def initialize reset end def set(s, f) case s when "+" @flags[f] = 1 when "-" @flags[f] = -1 when "!" @flags[f] = 0 when "~" @flags[f] = @flags[f]*-1 if @flags[f] else raise "State flag #{s} not understood." end end def reset @flags = Hash.new end def getFlag(f) return @flags[f] if @flags[f] return 0 end def apply(s) s.split(",").each{|t| a = t.slice 0,1 b = t.slice 1,1 set(a,b) } end def merge(s) s.flags.each_pair{|f, v| @flags[f] = getFlag(f) + v } end #how well do these two values match? def score( s) score=0; @flags.each_pair{|f, v| x = s.getFlag(f) (x==v)?score+=1:score-=1; } score end def strict_score( s) score=0; @flags.each_pair{|f, v| x = s.getFlag(f) (x==v)?score+=1:score=-1000; } score end def easy_score( s) score=0; @flags.each_pair{|f, v| x = s.getFlag(f) (x==v)?score+=1:score+=0; } score end end #main class class Cc @log @atom @rule @state @stickyatoms attr :log def initialize @atom = Hash.new @rule = Hash.new @state = Semantics.new @stickyatoms = true @log = false end #load rules and atoms def loadTables(file) f = File.open(file, "r") section = "unknown" what = Atom f.each_line{|l| l.chop! case l when "" when /^#/ when /\[(.*)\]/ section = $1 what = Rule if @rule[section] == nil @rule[section] = Array.new end when /<(.*)>/ what = Atom section = $1 if @atom[section] == nil @atom[section] = Array.new end else x = what.new(section, l) if what == Atom @atom[section].append x else @rule[section].append x end p x if @log end } end #given a rule name, expand it recursively def dorule(rulename) p "Rule: " + rulename if @log s="" a = @rule[rulename] if a==nil then raise "Rule #{rulename} does not exist" end rule = a.at_random begin rule.each{|tok| case tok when /^_(.*)/ r = doatom($1) when /^%(.*)/ r = dorule($1) when /^\{(.*)\}/ dopred($1) r = "" else r = tok end s += r.to_s s += " " } rescue p "Error in rule " + rule.to_s raise end p "Value: " + s if @log s end #given a string which is a semantic predicate embedded in a rule... do something great! def dopred(pred) p "Evaluating semantic predicate: " + pred if @log begin @state.apply(pred) rescue p "Error in predicate " + pred raise end end #given an atom type, pick an atom def doatom(atomname) best = nil a = @atom[atomname] atom=nil raise "Atom #{atom} does not exist" if a == nil bestscore = -1000000 (0..16).each{|i| atom = a.at_random score = @state.score(atom.semantics) if bestscore < score then bestscore = score best = atom # p "best match " + score.to_s + " " + atom.to_s end } if @stickyatoms then @state.merge(atom.semantics) # p @state end best.to_s end #given the string result of a rule or literal, apply it to outputstring def postProcess(s) out="" nospace=true sentencebreak=true waitingfora=false a = s.split a.each{|t| case t when "`" nospace = true when "&" if sentencebreak then out += "\n" end sentencebreak = true when "@" waitingfora = true else out += " " unless nospace == true out += "\n" if sentencebreak == true if waitingfora then x = t.slice (0,1) if x=="a" || x=="e" || x=="i" || x=="o" || x=="u" then t = "an " + t else t = "a " + t end end if t == "i" then t = "I" end t.capitalize! if sentencebreak == true out += t nospace = false sentencebreak = false waitingfora = false end } #p @state out end def enc(a) end def dec(a) end end #vig = Vig.new # #a = vig.enc("aacaaaaaaaaaa") # #cc = Cc.new # # #cc.loadTables("./ctab.txt") # #s = cc.dorule("poem") # #print "\n\n-----\n\n" #print cc.postProcess(s) #print "\n\n-----\n\n" # #Unforgiven lost teachers #----=-==-====-==-=---- #At the darkest hour I cry yearning after their skull scratching at a sensual spa #sm and yet cry... #The thorn of desolation seethes. #The cold knives drift... #I destroy my mirage, silently... #And why do i cry dying beside the terrifying dragon amid the vengeance?