[题解]ZOJ Monthly, May 2011 » ZOJ3503gen

ZOJ3503gen
ZOJ3503gen.rb


require 'matrix'

class Array
	def rand
		at(Kernel.rand(size))
	end
end

surface = {
	'coincident planes' =>
		-> {[[rand, 0, 0], [0, 0, 0], 0]},
	'ellipsoid (imaginary)' =>
		-> {[[rand, rand, rand], [0, 0, 0], rand]},
	'ellipsoid (real)' =>
		-> {[[rand, rand, rand], [0, 0, 0], -rand]},
	'elliptic cone (imaginary)' =>
		-> {[[rand, rand, rand], [0, 0, 0], 0]},
	'elliptic cone (real)' =>
		-> {[[rand, rand, -rand], [0, 0, 0], 0]},
	'elliptic cylinder (imaginary or real)' =>
		-> {[[rand, rand, 0], [0, 0, 0], rand * 2 - 1]},
#	'elliptic cylinder (imaginary)' =>
#		-> {[[rand, rand, 0], [0, 0, 0], rand]},
#	'elliptic cylinder (real)' =>
#		-> {[[rand, rand, 0], [0, 0, 0], -rand]},
	'elliptic paraboloid' =>
		-> {[[rand, rand, 0], [0, 0, -rand], 0]},
	'hyperbolic cylinder' =>
		-> {[[rand, -rand, 0], [0, 0, 0], rand]},
	'hyperbolic paraboloid' =>
		-> {[[rand, -rand, 0], [0, 0, rand], 0]},
	'hyperboloid of one sheet' =>
		-> {[[rand, rand, -rand], [0, 0, 0], -rand]},
	'hyperboloid of two sheets' =>
		-> {[[rand, rand, -rand], [0, 0, 0], rand]},
	'intersecting planes (imaginary)' =>
		-> {[[rand, rand, 0], [0, 0, 0], 0]},
	'intersecting planes (real)' =>
		-> {[[rand, -rand, 0], [0, 0, 0], 0]},
	'parabolic cylinder' =>
		-> {[[rand, 0, 0], [0, 0, rand], 0]},
	'parallel planes (imaginary or real)' =>
		-> {[[rand, 0, 0], [0, 0, 0], rand * 2 - 1]},
#	'parallel planes (imaginary)' =>
#		-> {[[rand, 0, 0], [0, 0, 0], rand]},
#	'parallel planes (real)' =>
#		-> {[[rand, 0, 0], [0, 0, 0], -rand]}
}

def swap(a, b, c)
	b.map!{|i| rand < 0.5 ? i : -i}
	p = [*0 .. 2].shuffle
	a = [*0 .. 2].map{|i| a[p[i]]}
	b = [*0 .. 2].map{|i| b[p[i]]}
	return Matrix.diagonal(*a), Matrix.column_vector(b), Matrix.diagonal(c)
end

def rotate(a, b, c)
	theta = rand < 0.618 ? 0 : rand * 2 * Math::PI
	rx = Matrix[
		[1, 0, 0],
		[0, Math.cos(theta), -Math.sin(theta)],
		[0, Math.sin(theta), Math.cos(theta)]]
	theta = rand < 0.618 ? 0 : rand * 2 * Math::PI
	ry = Matrix[
		[Math.cos(theta), 0, Math.sin(theta)],
		[0, 1, 0],
		[-Math.sin(theta), 0, Math.cos(theta)]]
	theta = rand < 0.618 ? 0 : rand * 2 * Math::PI
	rz = Matrix[
		[Math.cos(theta), -Math.sin(theta), 0],
		[Math.sin(theta), Math.cos(theta), 0],
		[0, 0, 1]]
	r = rx * ry * rz
	a = r.transpose * a * r
	b = r.transpose * b
	return a, b, c # a - a.transpose = 0
end

def shift(a, b, c)
	h = Matrix.column_vector([
		rand < 0.618 ? 0 : rand * 4 - 2,
		rand < 0.618 ? 0 : rand * 4 - 2,
		rand < 0.618 ? 0 : rand * 4 - 2])
	c = h.transpose * a * h + b.transpose * h + c
	b = 2 * (a * h) + b
	return a, b, c
end

def tof(a, b, c)
	# ax2+by2+cz2+2fyz+2gzx+2hxy+2px+2qy+2rz+d=0
	[a[0, 0], a[1, 1], a[2, 2], a[1, 2], a[2, 0], a[0, 1], b[0, 0] / 2, b[1, 0] / 2, b[2, 0] / 2, c[0, 0]]
end

input = open('input', 'w')
output = open('output', 'w')
input.puts 10000
10000.times do
	type = surface.keys.rand
	fun = tof(*shift(*rotate(*swap(*surface[type].call))))
	scale = rand < 0.5 ? 100 : -100
	str = fun.map{|_| _ * scale} * ' '
	redo if str =~ /e/
	input.puts str
	output.puts type
end
input.close
output.close
Leave a Reply