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

Algorithm

Canonical input ("fig", "apple", "fig", "pear", "apple", "fig") produces the final map {fig: 3, apple: 2, pear: 1}.

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 array of strings) to keep the printout deterministic; Perl hashes do not preserve insertion order, so the auxiliary list is the only reliable way to walk keys in the order the lesson spec expects.

Visual walkthrough

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

Basic Implementation

basic.pl
use strict; use warnings;
my @words = ("fig", "apple", "fig", "pear", "apple", "fig");
my %counts = ();
my @order = ();
my $i = 0;
while ($i < scalar @words) {
	my $word = $words[$i];
	if (!exists $counts{$word}) {
		push @order, $word;
		$counts{$word} = 1;
	} else {
		my $prev = $counts{$word};
		$counts{$word} = $prev + 1;
	}
	$i = $i + 1;
}
print "{";
my $j = 0;
while ($j < scalar @order) {
	if ($j > 0) {
		print ", ";
	}
	my $key = $order[$j];
	print "$key: $counts{$key}";
	$j = $j + 1;
}
print "}\n";

Complexity

  • Time: O(n) average with %counts.
  • Space: O(k) where k is the number of distinct keys.

Implementation notes

  • Perl: my %counts = (); is the idiomatic mutable hash; the exists $counts{$word} predicate plus an explicit assignment keeps the lesson on the read-or-default path without hiding it behind Perl's autovivification (which would create the slot during a read and collapse the branch) or a CPAN helper like Hash::Util.
  • The auxiliary @order array preserves first-seen order so the final printout is deterministic across languages — Perl hash iteration order is randomized per process, so leaning on keys %counts would print different orderings on different runs.
  • The replay renders the map as a list of key/value rows in first-seen order and animates the count increment on each frame.