powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Поиск последовательности в бинарном массиве
25 сообщений из 270, страница 5 из 11
Поиск последовательности в бинарном массиве
    #39587602
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Извиняюсь, нашёл баг

Время реальное - 0,148925
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587604
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Няшик,

Ранее ты опубликовал 21 лексему. Я уже пилю пример для них.
Запили аналогично

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
type
  TLexeme = (T_UNKNOWN, T_ASSIGN, T_GREATER, T_IS_EQUAL, T_DOUBLE_ARROW, T_SR,
    T_IS_GREATER_OR_EQUAL, T_IF, T_IS_IDENTICAL, T_SR_EQUAL, T_USE, T_VAR, T_LIST,
    T_GOTO, T_ISSET, T_RETURN, T_DIR, T_ENDWHILE, T_PROTECTED, T_ENDSWITCH, T_CLASS_C,
    T_REQUIRE_ONCE);

procedure LexemeFound(const Lexeme: TLexeme);
begin
  Writeln(GetEnumName(TypeInfo(TLexeme), Ord(Lexeme)));
end;

procedure ParseLexemes(const Text: AnsiString);
begin
  // Здесь
end;
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587620
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU, Няшик

вообще то задача найти в тексте позиции содержащие слова из группы заданых строк, а не разложить его на лексемы


например, провести следующие подстановки

'abc' -> '1'
'abe' -> '2'
....

для порядка будем считать, что формально происходит последовательная подмена
Код: pascal
1.
2.
for i in Range(Count) do 
   v := StringReplace(v, Patern[i], Value[i], [rfReplaceAll])
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587621
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan),

Так никто же не спорит
Просто Няшик предлагает деревья, а я предлагаю хеши

И мы рассматриваем частный случай его парсера, где набор искомых строк изначально известен, а значит, его можно захардкодить. Стандартный case по большому счёту и есть частный вид поиска по бинарному дереву
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587623
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,
kealon(Ruslan)вообще то задача найти в тексте позиции содержащие слова из группы заданых строк, а не разложить его на лексемы"разложение на лексемы" куда более примитивная задача
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587624
Bellic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет всем!
Я смотрю выходные даром не проходят - тема Топика переместилась в спор Ассов!?..))

Ну и у меня есть результат - допилил реальную свою процедуру на основе RawByteString и Pos() ...
Для начала скажу, что та же процедура, но с куском кода на разных "платформах", на одних и тех же входных файлах, дала следующие результаты:
- Memory -- 15-17 sec
- TByte -- 92-93 sec
- Raw+Pos -- 3-4 sec
Размер входных файлов:
- Бинарник в котором нужно искать и заменять - 10 Мбайт
- Файл с данными для Поиска и Замены содержащий 357 пар (время на распарсивание его тоже тратится) - 48 Кбайт
Количество произведенных замен - 526

Сам код получился достаточно коротким, но пришлось пошагово выловить несколько ошибок:
=Поиск и Замены на RawByteString + Pos()
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
AddressBin := 1;
while AddressBin <= (SizeBinFile - LenBPoisk + 1) do
   begin // Ищем подстроку
     AdrFind := Pos(RawPoisk, RawBin, AddressBin);
     if AdrFind > 0 then
	begin // Нашли фразу
	   // Копируем RawZamena в RawBin начиная с позиции AdrFind
	   Move(RawZamena[1], RawBin[AdrFind], LenBPoisk);
	   Inc(NumTrans); // Количество произведенных замен
	   // Коррекция на длину фразы, чтоб искать дальше
	   AddressBin := AdrFind + LenBPoisk;
	end
     else if AdrFind=0 then Break;
end;


Ну и пару вопросов по RawByteString :
- если в переменной этого типа уже есть данные, то следующее присваивание новых - выдает не правильный результат, в отличии от Sting?!
Может быть тут есть оператор позицирования?
Или же нужно тоже указывать начальную позицию?
т.е. вместо
Код: pascal
1.
RawPoisk := RawByteString(BPoisk);

писать
Код: pascal
1.
RawPoisk[1] := RawByteString(BPoisk);

???)
(мне пришлось делать RawPoisk=''; и RawZamena=''; )

- при записи в файл указал начало:
Код: pascal
1.
FBin.WriteBuffer(RawBin[1], SizeBinFile);
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587625
Bellic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Конечно же ускорить всю процедуру можно, но для этого потребуется всю ее перелопатить!
Я же сравнивал быстродействие, меняя чисто отдельный блок кода , отвечающий за Поиск и Замену!
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587626
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bellic,

ну чтож, значит с задачей угадали, однозначно Рефал переизобретён
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587627
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bellic,

