Докажите, что число является алгебраическим


10

Вдохновленный этим ответом (выделение мое):

Мы будем играть в игру. Предположим, у вас есть номер x . Вы начинаете с x, а затем можете добавлять, вычитать, умножать или делить на любое целое число, кроме нуля. Вы также можете умножить на х . Вы можете делать эти вещи столько раз, сколько захотите. Если сумма станет нулевой, вы выиграете.

Например, предположим, что х равен 2/3. Умножьте на 3, затем вычтите 2. Результат равен нулю. Ты победил!

Предположим, что х равен 7 ^ (1/3). Умножьте на x , затем снова на x , затем вычтите 7. Вы выиграли!

Предположим, что x равен √2 + √3. Здесь не так просто увидеть, как победить. Но оказывается, что если вы умножите на x , вычтите 10, умножите на x дважды и добавите 1, то вы выиграете. (Это не должно быть очевидно; вы можете попробовать это с помощью калькулятора.)

Но если вы начнете с x = π, вы не сможете выиграть. Невозможно перейти от π к 0, если вы добавляете, вычитаете, умножаете или делите на целые числа или умножаете на π, независимо от того, сколько шагов вы делаете. (Это также не должно быть очевидным. Это очень сложная вещь!)

Числа типа √2 + √3, из которых вы можете выиграть, называются алгебраическими . Числа, такие как π, с которыми вы не можете выиграть, называются трансцендентными.

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


По сути, вы будете использовать шаги, использованные в приведенном выше вопросе, чтобы «выиграть» игру для данного ввода.

Учитывая вещественную алгебраическую константу x, преобразуйте число в ноль, используя следующие разрешенные операции:

  • Добавить или вычесть целое число.
  • Умножьте или разделите на ненулевое целое число.
  • Умножьте на исходную константу x.

Входные данные - это строка, которая может содержать целые числа, сложение, вычитание, умножение, деление, возведение в степень (по вашему выбору **или ^, экспоненты используются для представления корней) и круглые скобки. Пробелы на входе являются необязательными, но не на выходе. Вы должны вывести шаги, необходимые для получения результата, равного нулю, поэтому умножение на 7один шаг будет выведено как *7. Трейлинг и / или перевод строки разрешены.

Примеры

0               ->  +0 (or any other valid, or empty)
5/7 + 42        ->  -42 *7 -5 (or shorter: *7 -299)
2^(1/3)         ->  *x *x -2
5*(3**(1/4))    ->  *x *x *x -1875
2^(1/2)+3^(1/2) ->  *x -10 *x *x +1

Самый короткий код выигрывает.


Насколько близко 0должны быть результаты? Учитывая ошибки округления и точность с плавающей точкой, я мог легко увидеть проблемные ситуации ...
AdmBorkBork

2
@TimmyD Ответ должен быть точным, чтобы я мог выполнить операции и получить ноль. Посмотрите представленные примеры. Здесь нет арифметики с плавающей точкой.
mbomb007

1
Как √2 + √3 алгебраический? Если вы умножите число на себя, вы получите 5 + 2√6 ... если я не пропущу что-то, вы никогда не сможете вытеснить радикал.
Марио Исхак

@ mbomb007 К сожалению, мои извинения, не нашли этого в ОП.
Марио Исхак

1
Это решение уравнения x^4-10*x^2+1. Смотрите WolframAlpha
mbomb007

Ответы:


3

SageMath , 108 байт

def f(s):p=map('{:+} '.format,numerator(minpoly(sage_eval(s)/1)));return'*'+p[-1][1:]+'*x '.join(p[-2::-1])

Попробуйте это на SageMathCell .

Объяснение:

Оцените строку символически как алгебраическое число ( sage_eval()). Каждое алгебраическое число является нулем некоторого многочлена a [0] + a [1] x ^ 1 + a [2] x ^ 2 + ⋯ + a [n] x ^ n с рациональными коэффициентами a [0],…, a [ n ] ( minpoly()). Умножьте все коэффициенты на их общий знаменатель, чтобы превратить их в целые числа ( numerator()), затем запишите этот полином в желаемом выходном формате,

*a[n] +a[n-1] *x +a[n-2] *x … *x +a[1] *x +a[0]

SageMath, 102 байта, почти

lambda s:(lambda a,*p:'*%d'%a+'*x'.join(map(' {:+} '.format,p)))(*numerator(minpoly(1/sage_eval(s))))

Это работает для всех входных данных, кроме 0, потому что полином для 1 / α является полиномом для α с обратными коэффициентами. :-(


1

Mathematica, 194 224 192 байта

""<>Cases[HornerForm@MinimalPolynomial[ToExpression@#,x]//.{Times->t,x^a_:>Fold[#2~t~#&,x~Table~a],a_~t~b_~t~c_:>a~t~t[b,c]},a_~b_~_:>{b/.t:>"*"/.Plus:>If[a>0,"+",""],ToString@a," "},{0,∞}]&

Вот трехбайтовый символ Юникода, представляющий бесконечность в Mathematica.

Поскольку input является строкой, 13 байтов теряются, ToExpression@что интерпретирует ввод строки как алгебраическое выражение.

HornerForm@MinimalPolynomial[2^(1/2)+3^(1/2), x]

Вернул бы что-то вроде

1 + x^2 (-10 + x^2)

Следующее правило замены массирует это в нечто, что структурно похоже

1 + (x * (x * (-10 + (x * (x)))))

Эта форма Хорнера может быть визуализирована как дерево:

TreeForm

Мы, по правилам ОП, начинаем с самого глубокого листа справа.

Cases проходит через выражение, начиная с самого глубокого уровня, беря каждый родительский узел и его левый лист и собирая его в таблицу, такую ​​как

"*" "x"   " "
""  "-10" " "
"*" "x"   " "
"*" "x"   " "
"+" "1"   " "

""<> объединяет все с пустой строкой.


Это неправильно возвращает -299для 5/7 + 42.
Андерс Касеорг

@ И так, он пропускает * 7 ... Я дважды проверю, как только я дома
LLlAMnYP

@AndersKaseorg это работает, но теперь у меня на 30 байтов меньше.
LLlAMnYP
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.