You're planning a heist on a cul-de-sac where the houses sit around a loop — the last house's backyard touches the first house's. Each house holds some loot, and any two houses next to each other share an alarm, so robbing both gets you caught. Because the street wraps, the first and last houses count as neighbours too. Given the loot in each house, return the largest total you can take without ever robbing two adjacent houses. This is the classic House Robber II problem.
// houses: array of non-negative numbers, arranged in a CIRCLE
// (houses[0] and houses[n-1] are adjacent).
// returns: the maximum total loot with no two adjacent houses robbed.
function neighborhoodTheftCircular(houses: number[]): number;
neighborhoodTheftCircular([2, 3, 2]); // → 3
// Houses 0 and 2 both hold 2, but they're adjacent on the loop,
// so you can't take both. The lone middle house (3) wins.
neighborhoodTheftCircular([1, 2, 3, 1]); // → 4
// Rob house 0 (1) and house 2 (3) → 4. They aren't adjacent,
// and neither is a wrap-around neighbour of the other.
houses[0] and houses[n - 1] are neighbours. You can rob at most one of them.[] returns 0 (nothing to steal).[v] returns v. A lone house has no neighbours at all, so it's always safe to rob.[a, b] returns max(a, b). On a ring of two, the houses are neighbours both ways, so you take only the richer one.≥ 0; you never lose money by robbing a house.