Выложишь тестовый проект ??? С файлами, с примером что должно получится. И так далее
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587629
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем у меня готова реализация, которую можно назвать демонстрационной
Идея родилась как раз, когда Няшик мучил нас своими простынями нагенерированного кода для парсера
Причём огромная часть токенов имело вид <= >= == $ " >>> + - >>= и прочая штукенция

Сначала я сделал табличное преобразование первого символа. От case уйти не удалось, но зато появилась возможность сделать его последовательным, т.е. на x86 бинарное дерево поменять на jmp [eax * 4 + offset], т.е. сделал некое подобие хеша.

Соответственно и для задачи ТС предлагалось сделать array[Char] для первого символа, чтобы оперативно определять, символ S[i] является первым символом одной из искомых строк или нет. Вообще array[Char] - это частный быстрый вид хеша, его минус расход памяти, поэтому применим не всегда, но для первого символа - самое то.

Так вот, возвращаясь к задаче Няшика, я постоянно настаивал на том, что для скорости компиляции лучше использовать байтовую кодировку (UTF-8, например). Потом возникла мысль, что можно "хешировать" сразу 2 символа, но тогда понадобится 64Кб таблица. А потом возникла мысль, что можно "хешировать" сразу 3 символа, причём это может занять значительно меньше памяти, а все операторные лексемы (типа <= >= ===) будут охвачены, уйдут простыни кода и многочисленные ошибки предсказаний ветвлений. Вот пример.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
type
  TLexeme = (T_UNKNOWN, T_ASSIGN, T_GREATER, T_IS_EQUAL, T_DOUBLE_ARROW, T_SR,
    T_IS_GREATER_OR_EQUAL, T_IF, T_IS_IDENTICAL, T_SR_EQUAL, T_USE, T_VAR, T_LIST,
    T_GOTO, T_ISSET, T_RETURN, T_DIR, T_ENDWHILE, T_PROTECTED, T_ENDSWITCH, T_CLASS_C,
    T_REQUIRE_ONCE);

