我正在尝试以螺旋顺序(顺时针方向)打印数组,但我的代码无法正确打印。
我的数组是:
a = [
[2, 4, 6, 8],
[5, 9, 12, 16],
[2, 11, 5, 9],
[3, 2, 1, 8]
]
我的解决方案:
def print_circ(arr, row, col)
t = 0
b = row - 1
l = 0
r = col - 1
dir = 0
while t <= b and l <= r do
if dir == 0
for i in l..r
puts arr[t][i]
end
t += 1
end
if dir == 1
for i in t..b
puts arr[i][r]
end
r -= 1
end
if dir == 2
for i in r..l
puts arr[b][i]
end
b -= 1
end
if dir == 3
for i in b..t
puts arr[i][l]
end
l += 1
end
dir = (dir+1)%4
end
end
当我运行它时,它不打印出底部或左边缘:
2
4
6
8
16
9
8
9
12
5
11
任何人都可以帮我理解我的代码有什么问题吗?
答案 0 :(得分:2)
代码中的错误位于r..l
和b..t
,其中r
大于l
,b
大于t
}。定义从较高整数到较低整数的范围时,范围实际上是空的。例如:
irb> (0..3).to_a
=> [0, 1, 2, 3]
irb> (3..0).to_a
=> []
要修复反向迭代代码,您可以将for i in r..l
循环更改为(l..r).reverse_each do |i| ... end
。
答案 1 :(得分:0)
您应该在减少循环中使用downto
。
以下是您的代码修复:
def print_circ(arr, row, col)
t = 0
b = row - 1
l = 0
r = col - 1
dir = 0
while t <= b and l <= r do
if dir == 0
for i in l..r
puts arr[t][i]
end
t += 1
end
if dir == 1
for i in t..b
puts arr[i][r]
end
r -= 1
end
if dir == 2
for i in r.downto(l)
puts arr[b][i]
end
b -= 1
end
if dir == 3
for i in b.downto(t)
puts arr[i][l]
end
l += 1
end
dir = (dir+1)%4
end
end
print_circ([[2,4,6,8],[5,9,12,16],[2,11,5,9],[3,2,1,8]], 4, 4)
答案 2 :(得分:0)
您的代码问题已经解决了。我只想提供更加惯用的代码版本:
def each_spiral_value(arr)
t = 0
b = arr.size - 1
l = 0
r = arr.first.size - 1
dir = [:right, :down, :left, :up].cycle
while t <= b && l <= r
case dir.next
when :right
l.upto(r) { |i| yield arr[t][i] }
t += 1
when :down
t.upto(b) { |i| yield arr[i][r] }
r -= 1
when :left
r.downto(l) { |i| yield arr[b][i] }
b -= 1
when :up
b.downto(t) { |i| yield arr[i][l] }
l += 1
end
end
end
each_spiral_value(a) { |v| puts v }
的变化:
b
和r
分别根据数组size
及其first
元素的大小计算dir
使用cycle
创建一个通过调用next
case
语句而不是多个if
语句for
循环被upto
和downto
循环替换您也可以将块传递给next
,而不是手动调用cycle
。这将有效地取代您的while
循环:
[:right, :down, :left, :up].cycle do |dir|
break if t > b || l > r
case dir
# ...
end
end