Как объединить функции поиска в строке символов для дальнейшей логики?

$inputString = '->11гe+20∆∆A+4µcњil->5•Ћ®†Ѓ p+5f-7Ќ¬f pro+10g+1悦ra->58->44m+1*m+2a喜er!';

$keywords = preg_quote($inputString, '/');

//поиск чисел по первому символу >
preg_match_all('/>(\d+)/',$keywords,$output);

$toDelete = 1;

$result2 = count($output[0]);

for ($i=0;$i<$result2;$i++){
    $result1[$i] = substr( $output[0][$i], $toDelete);
}

//print($result1[0]);

//убираем уже примененные символы и меняем символ плюс на другой для исключения ошибки и повторений выборки
$inputString2 = str_replace('->','',$inputString);
$inputString3 = str_replace('+','<',$inputString2);


//поиск чисел по второму символу -
preg_match_all('/-(\d+)/',$inputString3,$output2);

$toDelete = 1;

$result22 = count($output2[0]);

for ($i=0;$i<$result22;$i++){
    $result12[$i] = substr( $output2[0][$i], $toDelete);
}

//print($result12[0]);


//поиск чисел по третьему символу <
preg_match_all('/<(\d+)/',$inputString3,$output3);

$toDelete = 1;

$result23 = count($output3[0]);

for ($i=0;$i<$result23;$i++){
    $result13[$i] = substr( $output3[0][$i], $toDelete);
}

//print($result13[0]);



//



$res = mb_substr($inputString,$result1[0],1);
//$res2 = substr($inputString,11,10);

//print($res);
//print($res2);

$count1 = count($result1);

for ($j=0;$j<$count1;$j++){
    $res[$j] = mb_substr($inputString,$result1[$j],1);
}

print ($res);

как же мне объединить эти функции во одну?

мне нужно в указанной строке

$inputString = '->11гe+20∆∆A+4µcњil->5•Ћ®†Ѓ p+5f-7Ќ¬f pro+10g+1悦ra->58->44m+1*m+2a喜er!';

Начинать чтение нужно с крайнего левого символа и двигаться вправо.

  • Если вы сталкиваетесь с любым символом, кроме специальных обозначений, то данный символ без изменений попадает в результирующую строчку.
  • Специальными обозначениями являются "->", "+", "-". После специального обозначения всегда идет число, являющееся аргументом.
  • "->" — вам необходимо перейти к символу с номером, записанном в аргументе (счет начинается с 0).
  • "+" — пропустить столько символов, сколько записано в аргументе. Отсчет начинается после аргумента.
  • "-" — аналогично, но перемещение происходит назад (влево)

Ответы (1 шт):

Автор решения: teran

Я тут было написал в комментариях, что регулярные выражения не особо подходят для этой задачи, однако, если вспомнить про наличие параметра PREG_OFFSET_CAPTURE, то они весьма помогают в решении задачи. Так что чтобы исправить свой косяк, ниже пример решения данной задачи.

Очевидно, с использованием регулярок нам легко найти все управляющие конструкции в данной строке. Регулярка простая: (->|\+|-)(\d+)/ имеет две группы захвата, первая выбираем команду, вторая аргумент.
Упомянутый выше PREG_OFFSET_CAPTURE позволяет сохранить позицию в строке, на которой было соответствие. Небольшая проблема в том, что это смещение в байтах, а не символах.

Находим соотвествия:

preg_match_all('/(->|\+|-)(\d+)/u', $inputString, $matches, PREG_OFFSET_CAPTURE);

в результате у нас в $matches будут традиционно 3 массива (полный, первая группа, вторая группа). Но сами значения массива это не просто соотвествия, а массив из двух элементов - соответствие и позиция (смещение).

Преобразуем все эти соответствия в удобный нам вид:

$ops = array_map(function($all, $c, $v) use ($inputString){
                    return [
                        'cmd'  => $c[0],
                        'arg'  => $v[0],
                        'pos'  => mb_strlen(substr($inputString,0, $c[1])),
                        'cmdlen' => mb_strlen($all[0]),
                    ];
                }, ...$matches);

    $ops = array_column($ops, null, 'pos');

на выходе получим массив операций (фрагмент):

[6] => Array (              // индекс - позиция        
        [cmd] => +          // команда 
        [arg] => 20         // аргумент 
        [pos] => 6          // позиция  
        [cmdlen] => 3       // длина команды с аргументом
    )

Далее все просто. начиная с нуля, делаем цикл, пока не достигнем конца строки (длины). Смотрим, есть ли текущаия позиция в массиве команд (индекс). Если нашлось, то обрабатываем команду, сдвигаем позицию, так как надо. Если нет, то добавляем символ к результату.

$idx = 0;
$len = mb_strlen($inputString);
$result = "";

while($idx <= $len){
    $op = $ops[$idx] ?? null;

    if($op){
        switch($op['cmd']){
            case '->': $idx =  $op['arg']; break;
            case '-':  $idx -= $op['arg']; break;
            case '+':  $idx += $op['arg'] + $op['cmdlen']; break;
        }
        continue;
    }

    $result .= mb_substr($inputString, $idx++, 1);
}

echo  $result;
→ Ссылка