const
  LEXEME_LENGTH: array[Ord(Low(TLexeme))..Ord(High(TLexeme))] of Byte = (
    1, // :[?]: T_UNKNOWN
    1, // [=]: T_ASSIGN
    1, // [>]: T_GREATER
    2, // [==]: T_IS_EQUAL
    2, // [=>]: T_DOUBLE_ARROW
    2, // [>>]: T_SR
    2, // [>=]: T_IS_GREATER_OR_EQUAL
    2, // [if]: T_IF
    3, // [===]: T_IS_IDENTICAL
    3, // [>>=]: T_SR_EQUAL
    3, // [use]: T_USE
    3, // [var]: T_VAR
    4, // 
    : T_LIST 4, // [goto]: T_GOTO 5, // [isset]: T_ISSET 6, // [return]: T_RETURN 7, // [__DIR__]: T_DIR 8, // [endwhile]: T_ENDWHILE 9, // [protected]: T_PROTECTED 9, // [endswitch]: T_ENDSWITCH 9, // [__CLASS__]: T_CLASS_C 12 // [require_once]: T_REQUIRE_ONCE ); const TEST_CODE = '= > == => >> >= iF === >>= UsE vAr list goto' + 'isset return __DIR__ endwhile protected endswitch __CLASS__ require_once'; procedure LexemeFound(const Lexeme: TLexeme); begin Writeln(GetEnumName(TypeInfo(TLexeme), Ord(Lexeme))); end; procedure ParseLexemes(const Text: AnsiString); label unknown; type HugeByteArray = array[0..High(Integer) - 1] of Byte; var S: ^HugeByteArray; Value: NativeUInt; begin S := Pointer(Text); if (S = nil) then Exit; repeat // spaces, #0 Value := FIRST_CHARS[S[0]]; if (Value <= 1) then repeat Inc(PByte(S)); if (Value = 0{#0}) then Exit; Value := FIRST_CHARS[S[0]]; until (Value > 1); // offset (3 tables) Inc(Value, SECOND_CHARS[S[1]]); Inc(Value, THIRD_CHARS[S[2]]); // Lexeme Value := LEXEME_TABLE[Value]; if (Value >= NativeUInt(T_LIST){4 symbols}) then case Value of // 4, //
      : T_LIST Ord(T_LIST): begin if (S[3] or $20 <> Ord('t')) then goto unknown; end; // 4, // [goto]: T_GOTO Ord(T_GOTO): begin if (S[3] or $20 <> Ord('o')) then goto unknown; end; // 5, // [isset]: T_ISSET Ord(T_ISSET): begin if (S[3] or $20 <> Ord('e')) or (S[4] or $20 <> Ord('t')) then goto unknown; end; // 6, // [return]: T_RETURN Ord(T_RETURN): begin if (S[3] or $20 <> Ord('u')) or (S[4] or $20 <> Ord('r')) or (S[5] or $20 <> Ord('n')) then goto unknown; end; // 7, // [__DIR__]: T_DIR Ord(T_DIR): begin if (S[3] or $20 <> Ord('i')) or (S[4] or $20 <> Ord('r')) or (S[5] <> Ord('_')) or (S[6] <> Ord('_')) then goto unknown; end; // 8, // [endwhile]: T_ENDWHILE | 9, // [endswitch]: T_ENDSWITCH Ord(T_ENDWHILE): begin case (S[3] or $20) of Ord('w'): begin if (S[4] or $20 <> Ord('h')) or (S[5] or $20 <> Ord('i')) or (S[6] or $20 <> Ord('l')) or (S[7] or $20 <> Ord('e')) then goto unknown; end; Ord('s'): begin Value := Ord(T_ENDSWITCH); if (S[4] or $20 <> Ord('w')) or (S[5] or $20 <> Ord('i')) or (S[6] or $20 <> Ord('t')) or (S[7] or $20 <> Ord('c')) or (S[8] or $20 <> Ord('h')) then goto unknown; end; else goto unknown; end; end; // 9, // [protected]: T_PROTECTED Ord(T_PROTECTED): begin if (S[3] or $20 <> Ord('t')) or (S[4] or $20 <> Ord('e')) or (S[5] or $20 <> Ord('c')) or (S[6] or $20 <> Ord('t')) or (S[7] or $20 <> Ord('e')) or (S[8] or $20 <> Ord('d')) then goto unknown; end; // 9, // [__CLASS__]: T_CLASS_C Ord(T_CLASS_C): begin if (S[3] or $20 <> Ord('l')) or (S[4] or $20 <> Ord('a')) or (S[5] or $20 <> Ord('s')) or (S[6] or $20 <> Ord('s')) or (S[7] <> Ord('_')) or (S[8] <> Ord('_')) then goto unknown; end; // 12 // [require_once]: T_REQUIRE_ONCE Ord(T_REQUIRE_ONCE): begin if (S[3] or $20 <> Ord('u')) or (S[4] or $20 <> Ord('i')) or (S[5] or $20 <> Ord('r')) or (S[6] or $20 <> Ord('e')) or (S[7] <> Ord('_')) or (S[8] or $20 <> Ord('o')) or (S[9] or $20 <> Ord('n')) or (S[10] or $20 <> Ord('c')) or (S[11] or $20 <> Ord('e')) then goto unknown; end; else { вообще в данной ситуации никакого else не будет, но для иллюстрации выглядит неплохо } unknown: Value := Ord(T_UNKNOWN); end; // found lexeme LexemeFound(TLexeme(Value)); Inc(PByte(S), LEXEME_LENGTH[Value]); until (False); end;



Вот что на выходе:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
T_ASSIGN
T_GREATER
T_IS_EQUAL
T_DOUBLE_ARROW
T_SR
T_IS_GREATER_OR_EQUAL
T_IF
T_IS_IDENTICAL
T_SR_EQUAL
T_USE
T_VAR
T_LIST
T_GOTO
T_ISSET
T_RETURN
T_DIR
T_ENDWHILE
T_PROTECTED
T_ENDSWITCH
T_CLASS_C
T_REQUIRE_ONCE

Но многобуквенные лексемы я бы как-нибудь приспособил под универсальный компаратор, честно говоря. Это вообще не та ситуация, где нужно использовать кодогенерацию, ИМХО.
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587631
Bellic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, и тут у меня спрашивали - включена ли "Оптимизация"?
Т.к. сравнивать время выполнения начал еще при Выкл., то для чистоты экспериментов - далее ее не включал!

А вот скажите мне пожалуйста - почему она не включена "По умолчанию"?

Кстати - переход в режим Релиза, тоже даст результат, но я пока тестировал все в Дебаге!
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587632
Bellic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SOFT FOR YOU,
Убедительная просьба - заведите пожалуйста для своих споров ОТДЕЛЬНУЮ тему!!!
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587633
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)SOFT FOR YOU,
kealon(Ruslan)вообще то задача найти в тексте позиции содержащие слова из группы заданых строк, а не разложить его на лексемы"разложение на лексемы" куда более примитивная задача

