Introdução:
O seno de x
é dado pela fórmula:
sin(x) = x - x^3/3! + x^5/5! - x^7/7! + x^9/9! - x^11/11! // and more follows...
O cosseno de x
é dado pela fórmula:
cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + x^8/8! - x^10/10! // and more follows...
Tarefa:
Dado o valor de x
e n
, escreva um programa (sem funções, etc.) para gerar o valor sin(x)
e cos(x)
corrija os n
termos da fórmula acima. Suponha que x
esteja em radianos.
Entrada:
x n
Um número decimal x
(com até 3 casas decimais) e um número inteiro n
. A entrada deve estar no stdin ou em uma caixa de diálogo de prompt (se o seu idioma não suportar stdin)
Saída:
[sin(x)]
[cos(x)]
O valor de ambos sin(x)
e cos(x)
deve ser arredondado para 6 casas decimais. Se sin(x)
for 0.5588558855
(10 dígitos decimais), deve ser arredondado para 0.558856
(6 dígitos decimais). O arredondamento deve ocorrer para o mais próximo, conforme descrito na quinta coluna, "Arredondar para o mais próximo" da tabela neste artigo do Wiki .
Restrições:
1 <= x <= 20
1 <= n <= 20
Amostras:
----
5 3
10.208333
14.541667
----
8.555 13
0.765431
-0.641092
----
9.26 10
-3.154677
-8.404354
----
6.54 12
0.253986
0.967147
----
5 1
5.000000
1.000000
----
20 20
-5364.411846
-10898.499385
----
Notas:
- As brechas padrão são proibidas.
- Funções matemáticas internas e operadores de trigonometria (sin, cos, tan, etc.), fatorial e exponenciação não podem ser usados. Você é livre para usar uma função de arredondamento embutida para estimar o resultado da computação
sin(x)
ecos(x)
o sexto dígito decimal. - Não há necessidade de lidar com entradas erradas.
- Somente caracteres ASCII podem ser usados no programa, não os caracteres chineses Unicode que permitem a compactação de código.
- Seu programa deve terminar e exibir a saída dentro de 3 segundos após a entrada.
- Sua resposta deve acompanhar o código não-bloqueado, juntamente com a explicação do código (obrigatório se o código não for imediatamente óbvio para os programadores que não estão familiarizados com sua linguagem, especialmente GolfScript, J, etc.).
- Inclua um link para um compilador on-line onde seu programa possa ser testado.
Pontuação:
A resposta com o menor tamanho de código em caracteres, incluindo espaço em branco, guias, etc. vence! O vencedor seria declarado em 21 de maio de 2014.
EDIT : 21/05/14 O vencedor é aditsu usando a linguagem CJam . O segundo colocado segue jpjacobs com a linguagem J e o segundo classificado é primo com a linguagem Perl . Parabéns a todos!
mod 2pi
operação para converter as entradas mais rapidamente seria bastante útil - é uma das muitas melhorias que o mundo real usa ao lidar com essas funções. (na verdade, mod pi e sinal de conscientização).Respostas:
CJam - 42
Experimente online em http://cjam.aditsu.net
Explicação:
r
lê um token da entrada sed
converte em:X
atribuições duplas à variável X;
aparece o valor da pilha1
coloca 1 na pilha (o primeiro termo)_
duplica o 1r
lê o próximo token (n) sei
converte em número inteiro2*,1>{...}/
é um tipo de loop de 1 a 2 * n - 1:-
2*
multiplica por 2-
,
cria uma matriz de 0 a (último valor) -1-
1>
remove o primeiro item da matriz (0)-
{...}/
executa o bloco para cada item da matriz_
duplicando o loop " variável "(vamos chamá-lo de k)2%2*(
converte de par / ímpar em -1/1:-
2%
é o módulo 2 (-> 0/1)-
2*
multiplica por 2 (-> 0/2)-
(
decrementa (-> -1/1)*
multiplica, alterando o sinal a cada segunda vez,/
divide o termo na pilha por k ou -k; este é o "/ k!" parte do cálculo, juntamente com a mudança de sinal,X*
multiplica por X; esta é a parte "X ^ k" do cálculo; obtivemos o próximo termo na série_
duplicado, o termo a ser usado para calcular o termo a seguir na próxima iteração;
(após o loop) aparece o último termo duplicado]
coleta os termos na pilha em uma matrizNeste ponto, temos uma matriz [ 1 X-X ^ 2/2! -X ^ 3/3! X ^ 4/4! X ^ 5/5! ...] contendo exatamente todos os termos que precisamos para cos (x) e sin (x), intercalados
2/
dividem esse array em paresz
transpõe a matriz, resultando na matriz com os termos para cos (x) e na matriz com os termos para sin (x), como "linhas da matriz"{...}/
novamente executa o bloco para cada item da matriz (linha da matriz):-
:+
adiciona os elementos da linha da matriz juntos-
6mO
arredonda para 6 casas decimaisNeste ponto, temos o desejado cos (x) e sin (x) na pilha
p
imprime a representação do último item na pilha (sin (x)) seguido por uma nova linhaEm No final do programa, o conteúdo restante da pilha (cos (x)) é impresso automaticamente.
fonte
Perl - 72 bytes
Ou, contando as opções da linha de comando como 1 byte cada, em 70 bytes :
Ou, se você me permitir Perl 5.8, em 63 bytes :
mas por que você faria.
Editar : conformidade com as novas regras.
%f
arredonda para 6 lugares por padrão, que conveniente!Algoritmo
Examinando a série Taylor quanto ao pecado (x) :
pode-se ver que cada termo divide igualmente todos os termos sucessivos. Por isso, pode ser transformado sem esforço em uma expressão aninhada:
cos (x) se transforma da mesma forma, sem o x inicial e o denominador denomina um menor.
Além disso, essa expressão aninhada pode ser reformulada como uma expressão recursiva reversa:
com s ∞ = 0 e sin (x) = x · s 1 , que é basicamente o que é usado.
Ungolfed
Uso da amostra
Se você quiser testar isso online, recomendo usar o compileonline.com . Copie e cole o código em
main.pl
e a entrada naSTDIN
caixa Execute Script.fonte
Python 3 (102) / Python 2 (104)
Python 3 (102)
Python 2.7 (104)
Basicamente o mesmo código. Nós salvamos dois caracteres por não precisar de parênteses,
print
mas perdemos quatro por precisarraw_input
.Amostra de execução
Você pode executá-los aqui .
Explicação do código
A idéia principal é calcular
2*n
termos dee^(ix)
e, em seguida, pegar a parte imaginária e real para obter os valoressin
ecos
aproximados dosn
termos. Usamos o truncamento da série Taylor:Isso é polinomial em i * x, mas, em vez de calcular seu valor somando cada termo, usamos um método de Horner modificado para calcular a sequência (definida recursivamente ao contrário)
o que dá
t_1
igual ao valor desejado.As operações de formatação de seqüência de caracteres Python são usadas para obter os valores exibidos arredondados até 6 dígitos decimais.
Editar: alterado para arredondar para 6 dígitos, de acordo com as novas regras. Não foram necessárias outras alterações.
fonte
J
98 70 6958Embora isso possa ser encurtado usando funções mais sofisticadas ... os comentários são bem-vindos:
nota 2: a entrada termina ao receber EOF (ctrl-D no linux). Editar: junte exponenciação e fatorial em um mais agradável, mais J-ish todo:
($ %&(*/) >:@i.@[ )
. Isso se resume a obter uma matriz de x replicações de y e uma matriz dos números de 1 a y. Multiplique cada um e divida o resultado. Isso se livra da duplicata*/
.Graças a algortihmshark, mais 7 caracteres desligados.
Corte eliminado para se livrar da nova linha à direita.
Versão mais longa, para a qual é essencial conhecer os garfos.
Não há intérprete J online, mas é de código aberto há alguns anos; a instalação é fácil com estas instruções:
http://www.jsoftware.com/jwiki/System/Installation/J801
No #jsoftware em irc.freenode.org, também existe um bot J.
stdin funciona apenas quando executado a partir de um arquivo, a partir da linha de comando, substitua
stdin ''
por'a b;'
onde a e b são os números que seriam passados na linha de comando.fonte
exit
&
de0j6&":
para salvar um caractere. Além disso,(i.@(,&_2)@{:($%&(*/)>:@i.@[)"0{.)
pode ser reescrita(($%&(*/)1+i.@[)"0~i.@,&_2)/
para um outro 6.T.
(função aproximada da série Taylor de n termos), mas acho que isso é verboten como uma brecha padrão.Perl,
1201081048985Ungolfed:
A primeira linha lê a entrada e usa regex para encontrar um espaço; isso coloca automaticamente o valor antes do espaço em $ `e o valor depois em $ '.
Agora passamos de 1 para
2*n-1
.$t
é o nosso termo, que o loop multiplicax
e divide repetidamente pelo índice do loop ($_
). O loop começa em 1 em vez de 0 porque o cosseno é inicializado em 1, o que me salvou de ter que lidar com a divisão por zero.Após a atualização
$t
, o operador trinário retorna um$sine
ou$cosine
, dependendo se o índice é ímpar ou par, e adiciona$t
valor a ele. A fórmula mágica$_&2?-$t:$t
indica se você deve adicionar ou subtrair esse valor (basicamente usando um bit a bit - e no índice e 2 para gerar a sequência repetida de "adicionar, adicionar, subtrair, subtrair").Você pode testar esse código em compileonline.com .
fonte
20 20
.1..$n*2-1
, em vez de1..$n
. Enquanto estou aqui ...$s
é perfeitamente bem não inicializado, comoundef
avalia0
em um contexto numérico. Atribuição ternário não precisa de parênteses:$_&1?$s:$c+=$t
."%.8f\n%.8f"
pode ser reduzido para"%.8f\n"x2
, na conseqüência da adição de uma nova linha à direita.$t*(1-($_&2))
=>$_&2?-$t:$t
.Fortran:
8910912510210198 bytesAbuso de digitação implícita, mas infelizmente não existe esse tipo complexo implícito, então tive que especificar isso e o complexo
i
.O Gfortran corta a saída em 8 casas decimais naturalmente, por isso somos bons nessa especificação.Infelizmente, meu método original de saídaprint*,t
,, não atendia às especificações, então tive que adicionar 16 caracteres para gerar os componentes imaginários e reais e atingir as 8 casas decimais necessárias.Graças ao Ventero, consegui salvar 23 bytes entre a saída e o loop. E outro caractere para obter respostas corretas e saída formatada. E mais 3 na
read
declaração.Ungolfed,
fonte
C, 120
Para salvar um byte, as instruções que atualizam o valor do seno são colocadas dentro da
for()
instrução, mas na verdade são executadas após as instruções após os parênteses de fechamento que atualizam o valor do cosseno. (Acho que também pude salvar mais alguns bytes removendo o caractere de nova linha final na saída do programa.)As variáveis globais
s
,c
,r
ex
são implicitamente inicializado para zero, ei
terá um valor de 1, desde que não há argumentos fornecidos na linha de comando. Infelizmente, oprintf()
padrão é 6 casas decimais, portanto o formato de saída é um pouco detalhado.Ungolfed:
Aqui está o código com um pouco de reorganização para tornar a ordem em que as coisas são feitas um pouco mais clara:
Saída de amostra:
Experimente online:
http://ideone.com/URZWwo
fonte
Python> = 2.7.3,
186184211200182170 caracteresMeio simples como o inferno. Usa a fórmula da pergunta parametrizada para seno e cosseno.
Intérprete online pode ser encontrado
AquiAquiEditar: versão válida com todas as restrições
Edit2: Alterador do interpretador online para ideone.com devido à
round
saída de função inválida no Python 2.7.1Edit3: Descobri que eu usei lambda inline desnecessário + alterei o arredondamento para o formato de string (roubado do xnor :))
Edit4: Substituído
join
porfor
loop principal não funcionalfonte
**
estou fazendo, suponho). Então, acho que você terá que editar sua resposta. Desculpe pela inconveniência. Por favor corrija-me se eu estiver errado.20 20
, eu recebo saída-5364.4118142500001
. Pode querer corrigi-lo para 8 casas decimais.2.7.1
. Se você executá-lo em ideone.com (Python 2.7.3), ele funcionará corretamente. ideone.com/JsYNNKJavaScript - 114 caracteres
Baseado na grande resposta de James. Mesmo algoritmo, primeiro passo evitado com a inicialização de c = 1 es = x. Usar 2 vars em vez de uma matriz para saída simplifica o loop.
Ungolfed
fonte
s += (l *= x / ++d)
e nãos += (l* = x / ++d)
no código não destruído.JavaScript (ECMAScript 6 Draft) -
9796 caracteresUma solução recursiva:
Saída:
fonte
no functions
requisitos e formato de entrada .C, 114
Reputação insuficiente para comentar, mas, além da resposta C da Squeamish Offisrage , a redução de 7 bytes usando float para dobrar e remover espaços, e combinando declaração e init de 'r', fornece
tente aqui .
fonte
r
na declaração. Não testei para ver sefloat
dá a precisão necessária.float
que daria a precisão necessária, mas funciona :) E bem-vindo ao PPCG, user2702245!float
variáveis então? Parax=5
en=3
, recebosin(x)=10.20833206
ecos(x)=14.54166412
:-( (Intel Core Duo, em caso você estava pensando)GNU bc, controlado por bash, 128 bytes
Muitos bytes gastos configurando casas decimais e o arredondamento mais próximo. Oh bem, aqui está assim mesmo:
Saída:
Ferramentas de linha de comando do Linux, 97 caracteres unicode
Resposta de corte Unicode removida a pedido do OP. Veja o histórico de edições, se estiver interessado.
fonte
Ruby, 336
Provavelmente o mais longo aqui, mas tenho certeza de que poderia ser menor :(
fonte
JavaScript (ES6) - 185 caracteres
Usa uma função
q
para fatorial,i
para exponenciação ep
para executar ambossin
ecos
. Execute em jsbin.com. Usa exatamente a fórmula sem nenhuma modificação.EDIT :
8
casas decimais alteradas para6
casas decimais. 15 / Mai / 14Código Ungolfed :
fonte
JavaScript - 133 caracteres
Ungolfed
fonte
Mathematica, 96 caracteres
fonte
x,n
me parece ?x n
.Ruby -
160152140 CharsUsando recursão e o fato de que, para essa implementação recursiva, sin (x, 2n + 1) = 1 + cos (x, 2n - 1), sendo sin (x, n) e cos (x, n) as séries definidas acima para cos xe pecado x.
Editar: Contribuído por comentaristas (leia abaixo).
fonte
p=->x,n{...}
,f=->n{...}
e assim por diante, e, em seguida, usar colchetes em vez de parênteses para chamá-los, comop[x,n-1]
. Além disso, acho quecollect
é apenas um apelido paramap
, que é muito mais curto, e como você está mapeando apenas uma chamada de membro, pode abreviá-logets.split.map &:to_f
.