2

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.

3
  • What about Array#each? Commented Nov 7, 2017 at 2:54
  • What is counter in your second code? Commented Nov 7, 2017 at 6:05
  • 1
    @sawa thanks - I adjusted all the examples to use the same variables now. Commented Nov 7, 2017 at 13:25

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

Comments

1

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

1 Comment

Great suggestion

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.