stvn1337 Ответов: 2

Взорвать шаблон в C#


Как я могу взорвать шаблон в c#. Используя заданный вход и выводя заданный результат с помощью рекурсии.

The code here is unfinished because I had second thoughts about my logic. The idea is to walk through each character and decide if it was a number, or open or close parenthesis and save that information into a string, using the number to repeat what is in the parenthesis. and alowing for iteration in the event that another statement is inside the parenthesis.

For example :
2(ab)16(cd)3(a4(bc)d)

would equate to :
ABABCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDABCBCBCBCDABCBCBCBCDABCBCBCBCD


Что я уже пробовал:

static string ExplodeString(string holder)
        {

            bool firstRun = true;
            int c = 0;
            string holderStr = "";
            int numOpen = 0;
            int numClose = 0;
            string numBuilder = "";
            int rptNum = 0;
            string holderTmp = "";
            int numOpenBraces = 0;
            string finalStr = "";
            int numCloseBraces = 0;

            if (holder.Contains("("))
            {

                int num = 4; //buffer number of chars to process for first parenthese
                while (num >0 || numOpen > numClose)
                {
                    
                    if (char.IsNumber(holder[c]) && numOpen == 0)
                    {
                        numBuilder += holder[c];
                        int.TryParse(numBuilder, out rptNum);
                        Console.WriteLine(numBuilder);
                    }
                    else if (holder[c].Equals('('))
                    {
                        Console.WriteLine("Open found!");
                        numOpen++;
                        if (numOpen > 1)
                        {
                            holderStr += holder[c];
                        }
                    }
                    else if (holder[c].Equals(')'))
                    {
                        Console.WriteLine("Close found!");
                        numClose++;
                        if (numOpen > 1)
                        {
                            holderStr += holder[c];
                        }
                    }
                    else
                    {
                        Console.WriteLine("Building string...");
                        holderStr += holder[c];
                    }
                    c++;
                    num--;
                }
                
                finalStr = String.Concat(Enumerable.Repeat(holderStr,rptNum));
                Console.WriteLine(finalStr);
                while (finalStr.Contains('('))
                {
                    finalStr = ExplodeString(finalStr);
                }
            }
            Console.WriteLine(finalStr);
            return finalStr;
        }

Patrice T

В чем же вопрос?

stvn1337

Как я могу взорваться, сказал шаблон имто результата с помощью итераций в C#

Patrice T

Воспользуйся Улучшить вопрос чтобы обновить ваш вопрос.
Чтобы каждый мог обратить внимание на эту информацию.

BillWoodruff

Вы создали формат, в котором находится строка ? Это что, домашнее задание ? Знакомы ли вы с рекурсией или с использованием стековой структуры для ее реализации ?

stvn1337

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

stvn1337

Кроме того, это некоммерческий проект.

BillWoodruff

Привет, Не волнуйся, здесь много людей задают вопросы о текущей коммерческой работе.

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

Примеры таких парсеров есть здесь и на StackOverFlow.

stvn1337

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

Richard MacCutchan

Это просто вопрос разбора каждого выражения. Захватывайте все символы, пока не встретите открытую скобку; это и есть счет. Затем захватите все символы, пока не встретите близкую скобку; это последовательность символов. Учитывая эти два поля, генерировать последовательности очень просто. Затем вы переходите к следующему выражению, пока не дойдете до конца текста.

BillWoodruff

Привет, Ричард, имхо, рекурсия, необходимая здесь, делает его более сложным.

Richard MacCutchan

Верно, но основная идея все та же.

Maciej Los

Проверьте это для синтаксического анализа выражений: Механизм вычислений для .NET.

2 Ответов

Рейтинг:
16

Richard Deeming

Вероятно, есть более эффективное решение, но оно работает с предоставленными входными данными:

static string ExplodeString(string value)
{
    // Matches a repeated block which does not have a nested repeated block:
    Regex pattern = new Regex(@"(?<number>\d+)\((?<text>[^()]+)\)", RegexOptions.ExplicitCapture);
    
    while (pattern.IsMatch(value))
    {
        value = pattern.Replace(value, match =>
        {
            int number = int.Parse(match.Groups["number"].Value);
            string text = match.Groups["text"].Value;
            return string.Concat(Enumerable.Repeat(text, number));
        });
    }
    
    return value;
}

