Дана случайная последовательность открывающих и закрывающих скобок. Требуется определить, сколько открывающих скобок нужно дописать перед последовательностью, и сколько закрывающих скобок - после, чтобы получилось правильное скобочное выражение. Результат работы программы может выглядеть так: Код (Text): }}{}{{{ 2 3
Это нужно граф(дерево) обойти. Выполняется множество проходов и на каждом сокращаются "()" элементы, это если без таблиц, например: ((()())())((()())(()()))())())())) (())(()()))))) ()())))) )))) << Фейл!
Clerk Я прошу прощения, но Вы зациклились на графах. Это задача уровня первых трёх пар информатики: один цикл прохода по строке/массиву с условием. +1 к Rockphorr.
l_inc и мало того. задача решается обычным принципом стека. ... Эх... Строить танк, чтобы вспахать огород, это сильно.
l_inc И как вы за один цикл определите валидность расположения всех скобок, по мойму это не возможно, если конечно не запоминать их гдето в буфере ? Можно либо выполнить множество проходов про массиву(уже боюсь сказать графу..) либо удалять скобки от так скажем затравки с обеих сторон.
Код (Text): esi - указатель на массив скобок xor ecx,ecx xor edx,edx jmp start M2: inc edx start: lodsb cmp al,0 je exit cmp al,'}' je M1 cmp al,'{' jne start inc ecx jmp start M1: jecxz M2 dec ecx jmp start exit: ecx - с права edx - с лева
графы, стёки, "не возможно", гы! Код (Text): do c+=(*x=='{')-(*x=='}'); while(*++x); printf("%d unmatched brackets left",c); нет ты!
мм, комер как обычно нифига не прочитал, но уже ответил - моя киса на эту тему вечно стебётся) но ничего страшного, остаётся всего лишь проверку на отрицательное c воткнуть в цикл.
Хм точна. Когдато я трахался с интерпретатором васика и там было великогеморно выполнить такой анализ выражений. Тут просто выражение не смысловое и любая закрывающаяся кавычка завершает выражение. Наверно я схожу с ума %.
проверка, при том, даже с нуля начинается: Код (Text): char*x=")((()())())((()())(()()))())())()))"; int c[2]={0}; do{ if(*x=='(') c[0]++; if(*x==')') c[(!c[0])]--; }while(*++x); printf("pew-pew!1 %d:%d",+c[0],-c[1]);
FLASH300 работает Com[e]r работает, особенно понравилось c[(!c[0])]--; Clerk задача решается одним проходом по строке, но вариант с деревьями интересный
а вот и вариант с деревьями (C#): Код (Text): string s = Console.ReadLine(); string s2; do { s2 = s; s = s.Replace("{}", ""); } while (s.Length != s2.Length); Console.WriteLine("{0} {1}", s.Count<char>(c => c == '}'), s.Count<char>(c => c == '{') );
Я тут заметил, что последняя программа выполняется не очень быстро. Для случайной последовательности скобок длиной 10 млн время выполнения составляет около 1 сек. Поэтому я написал параллельную версию: Код (Text): string s = random_brackets(10000000); int N = Environment.ProcessorCount; string[] Q = new string[N]; int L = s.Length / N; int Rem = s.Length % N; for (int i = 0; i < N; i++) Q[i] = s.Substring(i * L, (i == N - 1) ? L+Rem : L); Action<int> A = new Action<int>((i) => { string ss; do { ss = Q[i]; Q[i] = Q[i].Replace("{}", ""); } while (ss.Length != Q[i].Length); } ); Parallel.For(0, N, A); Q[0] = Q.Aggregate((string a, string b) => a + b); A(0); Console.WriteLine("{0} {1}", Q[0].Count<char>(c => c == '}'), Q[0].Count<char>(c => c == '{') ); У меня на машине с двухъядерным процессором время выполнения 500-550 мсек.
А вот интересный вопрос: можно ли распараллелить однопроходной алгоритм? То есть мы разбиваем исходную строку на N подстрок, для каждой подстроки вычисляем пару (L1,R1) и... что дальше? Можно ли из полученных пар рассчитать суммарную пару? Например: }}{{ + }{{{ получаем 2 2 1 3 итоговая пара должна быть 2 4
что за глупый вопрос, конечно можно) a0 b0 a1 b1 ... an bn первое число - a0 + (a1 - b0) + ... + (an - b(n-1)) второе аналогично
n0name Это не совсем верно. Нужно различать, является положительным или отрицательным. В случае отрицательного прибавлять абсолютное значение к bn для второго числа, а не к a0 для первого. Второе аналогично.