In article <1137942795.627040.75...@g43g2000cwa.googlegroups.com>,
"Vladimir Agafonkin" <agafon...@gmail.com> writes:
> Thanks for the test, passed.
> "Finished in 182.372 seconds." - quite long for my 2Ghz P4. I wonder
> how much it takes to pass the test for the other participants.
502.175 (~90 for the 1024x1024 and 411 for the 2048x2048)
on a AMD Athlon XP 1600+ (1400 MHz).
Pretty slow I guess.
So I redid that using a single array instead of arrays of arrays of arrays.
I'm still accessing each cell indidually. But that turned out to be even
slower (I used a Array3d class and the additional method lookup is obviously
too expensive, especially since I access each point individually).
So here's my solution:
#! /usr/bin/ruby
class Sheet
attr_reader :width, :height, :depth
def check(dim)
n = Math.log(dim)/Math.log(2) # ' /x
if n != n.to_i
raise "dimension must be power of 2"
end
end
def initialize(width, height)
check(width)
check(height)
sheet = []
0.upto(height-1) do | y |
sheet[y] = []
0.upto(width-1) do | x |
sheet[y][x] = [ width*y + x ]
end
end
set_sheet(sheet)
end
def set_sheet(sheet)
@sheet = sheet
@width = sheet[0].size
@height = sheet.size
@depth = sheet[0][0].size
end
def output()
0.upto( height-1 ) do | y |
0.upto( width-1 ) do | x |
(depth-1).downto( 0 ) do | z |
print "%3d " % (@sheet[y][x][z]+1)
end
print " "
end
puts ""
end
puts ""
end
def result
@sheet[0][0].reverse.collect { | i | i+1 }
end
# ok, here comes the ugly part...
# for each folding direction a new (stacked) sheet is calculated
def fold(dir)
new_sheet = []
if dir == "T"
s2 = height/2 # i'd really liked to know why xemacs has problems with foo/2; probably it's confused with a regex
raise "cannot fold" if s2 == 0
0.upto( s2-1 ) do | y |
new_sheet[y] = @sheet[y + s2]
0.upto( width-1 ) do | x |
0.upto( depth-1 ) do | z |
new_sheet[y][x][depth+depth-1-z] = @sheet[s2-1-y][x][z]
end
end
end
elsif dir == "B"
s2 = height/2 #'/x
raise "cannot fold" if s2 == 0
0.upto( s2-1 ) do | y |
new_sheet[y] = @sheet[y]
0.upto( width-1 ) do | x |
0.upto(depth-1) do | z |
new_sheet[y][x][depth+depth-1-z] = @sheet[s2+s2-1-y][x][z]
end
end
end
elsif dir == "L"
s2 = width/2 #'/x
raise "cannot fold" if s2 == 0
0.upto( height-1 ) do | y |
new_sheet[y] ||= []
0.upto( s2-1 ) do | x |
new_sheet[y][x] ||= []
0.upto( depth-1 ) do | z |
new_sheet[y][x][z] = @sheet[y][x+s2][z]
new_sheet[y][x][depth+depth-1-z] = @sheet[y][s2-1-x][z]
end
end
end
elsif dir == "R"
s2 = width/2 #'/x
raise "cannot fold" if s2 == 0
0.upto( height-1 ) do | y |
new_sheet[y] ||= []
0.upto( s2-1 ) do | x |
new_sheet[y][x] ||= []
0.upto( depth-1 ) do | z |
new_sheet[y][x][z] = @sheet[y][x][z]
new_sheet[y][x][depth+depth-1-z] = @sheet[y][s2+s2-1-x][z]
end
end
end
else
raise "unknown edge #{dir}"
end
set_sheet(new_sheet)
end
def folds(dirs)
dirs.split(//).each do | dir |
fold(dir)
end
end
end
def fold(width, height, cmds)
sheet = Sheet.new(width, height)
sheet.folds(cmds)
raise "to few folds..." if sheet.width > 1 || sheet.height > 1
return sheet.result
end
if ARGV[0]
cmds = ARGV[0]
width = (ARGV[1] || 16).to_i
height = (ARGV[2] || width).to_i
digits = (Math.log(width*height)/Math.log(10)).ceil
puts fold(width, height, cmds).collect { | i | "%#{digits}d" % i }.join(", ")
end