Алгоритм смотрит на запись числа N, выбирает одну из
двух веток и достраивает запись. Получается R.
Решаем программой: разобрать правило, перевести его в цикл, забрать
ответ.
Базовый уровень, один балл. Ответ — одно целое число.
Строится двоичная запись N. Дальше:
Полученная запись — это R в двоичной системе.
Возьмём N = 13.
11011 + 1101 + 00 =
111010011101002 = 116Ветку выбирает N, а не R: здесь N нечётное, а R = 116 чётное.
В любом варианте условие устроено одинаково. Меняются три вещи — их и надо выписать первыми, ещё до кода.
| Что меняется | Что бывает (по 13 разобранным вариантам) |
|---|---|
| система записи | двоичная (9 задач), троичная (4) |
| признак ветвления | чётность самого N; чётность суммы цифр записи; делимость N на 3 |
| что делает ветка | дописать цифры слева или справа; дописать цифру и заменить два левых разряда; дописать последние цифры самой записи; сосчитать число (остаток или сумму цифр), умножить, перевести и дописать |
Первая проверка — примеры из условия. Их всегда два, по одному на ветку. Написали программу — прогоните её на обоих. Сошлось — правило прочитано верно. Не сошлось — искать ошибку здесь, а не в ответе.
s = f'{n:b}' # короткий способ
s = bin(n)[2:] # bin даёт '0b1101',
# срез убирает приставку
Оба дают строку — это важно: дописывать цифры мы будем склейкой строк.
def to3(n):
s = ''
while n > 0:
s = str(n % 3) + s
n = n // 3
return s
Остаток от деления — очередная цифра, и приписывается она слева. Готовой функции для троичной записи нет, поэтому это подпрограмма: написали один раз — зовём сколько угодно.
Обратно — int(s, 2) и int(s, 3):
строка и основание.
for n in range(1, 1001):
s = f'{n:b}'
if n % 2 == 0:
t = '11' + s + '11'
else:
t = '1' + s + '00'
r = int(t, 2)
#print(n, s, t, r)
if;if и else;int(t, 2).Дальше остаётся одна строка отбора — та, что зависит от вопроса. Каркас во всех задачах один и тот же.
А закомментированная строка #print(n, s, t, r) —
не украшение. С неё начинается работа: следующий слайд.
«…к записи справа дописываются её три последние двоичные цифры»
t = s + s[-3:]
s[-3:] — срез от третьего знака с конца до конца:
последние три цифры записи.
| N | s | t | R |
|---|---|---|---|
| 6 | 110 | 110110 | 54 |
«…справа дописывается 0, а затем два левых разряда заменяются на 10» (на другой ветке — 1 и 11)
if ds(s) % 2 == 0:
t = '10' + (s + '0')[2:]
else:
t = '11' + (s + '1')[2:]
Сначала дописать, потом заменить. [2:]
отрезает два левых знака, спереди встают новые.
| N | s | дописали | t | R |
|---|---|---|---|---|
| 6 | 110 | 1000 | 8 | |
| 4 | 100 | 1101 | 13 |
Обе ветки будут в каждой работе — и в практикуме, и в домашней, и в проверочной.
Строка отбора пока не написана: сперва печатаем след цикла и сверяем с примером из условия.
for n in range(1, 101): # пока немного
s = f'{n:b}'
if n % 2 == 0:
t = '11' + s + '11'
else:
t = '1' + s + '00'
r = int(t, 2)
print(n, s, t, r)
Печатаем все четыре величины: число, его запись, достроенную запись и результат.
Строки следа на экране:
| n | s | t | r |
|---|---|---|---|
| 2 | 10 | 111011 | 59 |
| 3 | 11 | 11100 | 28 |
| 4 | 100 | 1110011 | 115 |
| 5 | 101 | 110100 | 52 |
| 6 | 110 | 1111011 | 123 |
| … | |||
| 13 | 1101 | 1110100 | 116 |
Сверять надо обе ветки. Примеров в условии всегда два — по одному на ветку: 6 → 123 (а) и 13 → 116 (б). Обе строки в следе совпали. Одного примера мало: ошибка в другой ветке им не ловится.
Столбцы показывают, на каком шаге разошлось: s — перевод,
t — достройка, r — обратный перевод. Чужое число в
t — перепутаны ветки или сторона приписывания; чужое в
r — не то основание в int(t, 2).
Искать ошибку здесь, пока задача ещё не решается.
range(1, 101)На первом шаге нужен не ответ, а глазами читаемый след: сто строк видно, тысячу — уже нет, и пример из условия в ней не найти.
Пример из условия всегда маленький — сотни хватает.
Совпало — гасим печать и возвращаем большой диапазон, а дальше дописываем строку отбора:
for n in range(1, 1001):
...
r = int(t, 2)
#print(n, s, t, r)
if r > 95 and r < best:
best = r
Не стирать, а закомментировать. Показался странным ответ — решётку снять, и след снова перед глазами. Набирать строку заново на экзамене некогда.
def to2(n):
return f'{n:b}'
best = 10 ** 9 # больше любого R
for n in range(1, 1001):
s = to2(n)
if n % 2 == 0:
t = '11' + s + '11'
else:
t = '1' + s + '00'
r = int(t, 2)
#print(n, s, t, r)
if r > 95 and r < best:
best = r
print(best)
Печатает 100.
Ищем наименьшее — поэтому вначале в best кладём
заведомо большое число, больше любого R. Первое же
подходящее R окажется меньше и займёт его место.
Почему не годится «взять первое подходящее»: R растёт не ровно. Соседние N уходят в разные ветки, и значения скачут — вот что считает цикл:
| N | запись | ветка | стало | R |
|---|---|---|---|---|
| 6 | 110 | а | 1111011 | 123 |
| 7 | 111 | б | 111100 | 60 |
| 8 | 1000 | а | 11100011 | 227 |
| 9 | 1001 | б | 1100100 | 100 |
| 10 | 1010 | а | 11101011 | 235 |
| 11 | 1011 | б | 1101100 | 108 |
| 12 | 1100 | а | 11110011 | 243 |
В ответ идёт 100 — десятичное
число, а не 1100100.
Вначале в переменную кладём значение, противоположное искомому: ищем наименьшее — заведомо большое, наибольшее — ноль.
<, >best = 10 ** 9 # больше любого R
...
if r > 95 and r < best:
best = r
print(best)
min, maxbest = 10 ** 9 # больше любого R
...
if r > 95:
best = min(best, r)
print(best)
| Ищем | Вначале | Через <, > | Через min, max |
|---|---|---|---|
| наименьшее R | best = 10 ** 9 |
and r < best: best = r |
best = min(best, r) |
| наибольшее R | best = 0 |
and r > best: best = r |
best = max(best, r) |
| наименьшее N | best = 10 ** 9 |
and n < best: best = n |
best = min(best, n) |
| наибольшее N | best = 0 |
and n > best: best = n |
best = max(best, n) |
Обе записи верны — пишите ту, которую
держите в голове. Важно другое: сравнивается и сохраняется
r или n — смотря что спросили.
Что спрашивали в 13 разобранных вариантах. Каркас общий, меняется строка отбора:
| Вопрос | Раз | Строка отбора |
|---|---|---|
| наименьшее R больше T | 3 | if r > T and r < best: best = r |
| то же, но нечётное R | 2 | добавляется and r % 2 == 1 |
| наибольшее R не больше T | 1 | if r <= T and r > best: best = r |
| наименьшее N с R ≥ T | 4 | if r >= T and n < best: best = n |
| наибольшее N с R ≤ T | 2 | if r <= T and n > best: best = n |
| наибольшее N, R ближе всего к T | 1 | d = abs(r - T), затем if d <= dist: |
Половина вопросов про N, половина про R.
В коде это разница между best = n и
best = r — одна буква.
Единственный вопрос, где в цикле держим две переменные: одна для сравнения, другая для ответа.
dist = 10 ** 9 # расстояние: больше
# любого возможного
best = 0 # сам ответ
for n in range(1, 1001):
...
r = int(t, 2)
#print(n, s, t, r)
d = abs(r - T)
if d <= dist:
dist = d
best = n
print(best)
Правило демоверсии, порог T = 200:
| n | r | abs(r - 200) |
|---|---|---|
| 17 | 196 | 4 |
| 18 | 459 | 259 |
| 19 | 204 | 4 |
abs — потому что «ближе» не значит «больше»:
R годится с любой стороны от T, важна только
разница;dist), а
запоминаем номер (best). Положить d
в best — частая ошибка: напечатается расстояние,
а не ответ;<=, а не <: ближе
четвёрки к 200 не подошёл никто, а таких n два.
<= перезапишет ответ более поздним — останется
19, наибольшее, как и спросили. При <
осталось бы 17.best = n или best = r?Программа написана правильно, цикл верный — а сохраняется не то число, которое спросили.
Проверяющей машине всё равно, что решено верно: ответ не совпал.
Подчеркнуть в условии последнее предложение — там сказано, что указать.
Написав print(best), вернуться к подчёркнутому:
спросили N — в best должно лежать
n.
В практикуме, если перепутать, страница скажет прямо: «это R, а спрашивают N». На экзамене никто не скажет.
Четыре формулировки — четыре разных знака в условии отбора.
| В условии | В программе | Порог 100 подходит? |
|---|---|---|
| R, превышающее 100 | r > 100 |
нет |
| R, не меньшее 100 | r >= 100 |
да |
| R, не превышающее 100 | r <= 100 |
да |
| R, меньшее 100 | r < 100 |
нет |
Эти слова — не украшение условия, а его часть. Переносите их в программу дословно, а не по памяти.
def to3(n):
s = ''
while n > 0:
s = str(n % 3) + s
n = n // 3
return s
def ds(s):
v = 0
for c in s:
v = v + int(c)
return v
best = 10 ** 9
for n in range(1, 1001):
s = to3(n)
if n % 3 == 0:
t = s + s[-2:]
else:
t = s + to3(ds(s) * 2)
r = int(t, 3)
#print(n, s, t, r)
if r > 520 and r % 2 == 1 and r < best:
best = r
print(best)
Печатает 567.
Условие было такое: если N делится на 3 — дописать две последние цифры записи; иначе — сумму цифр, умноженную на 2 и переведённую в троичную. Найти наименьшее нечётное R больше 520. Обе подпрограммы позвались сами собой.
ds = s.count('1') + s.count('2') * 2
В троичной записи цифр всего три: нули в сумму не идут,
каждая единица даёт 1, каждая двойка — 2. Тогда подпрограмма
ds не нужна вовсе.
А вот to3 так не свернуть:
перевод в троичную систему — это цикл с остатками, готовой
функции для него в Python нет. Потому она и подпрограмма.
Все на экране сразу, порядок свой. Алгоритм в каждой задаче свой — списать у соседа нечего.
Ошибся — появится программа-разбор именно этой задачи и след её работы. Кнопка «Новые числа» даст задачу того же типа.
Балл за каждую верно решённую задачу.
6 — «5»
5 — «4»
4 — «3»
Видно и то, сколько сделано с первой попытки.
PC-XXXX-XXXX и кнопка «Сдать»;Число можно получить и не написав программу. Снимок кода показывает, что приём ваш, — поэтому он и просится вместе с ответом.