When dealing with Enumerables like arrays and hashes, it's useful to search the documentation to see if there's something there that will make your code higher level and more expressive. In this case, you can use each_cons to give you the pairs so you don't need to use array indexes at all:
2.3.0 :004 > [1,2,3,4].each_cons(2).to_a
=> [[1, 2], [2, 3], [3, 4]]
Also, rather than using if statements, it's better IMO to use select and reject.
Also, intermediate local variables can make your code more readable.
Using these ideas, your code could look something like this:
array = [chap1, chap1_page, chap2, chap2_page, chap3, chap3_page]
width = line / 2
array.each_cons(2).reject { |x,y| x == 0 }.each do |left, right|
puts left.ljust(width) + right.ljust(width)
end
(I haven't tested this code, but it shows the general idea.)
You could break down those enumerable calls and assign intermediate values to local variables if that makes it clearer for you:
array = [chap1, chap1_page, chap2, chap2_page, chap3, chap3_page]
width = line / 2
pairs = array.each_cons(2)
nonzero_pairs = pairs.reject { |x,y| x == 0 }
nonzero_pairs.each do |left, right|
puts left.ljust(width) + right.rjust(width)
end
Array#each? As a side effect, you wouldn't need to use a counter variable like this. More on topic: what do you mean by "works" and "does not [work]"? Ifxis 2, thenarr[x + 1]should return the element at index 3. What output are you seeing that you didn't expect?