Согласен, что примитивная. Так как можно захардкодить.
Но зачем ты мне это пишешь? Я ещё раз акцентирую твоё внимание - вопрос поиска подходящих вершин по Ахо-Корасику: деревьями или хешем :)
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587634
Bellic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kealon(Ruslan)Bellic,
ну чтож, значит с задачей угадали, однозначно Рефал переизобретён
Не совсем понял о чем речь? - Можно поподробнее?
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587636
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BellicSOFT FOR YOU,
Убедительная просьба - заведите пожалуйста для своих споров ОТДЕЛЬНУЮ тему!!!

В споре рождается истина
Ты просил быстрый поиск нескольких строк или нет?
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587642
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати

Здесь была интересная ветка про StringReplace, но её, похоже затёрли.
Так вот основная проблема StringReplace с множеством вхождений - в реаллоке памяти. Особенно, если речь идёт о нескольких мегабайтах.

Решение следующее. Мы анализируем всю строку и создаём массив структур вида <Указатель, Длина>, где Указатель это либо часть исходной строки, либо заменяемая строка.

Таким образом, когда анализ исходной строки заканчивается - мы имеем полное представление о результате. Сначала подсчитываем результирующую длину, выделяем требуемое количество памяти, потом последовательно заполняем результат нашими "кусками данных".

Там проблема была в том, где хранить массив структур <Указатель, Длина>. В качестве решения был базовый массив на стеке, а при нехватке дополнительно выделялись буферы в куче. На практике всегда хватает стека, но для общего случая реализация тоже подходит.
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587647
Bellic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
НяшикВыложишь тестовый проект ??? С файлами, с примером что должно получится. И так далее
А история то начиналась еще с Мемори вот в этом Топике:
Поиск и Замена последовательности байт в бинарном файле
До этого была жуткая по времени (24 часа) реальная процедура на реальных файлах - на TFileStream , позже выделенный желтым участок кода был переделан на TByte , а сейчас вот на RawByteString ...)))
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587654
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

А почему код не полны ? Сам меня тыкал выложить полный. А сам свой не выложил.

Кстати, у меня UTF8 может обрабатывать, а твой только AnsiString. Как то немного не честно будет..
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587656
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Няшик,

Ну во-первых, тут без разницы. Можно хоть PAnsiChar указывать с нулём на конце. Во-вторых, ты свой тест так и не выложил, чтобы сравнить. В-третьих, что не хватило для компиляции?
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587660
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUНяшик,

Ну во-первых, тут без разницы. Можно хоть PAnsiChar указывать с нулём на конце. Во-вторых, ты свой тест так и не выложил, чтобы сравнить. В-третьих, что не хватило для компиляции?

Как не выложил?

21123284

Не хватает THIRD_CHARS и THIRD_CHARS
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587662
Bellic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Няшик , SOFT FOR YOU , я Вам не мешаю???..)))
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587664
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bellic Няшик , SOFT FOR YOU , я Вам не мешаю???..)))

Нет, ты не большой. Можешь не волноваться
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587688
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НяшикSOFT FOR YOUНяшик,

Ну во-первых, тут без разницы. Можно хоть PAnsiChar указывать с нулём на конце. Во-вторых, ты свой тест так и не выложил, чтобы сравнить. В-третьих, что не хватило для компиляции?

Как не выложил?

21123284

Не хватает THIRD_CHARS и THIRD_CHARS

Я же тебе чёрным по белому написал. Выложи код для 21 токена и байтовой кодировки: 21123290
А таблички я генерю, завтра выложу
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587689
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bellic Няшик , SOFT FOR YOU , я Вам не мешаю???..)))

Мы обсуждаем твою тему. Что тебя не устраивает?
...
Рейтинг: 0 / 0
Поиск последовательности в бинарном массиве
    #39587713
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUКстати

Здесь была интересная ветка про StringReplace, но её, похоже затёрли.
Так вот основная проблема StringReplace с множеством вхождений - в реаллоке памяти. Особенно, если речь идёт о нескольких мегабайтах.

Решение следующее. Мы анализируем всю строку и создаём массив структур вида <Указатель, Длина>, где Указатель это либо часть исходной строки, либо заменяемая строка.

Таким образом, когда анализ исходной строки заканчивается - мы имеем полное представление о результате. Сначала подсчитываем результирующую длину, выделяем требуемое количество памяти, потом последовательно заполняем результат нашими "кусками данных".

Там проблема была в том, где хранить массив структур <Указатель, Длина>. В качестве решения был базовый массив на стеке, а при нехватке дополнительно выделялись буферы в куче. На практике всегда хватает стека, но для общего случая реализация тоже подходит.Зачем так сложно?
Выдели изначально памяти с запасом, потом урежешь. Вот и все.
...
Рейтинг: 0 / 0
25 сообщений из 270, страница 5 из 11
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Поиск последовательности в бинарном массиве
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]