Поиск последовательности одинаковых элементов массива не зная точно этих элементов

Файл прочитан побайтово и переведён в массив. Элементов массива много, каждый элемент string, несколько сотен тысяч. Элементами массива являются числа от 00 до FF(шестнадцатиричная система исчисления). Т.е. вот что я имею на руках:
$massiv = array(«00», «20», «07», «AD», «60», «20», «FE», «12», «20» и т.д.);
Задача: найти в массиве последовательность элементов массива, когда я не знаю значение этих элементов, но точно знаю что: какой-то один элемент(например «20» из примера выше) повторяется сначала через три других элемента(«07», «AD», «60» из примера выше), а потом повторяется через 2 других элемента(«FE», «12» из примера выше).
Т.е. в идеале я буду функцией получать номер элемента массива, с которого начинается последовательность, которую я ищу.
Уже два года мечтаю о таком скрипте))

 

Если это не массив а строка, то можно использовать регулярное выражение. Символ для подстановки в выражение можно получить из HEX с помощью функции chr:

PHP:
  1. $char = chr(0x20);
 

Так если они должны повторяться по системе, то даже однопроходный алгоритм получается, элементарный. Идти по порядку по массиву, и смотреть

PHP:
  1. if ($massiv[$i] == $massiv[$i +3] && $massiv[$i] == $massiv[$i + 5])

Что-то такое, если я на ночь глядя с цифрами не ошибся.

 

Всё здорово, получилось. Только каждое условие в отдельных скобках должно быть. И ещё и $i+4 && $i+7, т.к. текущая итерация

 

Незачем переводить байты в массив строк. В PHP есть прекрасная функция count_chars, которая за один вызов может посчитать сколько раз встретился каждый символ.
Например вот такой код

PHP:
  1. $source = «a\x12\xB0.L-dc.\xB0_h.»;
  2. $counts = count_count($source);
  3. var_export($counts);

выведет такой результат:

Код (Text):
  1. array (
  2.   18 => 1,
  3.   45 => 1,
  4.   46 => 3,
  5.   76 => 1,
  6.   95 => 1,
  7.   97 => 1,
  8.   99 => 1,
  9.   100 => 1,
  10.   104 => 1,
  11.   176 => 2,
  12. )

если надо найти с какой позиции начинаются эти серии байтов, то добавь strpos()

PHP:
  1. <?php
  2. $source = «a\x12\xB0.L-dc.\xB0_h.»;
  3. $counts = count_chars($source, 1);
  4. $sequences = array_map(
  5.   fn ($i) => sprintf(‘The byte 0x%02X appears %d time(s), starting from position %d’, $i, $counts[$i], strpos($source, chr($i))),
  6.   array_keys($counts)
  7. );
  8. echo implode(«\n«, $sequences);

The byte 0x12 appears 1 time(s), starting from position 1

 

Или так:

PHP:
  1. <?php
  2. $source = «\x07\x00\x20\x07\xAD\x60\x20\xFE\x12\x20«;
  3. $counts = count_chars($source, 1);
  4. $sequences = [];
  5. foreach (array_keys($counts) as $i) {
  6.   $positions = [];
  7.   for ($j = 0, $p = 1; $j < $counts[$i]; $j++) {
  8.     $p = strpos($source, chr($i), $p + 1);
  9.     $positions[] = $p;
  10.   }
  11.   $sequences[] = sprintf(‘The byte 0x%02X appears %d times: at %s’, $i, $counts[$i], implode(‘, ‘, $positions));
  12. }
  13. echo implode(«\n«, $sequences);
Код (Text):
  1.  
  2. The byte 0x00 appears 1 times: at 1
  3. The byte 0x07 appears 2 times: at 0, 3
  4. The byte 0x12 appears 1 times: at 8
  5. The byte 0x20 appears 3 times: at 2, 6, 9
  6. The byte 0x60 appears 1 times: at 5
  7. The byte 0xAD appears 1 times: at 4
  8. The byte 0xFE appears 1 times: at 7
 

@artoodetoo Ему же надо проверить повторение по системе (когда первое повторение через 3 байта, а второе — через 5). Хотя да, можно и просто со строкой это сделать

 

я понимаю Поиск последовательности одинаковых элементов массива
как поиск последовательности одинаковых элементов массива )) но возможно я не прав
— Добавлено —
но даже если конечная цель это нахождение известных паттернов в размещении, то скрипт мог бы проделать эту предварительную работу. будет всего навсего <= 256 цепочек для анализа
— Добавлено —
сразу после count_count() можно отбросить заведомо неподходящие варианты и сканировать остальные.

 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *