function compressString(str) {
	let currChar = str[0],
		currCharCount = 0
	const compressed = [] //Don't concat to string because string concatenation operates in O(n^2) time

	for (const char of str) {
		if (char === currChar) currCharCount++
		else {
			compressed.push(currChar, currCharCount)
			currCharCount = 1
			currChar = char
		}
	}

	compressed.push(currChar, currCharCount)

	const compressedStr = compressed.join('')

	return compressedStr.length < str.length ? compressedStr : str
}

/*
n = length of string
Time Complexity - O(n)
Space complexity - O(n)
*/

/* ---------------------------------------------------------------------------- */

// Optimized. Referenced from book.

function compress(str) {
	const finalLen = countCompression(str),
		strLen = str.length
	if (finalLen >= strLen) return str

	let compressed = [],
		currCharCount = 0

	for (let i = 0; i < strLen; i++) {
		currCharCount++

		if (i + 1 >= strLen || str[i] !== str[i + 1]) {
			compressed.push(str[i], currCharCount)
			currCharCount = 0
		}
	}
	return compressed.join('')
}

function countCompression(str) {
	let compressedLen = 0,
		currCharCount = 0

	for (let i = 0; i < str.length; i++) {
		currCharCount++
		if (i + 1 >= str.length || str[i] !== str[i + 1]) {
			compressedLen += 1 + currCharCount.toString().length
			currCharCount = 0
		}
	}
	return compressedLen
}

// tests
const testCases = [
	['aabcccccaaa', 'a2b1c5a3'],
	['a', 'a'],
	['aaaaaaaaaa', 'a10'],
]

for (const test of testCases) {
	const result = compressString(test[0]),
		result1 = compress(test[0])
	console.log(result === test[1], test[0], result, 'compressString')
	console.log(result1 === test[1], test[0], result1, 'compress')
}