#!/usr/bin/ruby

# by timo proescholt 
# timo.proescholdt@rz.ifi.lmu.de

#str = "(r1(x), r2(x), r1(z), w2(y), r3(y), w1(z), w3(y), r4(z), w2(x), w3(z))"
#str2 = "(r1(x), r1(y), r4(y), r3(x), w2(x), w4(y), w3(y), w1(x))"


class Transactions
	def initialize(nummer)
		nummer-=1
		@adj=Array.new
		0.upto(nummer) { |i|
			@adj[i]=Array.new
			0.upto(nummer) { |j|
				@adj[i][j]=Array.new
			}
		}
	end

	attr_reader :adj
	attr_writer :adj

	def store(eins,zwei)
		#puts eins
		#puts zwei
		raise ArgumentError unless eins.is_a? Operation and zwei.is_a? Operation 
		adj[eins.mytransaktion-1][zwei.mytransaktion-1] << "#{eins.kind}#{zwei.kind}(#{eins.objekt}) "
	end

	def to_s
		#puts @adj.size
		s= Array.new
		0.upto(@adj.size-1) { |t|
			s << "transaktion #{t+1} hat kanten zu folgenden transaktionen"
			0.upto(@adj.size-1) { |j|
				if ( not @adj[t][j].empty? ) then
					s << "zu #{j+1}: "+@adj[t][j].join(" , ")
				end
			}
			s << ""
		}
		return s.join("\n")
		
	end

	def detect
		return dec_rec("",0)
	end

	def dec_rec(gewesen,t)

		@adj[t].each_index { |j|
			if (not @adj[t][j].empty?) then
				
				if ( gewesen =~/#{j}/ ) then
					return true
				else 
					return dec_rec(gewesen+" #{j}",j)
				end
			
			end
		}
		return false
	end
end


class Operation
	def initialize(string)
		raise ArgumentError.new("ungueltiges format") unless string=~/([rw])(\d+)([a-z])/
		@kind=$1
		@mytransaktion=$2.to_i
		@objekt=$3
	end
	attr_reader :kind, :mytransaktion, :objekt
	attr_writer :kind, :mytransaktion, :objekt

	def to_s 
		return @kind+@mytransaktion.to_s+"("+@objekt+")"
	end
 
end


class Factory 
	def initialize(string)
		string.gsub!(/\(/,'')
		string.gsub!(/\)/,'')

		max=0
		@s1=Array.new
		
		ops = string.split(/,/)
		ops.each { |o|
			o.strip
			@s1 << Operation.new(o)
		}

		@s1.each { |o|
			if ( o.mytransaktion>max ) then
				max=o.mytransaktion
			end
		}

		@t=Transactions.new(max)
			
	end

	def calc
		@s1.each_index { |opi|
			(opi+1).upto(@s1.size()-1) { |opj|
				me=@s1[opi]
				other=@s1[opj]
				#puts "vergleiche "+me.to_s+" mit "+other.to_s
				## interessanter code
		
				if ( ( other.kind=="w" or me.kind=="w" ) and me.objekt==other.objekt and me.mytransaktion!=other.mytransaktion ) then
					@t.store(me,other)
				end
		}
		#puts "------------\n"
		}
	end

	def to_s
		return @t.to_s
	end
	
	def detect
		return @t.detect
	end
end


str = String.new(ARGV[0])

t = Factory.new(str)
t.calc
puts t

if (t.detect) then
	puts "zyklus entdeckt"
else 
	puts "kein zyklus entdeckt"
end

