O desafio é, dada uma lista de pontos, classificar de uma maneira que, quando estão conectados nessa ordem, nunca se cruzam.
Formato de entrada (lido em stdin):
X Y
1 2
3 4
5 6
...
A saída deve ser igual à entrada, mas classificada.
Regras:
- Você pode começar de qualquer ponto.
- O último ponto deve ser o mesmo que o primeiro, fazendo um circuito fechado.
- Isso deve ser feito considerando a grade cartesiana.
- Você pode supor que os pontos de entrada nem todos estejam em uma única linha.
- Os pontos finais de cada linha não contam como interseção.
Para mais ajuda:
Respostas:
Mathematica -
2030 caracteresApenas a parte de classificação
Código de teste completo, que consiste em gerar 100 pontos aleatórios e traçar a linha
+26 caracteres
Se você exigir entrada / saída adequada,
+2 caracteres
Apenas adicionando
N@
porque o código acima funciona apenas em números reais e não em números inteiros devido ao comportamento estranho do Mathematica ao classificar expressões simbólicas
EDIT Acabei de perceber que, se os pontos não estiverem ao redor da origem, não funcionará, por isso também exige mudança para o centro dos pontos
fonte
ArcTan
resultado seja realmente idêntico até o último bit. Sabe por que isso acontece? (neste caso, se você quiser brincar com ele{{1, 2}, {2, 4}, {3, 6}, {-5, 5}, {-6, -12}, {5, -5}}
).SortBy
documentação: Se alguns dos f [e_i] forem iguais, a ordem canônica do e_i correspondente será usada.A pergunta mudou, portanto, esta resposta contém versões diferentes, com e sem um caminho fechado.
Perl, caminho aberto, 69 bytes
Cada ponto é esperado em STDIN como linha, com as coordenadas separadas por espaço em branco.
Qualquer formato numérico é suportado pelo Perl como número (incluindo números de ponto flutuante).
Exemplo:
Resultado:
Ungolfed:
Variantes de circuito
Na versão da primeira pergunta, havia uma conexão entre o último e o primeiro ponto para fazer um circuito.
Centro não existe ponto, 253 bytes
Essa variante pode falhar, se o centro for um dos pontos, veja o exemplo 3.
Editar% s:
Em sua resposta, swish notou que os pontos devem estar centrados em torno da origem para garantir um circuito sem cruzamentos:
Correção de bug: o caso especial do eixo x negativo incluía o eixo x positivo.
Exemplo 1:
Saída 1:
Exemplo 2:
Teste de representação numérica e transformação de coordenadas.
Saída 2:
Ungolfed:
Sem restrição, 325 bytes
Na versão anterior, o centro é colocado no início e os últimos pontos no eixo negativo são classificados na ordem inversa para obter novamente a cruz para o centro. No entanto, isso não é suficiente, porque os últimos pontos podem estar em uma linha diferente. Portanto, o exemplo 3 a seguir falharia.
Isso é corrigido movendo a origem centralizada um pouco para cima e para a direita. Por causa da centralização, deve haver pelo menos um ponto com valor x positivo e um ponto com valor y positivo. Assim, os mínimos dos valores positivos de x e y são tomados e reduzidos a um nono (metade ou terceiro pode ser suficiente). Este ponto não pode ser um dos pontos existentes e é feita a nova origem.
Os tratamentos especiais da origem e o eixo x negativo podem ser removidos, porque existe algum ponto na nova origem.
Exemplo 3:
Saída 3:
O exemplo 1 agora está classificado de maneira diferente:
Ungolfed:
fonte
GolfScript, 6/13 caracteres (caminho aberto; 49 caracteres para caminho fechado)
O código acima pressupõe que a saída possa estar em qualquer formato razoável. Se o formato de saída precisar corresponder à entrada, a seguinte versão de 13 caracteres fará:
Explicação:
~
avalia a entrada, transformando-a em uma lista de números;]
reúne esses números em uma matriz e2/
divide essa matriz em blocos de dois números, cada um representando um ponto.$
classifica os pontos em ordem lexicográfica, ou seja, primeiro pela coordenada x e depois, se houver laços, pela coordenada y. É fácil mostrar que isso garantirá que as linhas desenhadas entre os pontos não se cruzem, desde que o caminho não precise voltar ao início.Na versão de 5 caracteres,
`
especifica a matriz classificada, produzindo a representação nativa da sequência (por exemplo[[0 0] [0 4] [4 0] [4 4]]
). Na versão mais longa,{" "*n}/
junta as coordenadas de cada ponto por um espaço e acrescenta uma nova linha.Demonstração online: versão curta / versão longa .
Ps. Aqui está uma solução de 49 caracteres para o problema original, em que é necessário fechar o caminho:
Funciona de maneira semelhante à solução Perl de Heiko Oberdiek , exceto que, em vez de usar funções trigonométricas, esse código classifica os pontos pela inclinação ( y - y 0 ) / ( x - x 0 ), onde ( x 0 , y 0 ) é o ponto com o menor coordenado x (e o coordenador y mais baixo , se vários pontos estiverem vinculados ao x mais baixo ).
Como o GolfScript não suporta ponto flutuante, as inclinações são multiplicadas pela constante fixa 9 9 = 387420489. (Se a precisão não for suficiente, você pode substituir o
9
com por99
para transformar o multiplicador em 99 99 ≈ 3,7 × 10 197 ). algum código extra para romper laços (pela coordenada x ) e garantir que, como na solução de Heiko, os pontos com x = x 0 sejam classificados por último, em ordem decrescente pela coordenada y .Novamente, aqui está uma demonstração online .
fonte
Mathematica, 35
Isso funciona para QUALQUER lista de pontos únicos.
Você diz "read from stdin", então para o Mathematica, eu estou assumindo "read from last output".
Entrada (última saída):
Resultado:
Se a entrada e a saída não precisarem estar no formato "novas linhas", isso poderá diminuir para 6 caracteres:
tomando a última saída como entrada, assumindo que a última saída seja uma matriz bidimensional.
Entrada (última saída):
Ouput:
fonte
Sort
a mesma coisa?SortBy
para que eu possa classificar facilmente com relação aos valores "x" e "y".StringSplit
novamente e usando a sintaxe do infixSort@(s=StringSplit)@%~s~"\n"
.PHP (
175109100 caracteres)Ok, admito, o PHP não é a melhor linguagem de golfe, mas tentei.
Aqui está um exemplo de saída:
O que faz é colocar as informações em uma string formatada com zeros anteriores.
Depois, apenas classifica os pontos textualmente.
PS Falha nos números acima
9999
.fonte
Python 2.7, 42B
Realmente não poderia ser mais simples; leia STDIN, ordene linhas, imprima linhas. NB Respeitei os requisitos exatos de E / S da pergunta, mas se você estiver preenchendo manualmente o STDIN, precisará pressionar
CTRL+d
para finalizar a entrada.fonte