String Problems for revision

1. Possible Portmanteau

Given three distinct words, determine if the third word is potentially a portmanteau of the first two.

	A portmanteau (https://en.wikipedia.org/wiki/Portmanteau) is a word that is made by taking the start of one word and the end of another and mashing them together. Brunch is a great example, combining the first 2 letters of "breakfast" with the last 4 of "lunch".

Compound words aren't considered portmanteaus, so "football" is not a portmanteau of "foot" and "ball". At least one of the two words needs to be truncated.
 

linear solution

Pasted image 20250215222028.png

2. Abbr

In the tech world it is becoming common to see abbreviations where a sequence of letters in a string are replaced with a number that represents the length of that sequence. For example, the word "internationalization" is often abbreviated as i18n. The 18 letters in between the 'i' and 'n' are replaced with the count.

A valid abbreviation of this type follows these rules:
- The starting and ending letters remain.
- Replacements must be separated by at least one letter to avoid ambiguity. 18 means eighteen letters were replaced, not 1 letter followed by 8 letters.
- Spaces and hyphens are ignored and not counted in replacements.

Example(s)
Valid abbreviations
  internationalization -> i18n 
  andreessen horowitz -> a16z (the space is ignored)
  the replacements -> the r9ts

Invalid abbreviations
  formation -> f8n (wrong number of letters replaced) 
  the replacements -> the r18ts (the e could be replaced by a 1, followed by the next 8 letters, but this leads to ambiguity. Are 9 letters replaced or 18?)
  internationalization -> 19n (doesn't start with a letter match)
 

Linear time and space solution

function validA10n(original, a10n) {
    // Remove spaces and hyphens from the original string for accurate letter counting
    let cleanedOriginal = "";
    for (let char of original) {
        if (char !== ' ' && char !== '-') {
            cleanedOriginal += char;
        }
    }
    
    // If the abbreviation is just the original word, return true
    if (original === a10n) return true;
    
    // Check if the first and last letters match
    if (a10n[0] !== cleanedOriginal[0] || a10n[a10n.length - 1] !== cleanedOriginal[cleanedOriginal.length - 1]) {
        return false;
    }

    // Extract the parts of the abbreviation
    let letters = [];
    let numbers = [];
    let numStr = "";
    
    for (let i = 1; i < a10n.length - 1; i++) {
        if (a10n[i] >= '0' && a10n[i] <= '9') {
            numStr += a10n[i];
        } else {
            if (numStr) {
                numbers.push(parseInt(numStr, 10));
                numStr = "";
            }
            letters.push(a10n[i]);
        }
    }
    
    // If there was a number left at the end
    if (numStr) {
        numbers.push(parseInt(numStr, 10));
    }
    
    // There should be exactly one numeric part
    if (numbers.length !== 1) {
        return false;
    }

    let replacedLength = numbers[0];
    let expectedReplacedLength = cleanedOriginal.length - 2 - letters.length;
    
    return replacedLength === expectedReplacedLength;
}

// Test cases
console.log(validA10n("internationalization", "i18n")); // true
console.log(validA10n("andreessen horowitz", "a16z")); // true
console.log(validA10n("the replacements", "the r9ts")); // true
console.log(validA10n("formation", "f8n")); // false (wrong number)
console.log(validA10n("the replacements", "the r18ts")); // false (ambiguous replacement)
console.log(validA10n("internationalization", "19n")); // false (does not start with 'i')
console.log(validA10n("the quick brown fox", "t17x")); // true
console.log(validA10n("the quick brown fox", "t5q10x")); // true
console.log(validA10n("the quick brown fox", "t3e14x")); // false (ambiguous)