Реализация вложенного синонимайзера?

Здравствуйте!
С легкостью реализовал синонимайз вида: {Здравствуйте|Привет|Добрый вечер}
Но вот как реализовать вложенный?
Например: {Хай {друг|подруга}|Здаров}
До 5-ти уровней вложенности. Может у кого есть готовые наработки или советы по алгоритму?
  • Вопрос задан
  • 216 просмотров
Пригласить эксперта
Ответы на вопрос 1
prototype_denis
@prototype_denis
Symfony
Сваял на коленке, не тестил. Дорабатывай, оптимизируй... А так, в следующий раз приводи примеры своего кода, а то тут обычно на соседний сайт посылают ))))

Суть проста - это калькулятор, где надо скобочки учитывать.
Идём из глубин в самый верх.

<?php

/**
 * class MagicWord
 */
class MagicWord
{
    /**
     * @param string $string
     */
    public function __invoke($string)
    {
        return $this->process($string);
    }

    /**
     * @param string $string
     * @return string
     * @throw InvalidArgumentException
     */
    private function getPart($string)
    {
        $array  = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
        $start  = 0;
        $end    = count($array);

        for ($i = 0; $i < $end; $i++) {
            if ($array[$i] == '{') {
                $start = $i;
            }
            if ($array[$i] == '}') {
                $end = $i;
                break;
            }
        }

        if ($start > $end) {
            throw \InvalidArgumentException('Bad brackets');
        }

        $words = [];
        for ($i = $start; $i < $end; $i++) {
            if ($array[$i] == '{' || $array[$i] == '}') {
                continue;
            }
            $words[] = $array[$i];
        }

        return join('', $words);
    }

    /**
     * (a|b|c) return b or a or c
     * @param string $string
     * @return string
     */
    private function getRandWord($string)
    {
        $array = explode('|', $string);
        shuffle($array);

        return current($array);
    }

    /**
     * Black magic function )))
     * @return string
     */
    public function process($string)
    {
        if (preg_match('/{/', $string)) {
            $words      = $this->getPart($string);
            $word       = $this->getRandWord($words);
            $string     = str_replace('{'.$words.'}', $word, $string);

            return $this->process($string);
        } else {
            return $string;
        }
    }

    /**
     * Check bracket balance
     * @param string $string
     * @return boolean
     */
    public function checkBalance($string)
    {
        $array      = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
        $balance    = 0;
        foreach($array as $char) {
            if ($char === '{') {
                --$balance;
            }
            if ($char === '}') {
                ++$balance;
            }
        }

        return ! ($balance);
    }
}


$data = '{ Здравствуйте | { Привет { подруга | подружка } | Hello } | Добрый вечер { друг | { подруга | подружка } } }';

$class = new MagicWord();
if ($class->checkBalance($data)) {
    echo $class->process($data);
}

// or
echo $class($data);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы