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}.

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.
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.