### [题解]ZOJ Monthly, May 2011 » 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
```