Uma curva algébrica é um certo "subconjunto 1D" do "plano 2D" que pode ser descrito como um conjunto de zeros {(x,y) in R^2 : f(x,y)=0 }
de um polinômio f
. Aqui, consideramos o plano 2D como o plano real R^2
, para que possamos imaginar facilmente como seria uma curva, basicamente algo que você pode desenhar com um lápis.
Exemplos:
0 = x^2 + y^2 -1
um círculo de raio 10 = x^2 + 2y^2 -1
uma elipse0 = xy
uma forma de cruz , basicamente a união do eixo xe do eixo y0 = y^2 - x
uma parábola0 = y^2 - (x^3 - x + 1)
uma curva elíptica0 = x^3 + y^3 - 3xy
o folium de Descartes0 = x^4 - (x^2 - y^2)
um lemniscato0 = (x^2 + y^2)^2 - (x^3 - 3xy^2)
um trifólio0 = (x^2 + y^2 - 1)^3 + 27x^2y^2
um astroide
Tarefa
Dado um polinômio f
(conforme definido abaixo) e os intervalos x / y, produz uma imagem em preto e branco de pelo menos 100x100 pixels que mostra a curva como linha preta em um fundo branco.
Detalhes
Cor : você pode usar quaisquer outras duas cores de sua escolha; deve ser fácil diferenciá-las.
Trama : em vez de uma imagem de pixel, você também pode exibir esta imagem como arte-ascii, onde o "pixel" do plano de fundo deve ser espaço / sublinhado ou outro caractere que "parece vazio" e a linha pode ser feita de um caractere que parece " cheio "como M
ou X
ou #
.
Você não precisa se preocupar com o alias.
Você só precisa plotar linhas onde o sinal do polinômio muda de um lado da linha para o outro (o que significa que você pode, por exemplo, usar o algoritmo do quadrado de marcha), não é necessário plotar corretamente "casos patológicos como 0 = x^2
onde o sinal ocorre" não muda ao passar de um lado da linha para o outro, mas a linha deve ser contínua e separar as regiões dos diferentes sinais de f(x,y)
.
Polinômio : O polinômio é dado como uma (m+1) x (n+1)
matriz / lista de listas de coeficientes (reais), no exemplo abaixo, os termos dos coeficientes são dados em sua posição:
[ 1 * 1, 1 * x, 1 * x^2, 1 * x^3, ... , 1 * x^n ]
[ y * 1, y * x, y * x^2, y * x^4, ... , y * x^n ]
[ ... , ... , ... , ... , ... , ... ]
[ y^m * 1, y^m * x, y^m * x^2, y^m * x^3 , ..., y^m * x^n]
Se preferir, você pode assumir que a matriz é quadrada (o que sempre pode ser feito com o preenchimento de zero necessário) e, se desejar, também pode assumir que o tamanho da matriz é dado como entradas adicionais.
A seguir, os exemplos acima são representados como uma matriz definida assim:
Circle: Ellipse: Parabola: Cross: Elliptic Curve: e.t.c
[-1, 0, 1] [-1, 0, 1] [ 0,-1] [ 0, 0] [-1, 1, 0,-1]
[ 0, 0, 0] [ 0, 0, 0] [ 0, 0] [ 0, 1] [ 0, 0, 0, 0]
[ 1, 0, 0] [ 2, 0, 0] [ 1, 0] [ 1, 0, 0, 0]
Casos de teste com intervalo x / intervalo y:
(Em um formato não tão legível, mas melhor disponível para copiar e colar, disponível aqui no pastebin .)
Circle:
[-1, 0, 1] [-2,2] [-2,2]
[ 0, 0, 0]
[ 1, 0, 0]
Ellipse:
[-1, 0, 1] [-2,2] [-1,1]
[ 0, 0, 0]
[ 2, 0, 0]
Cross:
[ 0, 0] [-1,2] [-2,1]
[ 0, 1]
Parabola:
[ 0,-1] [-1,3] [-2,2]
[ 0, 0]
[ 1, 0]
Elliptic Curve:
[-1, 1, 0,-1] [-2,2] [-3,3]
[ 0, 0, 0, 0]
[ 1, 0, 0, 0]
Folium of Descartes:
[ 0, 0, 0, 1] [-3,3] [-3,3]
[ 0, -3, 0, 0]
[ 0, 0, 0, 0]
[ 1, 0, 0, 0]
Lemniscate:
[ 0, 0, -1, 0, 1] [-2,2] [-1,1]
[ 0, 0, 0, 0, 0]
[ 1, 0, 0, 0, 0]
Trifolium:
[ 0, 0, 0,-1, 1] [-1,1] [-1,1]
[ 0, 0, 0, 0, 0]
[ 0, 3, 2, 0, 0]
[ 0, 0, 0, 0, 0]
[ 1, 0, 0, 0, 0]
Astroid:
[ -1, 0, 3, 0, -3, 0, 1] [-1,1] [-1,1]
[ 0, 0, 0, 0, 0, 0, 0]
[ 3, 0, 21, 0, 3, 0, 0]
[ 0, 0, 0, 0, 0, 0, 0]
[ -3, 0, 3, 0, 0, 0, 0]
[ 0, 0, 0, 0, 0, 0, 0]
[ 1, 0, 0, 0, 0, 0, 0]
Eu tenho a inspiração para algumas curvas deste pdf.
m
xn
, mas(m+1)
x(n+1)
. O que tomamos como entrada:,m, n
oum+1,n+1
? Ou podemos escolher?Respostas:
Haskell,
283275 bytesA função
g
deve ser chamada com a matriz e os dois intervalos como argumentos. A matriz é apenas uma lista de listas, os intervalos cada uma lista de dois elementos.Aqui estão as saídas para os casos mais interessantes: Observe que eu tive que diminuir o tamanho da resolução de 100x100 para cerca de 40x40 para que ela caiba no console (basta alterar o 102 codificado para um número menor). Observe também que o eixo y está apontando para baixo.
fonte
$
para salvar um byte. Ambos os locais onde você usamap
podem estar(<$>)
, e como você usa apenase
uma vez, pode puxar o(0<)
interior da definição. Tambéme
pode ser nomeado(!)
para salvar 3 bytes.z
na definição dev
permite livrar-se de 4 parênteses (ao redorz(&)
ef g
).#
para um único caractere (por exemplos
) e ter o padrão correspondente nas listas em vez deg
. (egs[a,b]=[a,a+(b-a)/102..b];g m u i=unlines$v[m!y<$>s u|y<-s i]
)Matlab,
11410092 bytesA ferramenta certa para o trabalho? Eu uso a maneira interessante que o Matlab faz
printf
para gerar um polinômio como uma string. Esse polinômio pode ser fornecido para oezplot
qual plota a curva implícita no domínio especificado. Para facilitar a leitura, o código é apresentado com novas linhas depois; o que não é necessário e não é contado para o tamanho.Progresso no golfe como snippet expansível.
Mostrar snippet de código
Saída dos casos de teste (clique para visualização completa):
fonte
sprintf/ezplot
!fix
vez defloor
poder ajudá-lo a alcançar a contagem de bytes de dois dígitos :-)[h,w]=size(A);t=0:h*w-1;
para salvar outros três bytes!%.0f
. Isso significa que eu posso derrubar o piso completamente e vamosprintf
consertá-lo!Python 2, 261 bytes
Formato de entrada:
matrix,xbounds,ybounds
(por exemplo[[-1,0,1],[0,0,0],[1,0,0]],[-2,2],[-2,2]
). Formato de saída: PGM simples .Isso estima a distância de cada centro de pixel à curva usando a aproximação de primeira ordem d ( x , y ) = | p ( x , y ) | / | ∇ p ( x , y ) |, onde ∇ p é o gradiente do polinômio p . (Esta é a distância de ( x , y ) à interseção do plano tangente em ( x , y , p ( x , y )) com o plano xy .) Em seguida, os pixels onde d (x , y ) tem menos de um pixel de largura da curva proporcionalmente a d ( x , y ), resultando em boas linhas antialias (mesmo que isso não seja um requisito).
Aqui estão os mesmos gráficos com a função de distância dividida por 16 para torná-la visível.
fonte
print
instrução para o cabeçalho da imagem e umaprint
instrução nowhile
loop para o valor de cada pixel.Python 3.5 + MatPlotLib + Numpy, 352 bytes:
Uma função nomeada. Muito tempo, mas, ei, estou feliz por ter conseguido realizar a tarefa. Aceita 3 entradas, que são a
m by n
matriz, asx
séries -range ey
-range, que devem estar todas em matrizes (por exemplo,[[-1,0,1],[0,0,0],[1,0,0]],[-2,2],[-2,2]
). Produz o gráfico concluído em uma nova janela gráfica e interativa. Vou jogar isso mais tempo quando puder, mas por enquanto estou feliz com isso.Saídas finais para os casos de teste:
fonte
MATL ,
6761 bytesEsse código é executado na versão 18.5.0 do idioma, que precede o desafio. Input usa o opcional
m
,n
parâmetros. A matriz possui ponto e vírgula como separadores de linha. O formato exato de entrada (usando a parábola como exemplo) éO código produz uma imagem com tamanho 255 × 255. Isso pode ser testado usando @Suever 's MATL online compilador, que, entre outras características muito interessantes, inclui saída gráfica. Veja por exemplo
Este compilador ainda está em um estágio experimental. Relate quaisquer problemas para o @Suever na sala de chat do MATL . Se o botão "Executar" não funcionar, tente atualizar a página e clicar novamente.
Se você preferir a saída ASCII , o código precisará ser modificado um pouco (as alterações afetam apenas os dois primeiros e os quatro últimos caracteres do código acima):
Isso produz uma grade ASCII 100 × 100 que usa caracteres
*
para representar a curva. Você também pode testar isso com o @Dennis ' Experimente online! plataforma:Observe que a proporção da saída ASCII é alterada porque os caracteres são um pouco mais altos do que largos.
Explicação
O código primeiro calcula o polinômio de duas variáveis em uma grade x - y . Isso faz uso intenso da transmissão , calculando um array 4D intermediário, em que cada dimensão representa valores x , valores y , x expoentes e expoentes respectivamente.
A partir dessa função, a linha de nível zero é calculada. Como o desafio especifica que apenas as alterações de sinal precisam ser detectadas, o código aplica a convolução 2D com um bloco 2 × 2 e marca um pixel como pertencente à linha, se não os quatro valores do bloco tiverem o mesmo sinal.
Todos os casos de teste
Aqui estão todas as entradas no formato apropriado, caso você queira tentar:
fonte