src/vs/editor/common/languages/supports/richEditBrackets.ts/areOverlapping
function groupFuzzyBrackets(brackets: readonly CharacterPair[]): InternalBracket[] {
	const N = brackets.length;

	brackets = brackets.map(b => [b[0].toLowerCase(), b[1].toLowerCase()]);

	const group: number[] = [];
	for (let i = 0; i < N; i++) {
		group[i] = i;
	}

	const areOverlapping = (a: CharacterPair, b: CharacterPair) => {
		const [aOpen, aClose] = a;
		const [bOpen, bClose] = b;
		return (aOpen === bOpen || aOpen === bClose || aClose === bOpen || aClose === bClose);
	};

	const mergeGroups = (g1: number, g2: number) => {
		const newG = Math.min(g1, g2);
		const oldG = Math.max(g1, g2);
		for (let i = 0; i < N; i++) {
			if (group[i] === oldG) {
				group[i] = newG;
			}
		}
	};

	// group together brackets that have the same open or the same close sequence
	for (let i = 0; i < N; i++) {
		const a = brackets[i];
		for (let j = i + 1; j < N; j++) {
			const b = brackets[j];
			if (areOverlapping(a, b)) {
				mergeGroups(group[i], group[j]);
			}
		}
	}

	const result: InternalBracket[] = [];
	for (let g = 0; g < N; g++) {
		const currentOpen: string[] = [];
		const currentClose: string[] = [];
		for (let i = 0; i < N; i++) {
			if (group[i] === g) {
				const [open, close] = brackets[i];
				currentOpen.push(open);
				currentClose.push(close);
			}
		}
		if (currentOpen.length > 0) {
			result.push({
				open: currentOpen,
				close: currentClose
			});
		}
	}
	return result;
}