O objetivo desse desafio é produzir uma animação de um sistema de acionamento por corrente , composto por um conjunto de engrenagens conectadas por uma corrente .
requerimentos gerais
Seu programa receberá uma lista de rodas dentadas , especificadas como (x, y, radius)
trigêmeos. O sistema de acionamento da corrente resultante é composto por essas rodas dentadas, conectadas por uma corrente esticada fechada que passa sobre cada uma delas, em ordem . Seu objetivo é produzir uma animação infinitamente em loop , mostrando o sistema em movimento. Por exemplo, dada a entrada
(0, 0, 16), (100, 0, 16), (100, 100, 12), (50, 50, 24), (0, 100, 12)
, a saída deve parecer algo como
.
O sistema de coordenadas deve ser tal que o eixo x aponte para a direita e o eixo y aponte para cima. Você pode supor que os raios sejam números pares iguais ou superiores a 8 (veremos por que isso importa mais tarde). Você também pode assumir que existem pelo menos duas rodas dentadas e que as rodas dentadas não se cruzam . As unidadesda entrada não são muito críticos. Todos os exemplos e casos de teste nesta postagem usam pixels como unidades de entrada (portanto, por exemplo, o raio da roda do meio na figura anterior é de 24 pixels;) tente não se desviar muito dessas unidades. No restante do desafio, entende-se que as quantidades espaciais são dadas nas mesmas unidades que a entrada - mantenha as proporções corretas! As dimensões da saída devem ser ligeiramente maiores que a caixa delimitadora de todas as rodas dentadas, suficientemente grandes para que todo o sistema seja visível. Em particular, as posições absolutas das rodas dentadas não devem afetar a saída; somente suas posições relativas deveriam (por exemplo, se trocássemos todas as rodas dentadas no exemplo acima pela mesma quantidade, a saída permaneceria a mesma).
A corrente deve ser tangente às rodas dentadas por onde passa em todos os pontos de contato e reta em qualquer outro lugar. A corrente deve passar sobre as rodas dentadas, de modo que os segmentos adjacentes da corrente (ou seja, partes da corrente entre duas rodas dentadas, que se encontram na mesma roda dentada) não se cruzem .
.
Por exemplo, enquanto o sistema esquerdo acima é válido, o do meio não é, pois os dois segmentos de corrente adjacentes que passam sobre a roda dentada inferior esquerda se cruzam. No entanto, observe que o sistema correto é válido, pois os dois segmentos de cadeia que se cruzam não são adjacentes (esse sistema é produzido por uma entrada diferente dos outros dois).
Para simplificar as coisas (r), você pode assumir que nenhum pinhão cruza o casco convexo de seus dois pinhões vizinhos ou os cascos convexos de cada um de seus vizinhos e seu outro vizinho. Em outras palavras, a roda dentada superior no diagrama abaixo pode não cruzar nenhuma das regiões sombreadas.
Os segmentos da cadeia podem cruzar as rodas dentadas diferentes daquelas que passam por cima (como no último caso de teste). Nesse caso, a corrente sempre deve aparecer na frente das rodas dentadas.
Requisitos visuais
A corrente deve consistir em uma série de elos de larguras alternadas. A largura do link estreito deve ser de cerca de 2 e a largura do link de largura deve ser de 5. O comprimento dos dois tipos de links deve ser aproximadamente igual. O períododa cadeia, ou seja, o comprimento total de um par de elos amplo / estreito, deve ser o número mais próximo de 4π que se ajusta a um número inteiro de vezes no comprimento da cadeia. Por exemplo, se o comprimento da cadeia for 1.000, seu período deverá ser 12,5, que é o número mais próximo de 4π (12,566 ...) que se ajusta a um número inteiro de vezes (80) em 1.000. É importante que o período ajuste um número inteiro de vezes no comprimento da corrente, para que não haja artefatos no ponto em que a corrente se enrola.
Uma roda dentada de raio R deve consistir em três partes concêntricas: um eixo central , que deve ser um círculo de raio de cerca de 3; o corpo da roda dentada , em torno do eixo, que deve ser um círculo de raio em torno de R - 4,5; e a borda da roda dentada , ao redor do corpo, que deve ser um círculo de raio em torno de
R - 1,5. O aro também deve conter os dentes da roda dentada , que devem ter uma largura de cerca de 4; o tamanho e o espaçamento dos dentes devem coincidir com os tamanhos dos elos da corrente, para que eles se enredem perfeitamente.
O período dos dentes da roda dentada, ou seja, a distância entre dois dentes consecutivos ao longo da circunferência da roda dentada, deve coincidir com o período da corrente. Como o período é de cerca de 4π e como o raio da roda dentada é garantido, o período deve caber na circunferência da roda dentada um número quase inteiro de vezes, para que não haja artefatos perceptíveis no ponto em que os dentes da roda dentada se enrolam.
Você pode usar qualquer combinação de cores para a corrente, as diferentes partes da roda dentada e o fundo, desde que sejam facilmente distinguíveis . O plano de fundo pode ser transparente. Os exemplos deste post são usados #202020
para a corrente, #868481
o eixo e a jante #646361
da roda dentada e o corpo da roda dentada.
Requisitos de Animação
O primeiro pinhão na lista de entrada deve girar no sentido horário ; o restante das rodas dentadas deve girar de acordo. A corrente deve se mover a uma velocidade de cerca de 16π (cerca de 50) unidades por segundo; a taxa de quadros depende de você, mas a animação deve parecer suave o suficiente.
A animação deve repetir sem problemas .
Conformidade
Alguns dos atributos e proporções visuais são especificados intencionalmente apenas aproximadamente - você não precisa correspondê-los exatamente . A saída do seu programa não precisa ser uma réplica pixel a pixel dos exemplos fornecidos aqui, mas deve ser semelhante. Em particular, as proporções exatas da corrente e das rodas dentadas, e o formato exato dos elos da corrente e dos dentes da roda dentada, são flexíveis.
Os pontos mais importantes a seguir são estes:
- A corrente deve passar sobre as rodas dentadas, na ordem de entrada, na direção correta.
- A corrente deve ser tangente às rodas dentadas em todos os pontos de contato.
- Os elos da corrente e os dentes das rodas dentadas devem enredar ordenadamente, pelo menos até corrigir o espaçamento e a fase.
- O espaçamento entre os elos da corrente e os dentes das rodas dentadas deve ser tal que não haja artefatos perceptíveis no ponto em que eles se enrolam.
- As rodas dentadas devem girar na direção correta.
- A animação deve repetir sem problemas.
Como nota final, embora, tecnicamente, o objetivo desse desafio seja escrever o código mais curto, se você quiser ser criativo e produzir uma saída mais elaborada, por qualquer meio, vá em frente!
Desafio
Escreva um programa ou uma função , fazendo uma lista de rodas dentadas e produzindo uma animação do sistema de acionamento por corrente correspondente, conforme descrito acima.
Entrada e saída
Você pode levar a entrada pela linha de comando , pelo STDIN , como argumentos de função ou usando um método equivalente . Você pode usar qualquer formato conveniente para a entrada, mas certifique-se de especificá-lo em sua postagem.
Como saída , você pode exibir a animação diretamente , produzir um arquivo de animação (por exemplo, um GIF animado) ou produzir uma sequência de arquivos de quadro (no entanto, há uma pequena penalidade nesse caso; veja abaixo.) Se você usar a saída do arquivo, verifique se o número de quadros é razoável (os exemplos nesta postagem usam muito poucos quadros;) o número de quadros não precisa ser mínimo, mas você não deve produzir muitos quadros supérfluos. Se você produzir uma sequência de quadros, especifique a taxa de quadros na sua postagem.
Ponto
Isso é código-golfe . A resposta mais curta , em bytes, vence.
+ 10% de multa Se o seu programa produzir uma sequência de quadros como saída, em vez de exibir a animação diretamente ou produzir um único arquivo de animação, adicione 10% à sua pontuação.
Casos de teste
Teste 1
(0, 0, 26), (120, 0, 26)
Teste 2
(100, 100, 60), (220, 100, 14)
Teste 3
(100, 100, 16), (100, 0, 24), (0, 100, 24), (0, 0, 16)
Teste 4
(0, 0, 60), (44, 140, 16), (-204, 140, 16), (-160, 0, 60), (-112, 188, 12),
(-190, 300, 30), (30, 300, 30), (-48, 188, 12)
Teste 5
(0, 128, 14), (46.17, 63.55, 10), (121.74, 39.55, 14), (74.71, -24.28, 10),
(75.24, -103.55, 14), (0, -78.56, 10), (-75.24, -103.55, 14), (-74.71, -24.28, 10),
(-121.74, 39.55, 14), (-46.17, 63.55, 10)
Teste 6
(367, 151, 12), (210, 75, 36), (57, 286, 38), (14, 181, 32), (91, 124, 18),
(298, 366, 38), (141, 3, 52), (80, 179, 26), (313, 32, 26), (146, 280, 10),
(126, 253, 8), (220, 184, 24), (135, 332, 8), (365, 296, 50), (248, 217, 8),
(218, 392, 30)
Respostas:
JavaScript (ES6),
2557191518971681 bytesIsso não é realmente um super-jogador de golfe ; é reduzido - parcialmente à mão - mas isso não é nada de especial. Sem dúvida, poderia ser mais curto se eu tivesse jogado mais antes da minificação, mas já passei (mais do que) tempo suficiente nisso.
Edit: Ok, então eu gastei mais tempo nele e joguei o código mais antes da minificação (desta vez, muito manualmente). O código ainda está usando a mesma abordagem e estrutura geral, mas mesmo assim eu acabei economizando 642 bytes. Não é tão pobre, se eu digo. Provavelmente perdi algumas oportunidades de economia de bytes, mas, neste momento, nem tenho mais certeza de como funciona. A única coisa diferente em termos de saída é que agora ela usa cores ligeiramente diferentes que podem ser escritas de maneira mais concisa.
Editar 2 (muito mais tarde): salvou 18 bytes. Agradeço a ConorO'Brien nos comentários por apontar o óbvio óbvio de que eu tinha perdido totalmente.
Edit 3: Então, imaginei que eu faria engenharia reversa do meu próprio código, porque, francamente, não conseguia me lembrar de como o havia feito, e perdi as versões não destruídas. Então eu passei, e eis que encontrei outros 316 bytes para economizar, reestruturando e praticando micro-golfe.
A função acima anexa um elemento SVG (incluindo animações) ao documento. Por exemplo, para exibir o segundo caso de teste:
Parece funcionar - pelo menos aqui no Chrome.
Experimente no trecho abaixo (clique nos botões para desenhar cada um dos casos de teste do OP).
Mostrar snippet de código
O código desenha os dentes da corrente e da engrenagem como traços tracejados. Em seguida, ele usa
animate
elementos para animar ostroke-dashoffset
atributo. O elemento SVG resultante é independente; não há animação orientada por JS ou estilo CSS.Para alinhar bem as coisas, o anel de dentes de cada engrenagem é realmente desenhado como um caminho que consiste em dois arcos, para que o caminho possa começar exatamente no ponto tangente onde a corrente toca. Isso torna muito mais simples alinhá-lo.
Além disso, parece que há muitos erros de arredondamento ao usar os traços tracejados do SVG. Pelo menos, foi o que vi; quanto mais longa a corrente, pior seria a malha com cada engrenagem sucessiva. Portanto, para minimizar o problema, a cadeia é composta de vários caminhos. Cada caminho consiste em um segmento de arco em torno de uma marcha e uma linha reta para a próxima marcha. Seus desvios são calculados para corresponder. A parte fina "interna" da cadeia, no entanto, é apenas um caminho de loop único, pois não é animado.
fonte
R=g=>...
<g>
, mas coloquei diretamente na raiz svg. Também encontrado um lugar onde você transformou bandeira varredura e bandeira do arco grande de booleano para o número usando1*x
, mas você poderia usar+x
Bytes C # 3566
Não é golfe, masfunciona (acho)Ungolfed no histórico de edições.
Usa Magick.NET para renderizar gif.
A classe P tem uma função F; Exemplo:
fonte
public
modificador antes de cada campo da sua classe?using
cláusulas correspondentes devem ser incluídas ou os tipos totalmente qualificados quando usados e a referência ao System.Drawing deve ser observada. na resposta (se deve adicionar à pontuação que eu não sei). Resposta impressionante de qualquer maneira.JavaScript (ES6) 1626 bytes
Esta solução é o resultado da engenharia reversa da solução da @ Flambino, eu a publico com ele.
A versão não destruída:
fonte