Just a modification of @tihom's answer, not relying on uniqueness, but using some ideas from "How to map with index in Ruby?":
>> arr.each_with_index.select{ |x, i| (arr.count-i)%5 != 0 }.map{ |x,i| x }
=> [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]
Step by step it does:
.each_with_index returns an Enumerator, which yields pairs of value and its index like [7, 0], [8, 1], [9, 2], ...
.select{...} selects those pairs [x,i] for which count - i is not divisible by 5 (it would be all except count - 5, count - 10, etc)
.map{ |x,i| x } transforms each pair to just its first element.
Not the most efficient, but at least clear, I think
BONUS:
I am sure that it is better to create a new array by some tranformation (in a functional-style) than modify it in-place, but if you insist on "in-place", here is a modification of @sawa's answer without hard-coded digits:
>> (-arr.count..-5).select {|i| i % 5 == 0}.each{|i| arr.delete_at(i)}
=> [-15, -10, -5]
>> arr
=> [8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 22, 23]
Here we have a range from -size to -5, select only indices that are divisible by 5, and delete by them. As he said, it is important here to delete exactly in this order. But still to protect yourself from possible mistakes, I think it is safer yo never delete from an array you are iterating through and instead produce a new array (like in first method). Why complicate? ;)
delete_ataccepts index. Give it an index.