0

I'm doing some codewars and arr[index] keeps returning nil. I've done this a few different ways, and I'm sure the array exists, as well as the index. What's wrong here, is it syntax? As I've mentioned in the title, I want to find the last digit of the array.

if arr[index] <= 0 then
    return -1
end

Full Code:

local solution = {}

function solution.newAvg(arr, navg)
    local currentAverage = 0
    local index = 0
    for i, v in pairs(arr) do
        index = i
        currentAverage = currentAverage + v
    end
    if arr[index] <= 0 then
        return -1
    end
    return math.ceil(((index+1) * navg) - currentAverage)
end

return solution
Zakk
  • 1,935
  • 1
  • 6
  • 17

2 Answers2

1

I see two issues with your code:

Edge case: Empty array

If arr = {}, the loop for i, v in pairs(arr) do won't execute at all and index will remain at 0. Since arr is empty, arr[0] will be nil and arr[index] <= 0 will fail with an "attempt to compare a nil value" error.

Lack of ordering guarantee

You use pairs rather than ipairs to loop over what I assume is a list. This means keys & values might be traversed in any order. In practice pairs usually (but not always!) traverses the list part of a table in the same order as ipairs, but the reference manual clearly states that you can't rely on no specific order. I don't think CodeWars is this advanced but consider the possibility that pairs may be overridden to deliberately shuffle the order of traversal in order to check whether you're relying on the dreaded "undefined behavior". If this is the case, your "last index" might actually be any index that happens to be visited last, obviously breaking your algorithm.

Fixes

I'll assume arr is an "array", that is, it only contains keys from 1 to n and all values are non-nil (i.e. there are no holes). Then you can (and should!) use ipairs to loop over the "array":

for i, v in ipairs(arr) do ... end

I don't know the problem statement so it's hard to tell how an empty array should be handled. I'll assume that it should probably return 0. You could add a simply early return at the top of the function for that: if arr[1] == nil then return 0 end. Nonempty arrays will always have arr[1] ~= nil.

Luatic
  • 8,513
  • 2
  • 13
  • 34
1

I want to find the last digit of the array.

If you mean the last integer (or entry/item) of the array:

local last = array[#array]

If you mean the last digit (for example array = {10, 75, 44, 62} and you want 2), then you can get the last item and then get the last digit using modulo 10:

local last = array[#array] % 10
for i, v in pairs(arr) do
    index = i
    currentAverage = currentAverage + v
end

Just a reminder:

  1. #array returns the number of items in a table.
  2. In Lua, arrays are implemented using integer-indexed tables.
  3. There's a difference between pairs() and ipairs().

Regarding point 3 above, the following code:

local array = {
    [1] = 12,
    [2] = 32,
    [3] = 41,
    [4] = 30,
    [5] = 14,
    [6] = 50,
    [7] = 62,
    [8] = 57
}

for key, value in pairs(array) do
    print(key, value)
end

produces the following output (note that the order of keys is not respected):

8   57
1   12
2   32
3   41
4   30
5   14
6   50
7   62

while the same code above with pairs() replaced with ipairs() gives:

1   12
2   32
3   41
4   30
5   14
6   50
7   62
8   57

So, this might be the cause of your problem.

Zakk
  • 1,935
  • 1
  • 6
  • 17