Walk a sequence and count occurrences of each value in a map. Classic "get current count, add one, write back" loop.

Algorithm

Basic Implementation

basic.lua
local words = {"fig", "apple", "fig", "pear", "apple", "fig"}
local counts = {}
local order = {}
local i = 1
while i <= #words do
	local word = words[i]
	if counts[word] == nil then
		order[#order + 1] = word
		counts[word] = 1
	else
		local prev = counts[word]
		counts[word] = prev + 1
	end
	i = i + 1
end
io.write("{")
local j = 1
while j <= #order do
	if j > 1 then
		io.write(", ")
	end
	local key = order[j]
	io.write(key .. ": " .. tostring(counts[key]))
	j = j + 1
end
io.write("}\n")

The pinned input is [fig, apple, fig, pear, apple, fig]. The diagrams show get-or-default, writeback, and final bucket contents.

Step 1 - First write creates a key

fig is absent, so get-or-default reads 0 and writes fig: 1.

After reading the first word fig.wordold countnew countmapfig01{fig: 1}

Step 2 - Existing keys increment

The second fig reads 1 and writes 2; apple has its own count.

After fig, apple, fig.scanfigapplepearafter fig100after apple110after fig210

Step 3 - Final counts

The full scan produces fig: 3, apple: 2, and pear: 1.

Final map for [fig, apple, fig, pear, apple, fig].bucket/keycountfig3apple2pear1

Complexity

  • Time: O(n) average with Lua tables (hash-table backed for string keys).
  • Space: O(k) where k is the number of distinct keys.

Implementation notes

  • Lua: counts = {} is the idiomatic table; the counts[word] == nil predicate plus an explicit assignment keeps the lesson on the read-or-default path without hiding it behind a metatable __index default. Lua has no array_count_values shortcut, so the explicit loop already mirrors the lesson spec.
  • The auxiliary order buffer makes the first-seen order explicit so the final printout does not lean on Lua's unspecified hash-key iteration order as a contract.
  • The replay renders the map as a list of key/value rows in first-seen order and animates the count increment on each frame.
get-or-default A first-time `word` triggers the "default" branch: append to `order` and set `counts[word] = 1`. A repeat read-modify-writes `counts[word] = prev + 1`.
first-seen order Keys are tracked in `order` (a plain sequence) to keep the printout deterministic; Lua's table iteration order is unspecified for non-sequence keys.