🟨 JavaScript
Средняя
🕐 15 мин

Сжатие строки (Run-Length Encoding)

Цель: реализовать алгоритм сжатия строки, который эффективно группирует последовательности одинаковых символов.

💡 Подсказка к решению

Есть два популярных подхода к решению этой задачи:

  1. Итеративный подход (цикл for):

    • Итерируйте по строке, отслеживая текущий символ и его количество.
    • Если следующий символ отличается от текущего (или строка закончилась), добавьте к результату текущий символ и его количество (если оно больше 1).
    • Сбросьте счетчик и продолжайте.
  2. С помощью регулярных выражений:

    • Можно использовать регулярное выражение, чтобы найти все последовательности одинаковых символов.
    • Выражение /(.)\1*/g отлично подходит: (.) захватывает любой символ, а \1* ищет его повторения.
    • Используйте метод replace с функцией обратного вызова для форматирования результата.
👀 Решение №1 (Цикл for)
const compressString = (str) => {
  // Если строка пустая, нет смысла продолжать. Возвращаем пустую строку.
  if (!str) {
    return '';
  }
 
  // `result` будет хранить нашу сжатую строку.
  let result = '';
  // `count` отслеживает количество повторений текущего символа.
  let count = 1;
 
  // Итерируем по строке с помощью цикла for.
  for (let i = 0; i < str.length; i++) {
    // Заглядываем вперед: сравниваем текущий символ (str[i]) со следующим (str[i + 1]).
    // Если они совпадают, значит, последовательность продолжается.
    if (str[i] === str[i + 1]) {
      // Просто увеличиваем счетчик и переходим к следующей итерации.
      count++;
    } else {
      // Если следующий символ другой или это конец строки,
      // значит, последовательность текущего символа прервалась.
 
      // Добавляем к результату сам символ.
      // Затем проверяем счетчик: если он больше 1, добавляем и его.
      // Если счетчик равен 1, ничего не добавляем, согласно условию.
      result += str[i] + (count > 1 ? count : '');
      
      // Сбрасываем счетчик до 1 для следующей последовательности символов.
      count = 1;
    }
  }
 
  // Возвращаем итоговую сжатую строку.
  return result;
};

Анализ решения:

  • Плюсы:

    • Прозрачность: Код легко читается и понимается, так как логика реализована пошагово.
    • Производительность: Обычно это самый быстрый подход, так как он избегает накладных расходов на создание и компиляцию регулярных выражений.
    • Контроль: Полный контроль над процессом итерации и обработки.
  • Минусы:

    • Многословность: Требует больше кода по сравнению с регулярными выражениями.
    • Управление состоянием: Нужно вручную управлять переменными result и count.
👀 Решение №2 (Регулярные выражения)
const compressString = (str) => {
  // Простая проверка на пустую строку.
  if (!str) {
    return '';
  }
 
  // Используем метод `replace` с регулярным выражением.
  // Регулярное выражение /(.)\1*/g находит все последовательности
  // одинаковых символов в строке.
  // ( . ) - Захватывает любой одиночный символ (кроме новой строки) в группу.
  // \1*   - Ищет ноль или более повторений того, что было захвачено в первой группе.
  // g     - Глобальный флаг, чтобы найти все совпадения, а не только первое.
  return str.replace(/(.)\1*/g, (match, char) => {
    // `replace` вызывает эту callback-функцию для каждого найденного совпадения.
    // `match` - это вся найденная последовательность (например, "AAAA").
    // `char` - это символ, захваченный первой группой (например, "A").
 
    // Если длина найденной последовательности больше 1,
    // возвращаем символ + его длину.
    // В противном случае (если длина 1), возвращаем только сам символ.
    return match.length > 1 ? char + match.length : char;
  });
};

Анализ решения:

  • Плюсы:

    • Краткость: Решение очень лаконичное и элегантное.
    • Декларативность: Вы описываете что нужно найти (шаблон), а не как это сделать (итерация).
  • Минусы:

    • Читаемость: Может быть сложным для понимания, если вы не знакомы с регулярными выражениями.
    • Производительность: На очень больших строках может работать медленнее, чем цикл, из-за сложности движка регулярных выражений. Однако для большинства случаев разница будет незначительной.

Описание задачи

Вам нужно создать функцию compressString, которая выполняет базовое сжатие строки с использованием алгоритма Run-Length Encoding (RLE).

Правила сжатия:

  1. Если последовательность состоит из одного символа, он остается без изменений.
  2. Если символ повторяется в последовательности несколько раз, он заменяется на сам символ, за которым следует количество его повторений.

Примеры

// 'AAA' -> 'A3', 'B' -> 'B', 'CC' -> 'C2'
compressString('AAABCC'); // "A3BC2"
 
// Нет последовательных повторений
compressString('ABC'); // "ABC"
 
// Длинная последовательность
compressString('WWWWWWWWWWWW'); // "W12"
 
// Пустая строка
compressString(''); // ""

Требования

  • Функция должна называться compressString.
  • Функция должна корректно обрабатывать пустые строки.
  • Функция должна быть чувствительна к регистру ('a' и 'A' — разные символы).

🧑‍💻 Это не баг! Это фича!

Редактор кода намеренно скрыт на мобильном.

Поверь, так лучше: я оберегаю тебя от искушения писать код в неидеальных условиях. Маленький экран и виртуальная клавиатура — не лучшие помощники для программиста.

📖 Сейчас: Изучи задачу, продумай решение. Действуй как стратег.

💻 Потом: Сядь за компьютер, открой сайт и реализуй все идеи с комфортом. Действуй как код-джедай!