Reputation: 15957
In a completely contrived problem on exercism.io, I'm tasked to come up with a way to get the length/size of an array without using any enumerable methods.
I originally simply had:
arr = [1,3,4]
ctr = 0
while arr[ctr]
ctr += 1
end
ctr
The problem is that I can have arr = Array.new(5)
, which is [nil, nil, nil, nil, nil]
.
I've found two ways:
ctr = 0
loop do
element = arr.fetch(ctr) { 'outofbounds!' }
break if element == 'outofbounds!'
ctr += 1
end
ctr
I'd like to do it without using Array#fetch
because index out of bounds is just likely looking at the known length (which again I'm trying to implement).
Another solution:
ctr = 0
copy = arr.dup
while copy != []
ctr += 1
copy.pop
end
ctr
This feels slightly right but ==
on Array
first checks length then checks ==
on each element. I'm trying to implement length so stuck again.
Upvotes: 2
Views: 120
Reputation: 70257
I think your first solution is close. The problem, of course, is that nil
is a valid element of the list. So the easiest solution is to add a sentinel value at the end which is never going to be an element of the list.
I've used this idiom from time to time; you just make a brand new instance of the Object
class and use it as a value. No other object will ever compare equal to it, and it can't possibly be an element of the list since it was just now made up.
arr = [1,3,4]
end_of_list = Object.new
copy = arr.dup
copy.push end_of_list
ctr = 0
while end_of_list != copy[ctr]
ctr += 1
end
ctr
Upvotes: 1
Reputation: 211540
Here's a solution that's deliberately really out there because this question is an exercise in not doing things using the core API:
def array_length(a)
b = a.dup
c = [ ]
f = 0
while (b != [ ])
c.push('')
b.pop
f = 1
end
e = c.join("\x01").to_s.unpack('C*')
while (e[0])
f += e.pop
end
f
end
Upvotes: 2