$values = {} # hodnoty portu (nil u neznamych) $gates = [] # hradla # hradlo class Gate attr_accessor :inputs # pole indexu v poli $values ktere jsou vstupy attr_accessor :output # a vystup def initialize @inputs = [] @output = nil end def all_inputs? @inputs.all? { |i| $values[i] } end end class AndGate < Gate def make_output value = 1 for i in @inputs if $values[i] == 0 value = 0 break end end $values[@output] = value end end class OrGate < Gate def make_output value = 0 for i in @inputs if $values[i] == 1 value = 1 break end end $values[@output] = value end end class XorGate < Gate def make_output ones = 0 for i in @inputs if $values[i] == 1 ones += 1 end end $values[@output] = ones % 2 end end class NotGate < Gate def make_output value = $values[@inputs[0]] == 1 ? 0 : 1 $values[@output] = value end end $input_ports = [] # idcka vstupnich portu $input_ports_values = [] # a jejich hodnoty $output_ports = [] # a vystupnich require 'rexml/document' # parsuje soubor a haze chyby def parse_file(filename) input = File.new filename doc = REXML::Document.new input doc.root.each_element "input" do |elem| a = elem.attributes $values[a["id"]] = nil $input_ports.push a["id"] end doc.root.each_element "output" do |elem| a = elem.attributes $output_ports.push a["id"] end doc.root.each_element "gate" do |elem| klass = case elem.attributes["type"].downcase when "and" AndGate when "or" OrGate when "not" NotGate when "xor" XorGate end gate = klass.new elem.each_element("input") do |e| gate.inputs.push e.attributes["id"] end elem.each_element("output") do |e| if gate.output raise ParseError, "Hradlo muze mit jen jeden vystup" end gate.output = e.attributes["id"] end # kontrola vstupu if gate.kind_of? NotGate unless gate.inputs.size == 1 raise ParseError, "Hradlo not ma jen jeden vstup" end else unless gate.inputs.size >= 1 raise ParseError, "Hradlo musi mit alespon jeden vstup" end end $gates.push gate end end # ziska vstupni udaje ze souboru filename a vypise jejich vysledek def get_inputs(filename) file = File.open filename while line = file.gets $values = {} for i in 0...$input_ports.size $values[$input_ports[i]] = line[i].chr.to_i end puts calculate end end # spocita vystupy a vrati je jako string def calculate gates = $gates.clone # hradla ke zpracovani # dokud nejake hradla zbyvaji, pro hradla ktera maji vsechny vstupy # dela vystup until gates.empty? catch :deleted do 0.upto gates.size-1 do |i| if gates[i].all_inputs? gates[i].make_output gates.delete_at i throw :deleted end end end end str = "" $output_ports.each do |out| str << $values[out].to_s end return str end if ARGV.size != 2 STDERR.puts File.read "README" exit 1 end begin STDERR.print "Parsuji..." STDERR.flush parse_file ARGV[0] STDERR.puts " OK" get_inputs ARGV[1] rescue Interrupt STDERR.puts "Hej! Ani me nenechas dobehnout!" exit 1 end