// ExplodeString("2(ab)16(cd)3(a4(bc)d)")
// => "ababcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdabcbcbcbcdabcbcbcbcdabcbcbcbcd"

Куда он упадет, так это если повторяющийся текст может содержать круглые скобки. Например, 2(ab(c)) не будет расширяться. Из вопроса не ясно, возможно ли это.


Maciej Los

Я тоже думал о регулярном выражении...
5ed!

Richard Deeming

Я думал, что это должно быть возможно сделать что-то с балансирующими группами, но я не мог заставить это работать.

Maciej Los

Забудьте о балансировке групп! :смех: это потрясающее решение!

stvn1337

Это идеальное решение! Спасибо за ваш ответ. Потрясающая работа с регулярным выражением, я никогда бы не подумал сделать это таким образом.

Рейтинг:
0

Patrice T

[Обновление]
Мы можем помочь вам исправить ваш код, но вам нужно показать нам готовый (завершенный) фрагмент кода.
Если вы попросите 5 программистов написать код для этой задачи, вы получите 6 программ. Это означает, что нет единого решения, их много, некоторые рекурсивные, некоторые просто циклические, некоторые регулярные выражения ...
Вот почему вам нужно показать свой код. Без готового кода я могу дать только некоторые общие советы.
-----

Цитата:
Код здесь незакончен, потому что я передумал насчет своей логики.

Не останавливайся из-за этого. Есть только один способ узнать, работает ваша идея или нет: дайте ей попробовать.
Будучи учеником, вы также узнаете, что работает, а что нет, практикуя, поэтому вы можете извлечь выгоду из неправильной идеи.
Совет: если проблема кажется вам слишком сложной, попробуйте решить упрощенную задачу.
Во - первых, попробуйте решить задачу без вложенности, как только вы познакомитесь с упрощенной задачей, добавление вложенности не будет очень сложным.

Ваша проблема заключается в изменении сжатия RLE: Кодировка длины пробега - Википедия[^]

-----
Изучите один или несколько методов анализа, У. Е. сверху вниз Djikstra способ это хорошее начало, оно поможет вам организовать ваши идеи.
https://en.wikipedia.org/wiki/Top-down_and_bottom-up_design[^]
https://en.wikipedia.org/wiki/Structured_programming[^]
https://en.wikipedia.org/wiki/Edsger_W._Dijkstra[^]
https://www.cs.utexas.edu/users/EWD/ewd03xx/EWD316.PDF[^]

-----
Когда ваш код ведет себя не так, как вы ожидаете, и вы не понимаете почему !
Существует почти универсальное решение: запускайте свой код на отладчике шаг за шагом, проверяйте переменные.
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не знает, что вы должны делать, он не находит ошибок, он просто помогает вам, показывая, что происходит. Когда код не делает того, что ожидается, вы близки к ошибке.
Чтобы увидеть, что делает ваш код: просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.

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

Вторичное воздействие
- Вы будете гордиться тем, что сами находите Жуков.
- Ваши навыки обучения улучшатся.

Вы должны довольно быстро найти, что не так.

Отладчик - Википедия, свободная энциклопедия[^]
Отладка кода C# в Visual Studio - YouTube[^]
Отладчик здесь только для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.

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


BillWoodruff

Мой голос за № 1. Этот бред имеет мало общего с конкретным вопросом ОП.

RLE не требует рекурсивного синтаксического анализа: это делает проблема OP.

Patrice T

С незаконченным фрагментом кода трудно давать исправления к этому коду, поэтому только советы.
RLE: вот почему я использовал слово "variating" (может быть, это неправильное слово в английском, во французском я хотел использовать слова "variante" или "variation").

Я думаю, что ОП достиг той точки, когда метод анализа будет полезен, и отладчик тоже будет полезен.

Richard MacCutchan

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

Patrice T

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

BillWoodruff

С этой "логикой" вы можете включить рецепт куриного супа вашей матери в свой пост.

Patrice T

Дорогой Билл,
Похоже, все недовольны моим ответом, но пока это лучший ответ, потому что больше никто не ответил.
Вы, кажется, знаете, что делает ответ хорошим или плохим, я хотел бы видеть ваш хороший ответ на этот вопрос.

Richard MacCutchan

Нет, это не самый лучший ответ. Это ваш стандартный ответ, который на самом деле не помогает вопрошающему.