Задача 6679. Источник: Поляков. Задание КИМ 24
(В. Шубинкин) Текстовый файл 24-268.txt состоит не более чем из 106 символов и содержит только заглавные буквы латинского алфавита и цифры. В файле записаны числа в тридцатеричной системе счисления, окружённые символами, не являющимися цифрами в этой системе счисления или началом/концом файла. Лидирующие нули в записи чисел не допускаются. Определите самую длинную последовательность в этом файле, которая может представлять собой запись числа в тридцатеричной системе счисления, где чётные и нечётные цифры чередуются. Если таких последовательностей несколько, выберите ту, числовое значение которой наименьшее. Например, в последовательности Z12345UABCX11111XX0123456Y98765 есть три тридцатеричных числа с чередующейся чётностью цифр: 12345, ABC, 98765. Наибольшая длина – 5. Наименьшее числовое значение последовательности с такой длиной – 12345.
Алфавит тридцатеричной системы счисления: 0123456789ABCDEFGHIJKLMNOPQRST.
Решение
Более коротким будет решение с использованием метода разделения строк. Заменяем все буквы, не входящие в тридцатеричную систему счисления на какую-то одну и делим строку на подстроки по этой букве. Каждую подстроку анализируем на условие задачи и находим ответ. Анализ строки лучше вынести в отдельную функцию, возвращающую логическое значение.
Python с разделением строки методом split
def good(s):
if len(s) == 0 or s[0] == '0':
return False
d = '0123456789'
for i in range(len(s) - 1):
if ((s[i] in d) == (s[i + 1] in d) and ord(s[i]) % 2 == ord(s[i + 1]) % 2 or
(s[i] in d) != (s[i + 1] in d) and ord(s[i]) % 2 != ord(s[i + 1]) % 2):
return False
return True
s = open('24-268.txt').readline()
for i in 'UVWXY':
s = s.replace(i, 'Z')
mx = ''
for i in s.split('Z'):
if good(i) and (len(i) > len(mx) or len(i) == len(mx) and i < mx):
mx = i
print(mx)
PascalABC с разделением строки методом split
function good(s: String): Boolean;
var
i: Integer;
d: Set of Char;
begin
result := True;
if (s.Length = 0) or (s[1] = '0') then
result := False
else
d := ['0'..'9'];
for i := 1 to s.Length - 1 do
if (((s[i] in d) = (s[i + 1] in d)) and (ord(s[i]) mod 2 = ord(s[i + 1]) mod 2) or
((s[i] in d) <> (s[i + 1] in d)) and (ord(s[i]) mod 2 <> ord(s[i + 1]) mod 2)) then
begin
result := False;
break;
end;
end;
var
i: Integer;
s, mx: String;
ss: Array of String;
c: Char;
f: TEXT;
begin
Assign(f, '24-268.txt');
Reset(f);
Readln(f, s);
for c := 'U' to 'Y' do
s := s.Replace(c, 'Z');
ss := s.Split('Z');
for i := 0 to ss.Length - 1 do
if good(ss[i]) and ((ss[i].Length > mx.Length) or
(ss[i].Length = mx.Length) and (ss[i] < mx)) then
mx := ss[i];
Writeln(mx);
end.
Альтернативным вариантом решения является классический посимвольный анализ. Накапливаем в переменной r строку от одного символа, не входящего в тридцатеричную систему счисления, до другого. Параллельно анализируем, чередуются ли четные и нечетные цифры, отражая это в значении переменной good. Для этого сохраняем предыдущий символ в переменной last. Если оба соседних символа являются цифрами или оба являются буквами, то четность их кодов должна быть различной, а, если один символ является цифрой, а другой - буквой, то их четность должна совпадать. Достигнув разделительного символа, проверяем накопленную строку на соответствие условию задачи и сбрасываем переменные в исходное состояние для поиска следующей строки. Обязательно после цикла следует сделать анализ накопленной строки, т.к. решением может быть последняя подстрока, ограниченная концом файла.
Python с посимвольным анализом
s = open('24-268.txt').readline()
r = ''
mxr = ''
d = '0123456789'
last = ''
good =True
for i in s:
if i > 'T':
if (good and len(r) > 0 and r[0] != '0' and
(len(r) > len(mxr) or len(r) == len(mxr) and r < mxr)):
mxr = r
r = ''
last = ''
good = True
else:
if (last == '' or (i in d) == (last in d) and ord(i) % 2 != ord(last) % 2 or
(i in d) != (last in d) and ord(i) % 2 == ord(last) % 2):
r += i
last = i
else:
good = False
if (good and len(r) > 0 and r[0] != '0' and
(len(r) > len(mxr) or len(r) == len(mxr) and r < mxr)):
mxr = r
print(mxr)
PascalABC с посимвольным анализом
var
i: Integer;
s, r, mxr: String;
last: Char;
good: Boolean;
d: Set of Char;
f: TEXT;
begin
Assign(f, '24-268.txt');
Reset(f);
Readln(f, s);
r := '';
mxr := '';
d := ['0'..'9'];
last := ' ';
good := True;
for i := 1 to s.Length do
if s[i] > 'T' then
begin
if good and (r.Length > 0) and (r[1] <> '0') and
((r.Length > mxr.Length) or (r.Length = mxr.Length) and (r < mxr)) then
mxr := r;
r := '';
last := ' ';
good := True;
end
else
begin
if (last = ' ') or
((s[i] in d) = (last in d)) and (ord(s[i]) mod 2 <> ord(last) mod 2) or
((s[i] in d) <> (last in d)) and (ord(s[i]) mod 2 = ord(last) mod 2) then
begin
r := r + s[i];
last := s[i];
end
else
good := False;
end;
if good and (r.Length > 0) and (r[1] <> '0') and
((r.Length > mxr.Length) or (r.Length = mxr.Length) and (r < mxr)) then
mxr := r;
Writeln(mxr);
end.
C++ с посимвольным анализом
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream f;
f.open("24-268.txt");
string s, r = "", mxr = "", d = "0123456789";
char last = ' ';
bool good = true;
f >> s;
for (int i = 0; i < s.length(); i++)
if (s[i] > 'T')
{
if (good && r.length() > 0 && r[0] != '0' &&
(r.length() > mxr.length() || r.length() == mxr.length() && r < mxr))
mxr = r;
r = "";
last = ' ';
good = true;
}
else
{
if (last == ' ' ||
d.find(s[i]) == d.find(last) && (int)s[i] % 2 != (int)last % 2 ||
d.find(s[i]) != d.find(last) && (int)s[i] % 2 == (int)last % 2)
{
r += s[i];
last = s[i];
}
else
good = false;
}
if (good && r.length() > 0 && r[0] != '0' &&
(r.length() > mxr.length() || r.length() == mxr.length() && r < mxr))
mxr = r;
cout << mxr << endl;
}
Ответ
8NERO9KLST