Prove que um número é algébrico

10

Inspirado por esta resposta (ênfase minha):

Vamos jogar um jogo. Suponha que você tenha algum número x . Você começa com x e pode adicionar, subtrair, multiplicar ou dividir por qualquer número inteiro, exceto zero. Você também pode multiplicar por x . Você pode fazer essas coisas quantas vezes quiser. Se o total se tornar zero, você ganha.

Por exemplo, suponha que x seja 2/3. Multiplique por 3 e subtraia 2. O resultado é zero. Você ganha!

Suponha que x é 7 ^ (1/3). Multiplique por x , depois por x novamente e subtraia 7. Você ganha!

Suponha que x é √2 + √3. Aqui não é fácil ver como vencer. Mas acontece que se você multiplicar por x , subtrair 10, multiplicar por x duas vezes e adicionar 1, então você vence. (Isso não deve ser óbvio; você pode experimentá-lo com sua calculadora.)

Mas se você começar com x = π, não poderá vencer. Não há como ir de π a 0 se você adicionar, subtrair, multiplicar ou dividir por números inteiros ou multiplicar por π, independentemente de quantas etapas você executar. (Isso também não deveria ser óbvio. É uma coisa muito complicada!)

Números como √2 + √3 dos quais você pode ganhar são chamados algébricos . Números como π com os quais você não pode vencer são chamados transcendentais.

Por que isso é interessante? Cada número algébrico está relacionado aritmeticamente com os números inteiros, e os movimentos vencedores no jogo mostram como sim. O caminho para zero pode ser longo e complicado, mas cada passo é simples e existe um caminho. Mas os números transcendentais são fundamentalmente diferentes: eles não estão aritmeticamente relacionados aos números inteiros por meio de etapas simples.


Essencialmente, você usará as etapas usadas na pergunta citada acima para "vencer" o jogo para obter informações.

Dada uma constante algébrica real, xconverta o número em zero usando as seguintes operações permitidas:

  • Adicione ou subtraia um número inteiro.
  • Multiplique ou divida por um número inteiro diferente de zero.
  • Multiplique pela constante original x.

Entrada é uma sequência que pode conter números inteiros, adição, subtração, multiplicação, divisão, exponenciação (sua escolha de **ou ^expoentes é usada para representar raízes) e parênteses. Os espaços na entrada são opcionais, mas não na saída. Você deve enviar as etapas necessárias para obter um resultado zero, multiplicando-se por 7uma única saída como *7. Um espaço à direita e / ou nova linha é permitido.

Exemplos

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

O menor código vence.

mbomb007
fonte
Quão perto 0os resultados precisam estar? Dada erros de arredondamento e precisão float, eu poderia facilmente ver situações problemáticas ...
AdmBorkBork
2
@ TimmyD A resposta precisa ser exata, para que eu possa executar as operações e obter zero. Veja os exemplos fornecidos. Não há aritmética de ponto flutuante.
mbomb007
11
Como é √2 + √3 algébrico? Se você multiplicar o número por si só, obtém 5 + 2√6 ... a menos que esteja faltando algo, você nunca pode forçar o radical.
Mario Ishac
@ mbomb007 Opa, minhas desculpas, não percebi isso no OP.
22816 Mario Ishac
11
É uma solução para a equação x^4-10*x^2+1. Veja WolframAlpha
mbomb007

Respostas:

3

SageMath , 108 bytes

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

Experimente no SageMathCell .

Explicação:

Avalie a sequência simbolicamente como um número algébrico ( sage_eval()). Todo número algébrico é zero de algum polinômio a [0] + a [1] x ^ 1 + a [2] x ^ 2 + ⋯ + a [n] x ^ n com coeficientes racionais a [0],…, a [ n ] ( minpoly()) Multiplique todos os coeficientes pelo denominador comum para transformá-los em números inteiros ( numerator()) e, em seguida, escreva esse polinômio no formato de saída desejado,

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

SageMath, 102 bytes, quase

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

Isso funciona para todas as entradas, exceto 0, porque um polinômio para 1 / α é um polinômio para α com os coeficientes invertidos. :-(

Anders Kaseorg
fonte
1

Mathematica, 194 224 192 bytes

""<>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,∞}]&

Aqui está o caractere unicode de três bytes que representa o infinito no Mathematica.

Como a entrada é uma string, são perdidos 13 bytes, os ToExpression@quais interpretam a entrada da string como uma expressão algébrica.

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

Gostaria de retornar algo como

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

A próxima regra de substituição massageia isso em algo estruturalmente parecido

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

Este formulário Horner pode ser visualizado como uma árvore:

TreeForm

Pelas regras do OP, começamos com a folha mais profunda à direita.

Cases passa pela expressão, começando no nível mais profundo, pegando cada nó pai e sua folha esquerda e montando-o em uma tabela como

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

""<> concatena tudo com a string vazia.

LLlAMnYP
fonte
Isso retorna incorretamente -299para 5/7 + 42.
Anders Kaseorg
@And Por isso omite o * 7 ... Vou verificar novamente uma vez que eu estou em casa
LLlAMnYP
@AndersKaseorg funciona, mas agora estou com 30 bytes de inatividade.
LLlAMnYP