Комментарии 53
Вроде уравнение плоскости, которая проходит через центр координат, то есть нужны 2 любые точки чтобы однозначно определить все углы наклона.
Некоторые участники квеста пытались использовать эту схожесть))
Я к тому, что в этой задаче в теории можно пару раз случайно вызвать функцию, не придумывая специальные значения и алгоритмы, только лень решать.
P.S. Я не прав (алгебраически и геометрически нужно вроде три случайных вызова).
Да, вот только вам надо эти точки угадать. Просто передав какую-то точку вы получите расстояние до плоскости (растянутое в константу раз). И просто по двум точкам вы однозначно плоскость не найдете.
Задача мне не понравилась, из пальца высосана, а самодовольства море разливанное.
def magic(x: int, y: int, z: int) -> int:
a = 1
b = 2
c = 3
return a * x + b * y + c * z
s = magic("a", "b", "c")
print(f'a={s.count("a")}, b={s.count("b")}, c={s.count("c")}')
Без лоха и жизнь плоха.
Шаман Хакер!
А что, (x: int, y: int, z: int) -> int:
- задние типов аргументов и возвращаемого значения вообще ничего не ограничивает в Питоне?
Ваш код не работает - падает с ошибкой. Точнее, работает или не работает в зависимости от значения констант.
А какие именно значения констант валят этот код? слишком большие?
Это питон. Там длинная арифметика встроенная. Не упадет, если только там константы не по миллиону знаков.
Можно вот так тогда:
def magic(x: int, y: int, z: int) -> int:
a = 10000000000000000000000
b = 20000000000000000000000
c = 30000000000000000000000
return a * x + b * y + c * z
class Num(int):
mul: int | None
def __new__(cls, x, *args, **kwargs):
instance = int.__new__(cls, x, *args, **kwargs)
instance.mul = None
return instance
def __rmul__(self, other) -> int:
self.mul = other
return super().__mul__(other)
x = Num(1)
y = Num(1)
z = Num(1)
magic(x, y, z)
print(x.mul, y.mul, z.mul)
А если numpy
или подобные либы есть, то можно не класс создавать, а матрицей прикинуться:
import numpy as np
def magic(x: int, y: int, z: int) -> int:
a = 10000000000000000000000
b = 20000000000000000000000
c = 30000000000000000000000
return a * x + b * y + c * z
X = np.array([[1, 0, 0]])
Y = np.array([[0, 1, 0]])
Z = np.array([[0, 0, 1]])
print(magic(X, Y, Z))
Вы бы хотя бы условие задачи прочитали. Функция принимает целые числа в качестве аргументов, так что ваше решение в корне неверно.
Это задача на программирование, с условием описанным конкретным кодом, на конкретном языке программирования.
Это решение запускается, и решает задачу, на мой читательский взгляд - с меньшим числом допущений, чем попытка угадать размерность константы, которая не указана в описании задачи или спецификаци функции.
Размерность констант может быть любой, в условии оговаривается то, что они явлются натуральными числами, то есть 1, 2, 3 и так далее. Решение, конечно, запускается, но оно вообще не оптимальное. Если константы будут достаточно большими, вычисление может занять очень много времени либо вообще выдаст MemoryError.
Как программист я Вас очень хорошо понимаю. Но как олимпиадник - нет, потому что про время вычисления в условии не оговаривается. Понимаю это уже рефлекс из опыта разработки, но раз это ограничение не оговорено, и это сферическая задача в вакууме, а не часть продакшн модуля - его нет.
как олимпиадник - нет
Согласен. Задача сформулирована не корректно, с точки зрения соревнований/конкурса. Что-то (ограничения) приходится додумывать.
Раньше в олимпиадном программировании всегда были ограничения и на память и на время. Решение прошло бы на хакерском квесте, но не на олимпиаде по математике или программированию.
В условии не говорится, что они являются натуральными. Это дополнительное ограничение вводится, когда хочется притянуть за уши возможность решения с двумя вызовами:
Оказывается, можно — при условии, что константы
a, b
иc
являются натуральными числами.
Поэтому таким же образом, @longclaps может сказать: "Оказывается можно и за один - при условии, что константы в диапазоне от 0
до 10**19
".
Нет, это решение отлично работет в питоне. Ваше решение тоже основано на тонкостях работы питона. Конкретно, на том, что там встроенная длинная арифметика. Если бы это был какой-нибудь C++ с 32-битными int-ами, то удачи вам получить назад число из 27 цифр.
Можно строки заменить на векторы: x = (1, 0, 0), y = (0, 1, 0), z = (0, 0, 1). Либо самому написать простенький класс, либо, например, воспользоваться numpy.
В квесте была проверка на тип int, такое решение не проходило
Ну это вообще на решение не тенет. А если у вас "черный ящик" с проверкой типов переданных аргументов?
Некоторое размышление сразу привели к тому, что нужно как-то разделить числа на разные интервалы порядков, не было только понятно как это сделать, без неоднозначности. А вот использование суммы неизвестных и исходя из этого использовать степени, вот это как раз любопытно, хотя после того как узнал, становится практически очевидным.
Самое забавное, что иногда такие задачи приходится решать. Но там есть известные ограничения на максимальное значение элементов.
Если прочитать условие задачи НЕ смотря на картинку, то не понятно что возвращает функция. Вот так у нас и пишут документацию )
0 вызовов:
from inspect import getsource
def magic(x: int, y: int, z: int) -> int:
a = 256
b = 512
c = 1024
return a * x + b * y + c * z
print(getsource(magic))
Не хватает кода для разбора (парсинга) кода функции, чтобы определить значения констант. :)
Допустим, так:
from inspect import getsource
def magic(x: int, y: int, z: int) -> int:
a = 256
b = 512
c = 1024
return a * x + b * y + c * z
def parse_var_vals(source_code: str) -> None:
code_fragments = source_code.split(' ')
func_vars = [fragment.strip() for fragment in code_fragments if ' = ' in fragment]
vars_mapping = dict([var.split(' = ') for var in func_vars])
print(', '.join(func_vars))
print(vars_mapping)
if __name__ == '__main__':
parse_var_vals(getsource(magic))
С помощью десятичного логарифма находим минимальную степень десяти, превышающую число
total
, которую запишем в переменнуюpower
Непонятно, почему бы не воспользоваться тривиальным power = 1 + len(str(total))
А если не нравится, что для точных степеней десятки оно даст больше, чем нужно - ну можно отнять единичку.
А где же разбор за один вызов magic()
?
Если немного схитрить в том, что это всё же не чисто математическая задача, а задание на программирование, то можно и в один вызов, сохраняя все исходные требования к типам:
class MyInt(int):
memory: list[tuple] = []
def __rmul__(self, __value):
return MyInt(__value)
def __add__(self, __value):
self.memory.append((self, __value))
return MyInt(0)
def magic(x: int, y: int, z: int) -> int:
a = 314
b = 271828
c = 69
return a * x + b * y + c * z
if __name__ == '__main__':
x_ = MyInt(0)
y_ = MyInt(0)
z_ = MyInt(0)
assert isinstance(x_, int)
assert isinstance(y_, int)
assert isinstance(z_, int)
result = magic(x=x_, y=y_, z=z_)
assert isinstance(result, int)
print(', '.join([str(j) for i in result.memory for j in i if j]))
Можно изящнее, но подход, думаю, понятен
Не знаю питон, но разве у инта нет ограничения на максимальный размер? И что будет если одна из переменных будет близка к этому ограничению?
X=1, y=0, z=0
Получаем значение a.
X=0, y=a, z=1
Получим число, остаток деления которого на а будет значение с, целая часть от этого деления будет b. Если остаток от деления равен 0, то b=с.
Простая задача. Можно и за один вызов функции решить)))
sum = magic(10**60, 10**30, 1)
a = round(sum / (10**60))
rest = sum - (a * (10**60))
b = round(rest / (10**30))
c = rest - (b * (10**30))
print(a,b,c)
class int:
def __init__(self, val) -> None:
self.val = val
def __rmul__(self, owner):
st = o
wner * self.val
return [st]
А если одно из чисел (a, b, c) порядка MAXINT/100?
def magic(x: int, y: int, z: int) -> int:
a = 256
b = 512
c = 1024
return a * x + b * y + c * z
class A(int):
def __rmul__(self, x):
print(x)
return self * x
print(magic(A(1), A(1), A(1)))
Коллега высказал идею, что если бы x, y, z были бы вещественные — можно было бы опознать a, b, c за один вызов magic(e², e, 1) перебором.
Помнится, такая задача, вместе с ещё двумя, попалась мне на очном собесе в майлРу в 2016. Все три уже были ранее решены на braingames.ru, и целых 20 минут я усиленно изображал работу мысли в поисках решения :)
Об одной изящной задаче