Escreva um programa para desenhar um diagrama 2-D de um nó com base na estrutura do nó. Um nó é exatamente o que parece: um laço de corda amarrado. Na matemática, um diagrama de nós mostra onde um pedaço de corda cruza-se sobre ou embaixo de si para formar o nó. Alguns exemplos de diagramas de nós são mostrados abaixo:
Há uma quebra na linha onde a corda cruza sobre si mesma.
Entrada: a entrada que descreve o nó é uma matriz de números inteiros. Um nó em que a corda se cruza n vezes pode ser representado como uma matriz de n números inteiros, cada um com um valor no intervalo [0, n-1]. Vamos chamar essa matriz K .
Para obter a matriz que descreve um nó, numere cada um dos segmentos de 0 a n-1. O segmento 0 deve levar ao segmento 1, que deve levar ao segmento 2, que deve levar ao segmento 3, e assim sucessivamente até o segmento n-1 voltar e retornar ao segmento 0. Um segmento termina quando outro segmento de corda passa por ele ( representado por uma quebra na linha do diagrama). Vamos dar o nó mais simples - o nó do trevo. Depois de numerarmos os segmentos, o segmento 0 termina quando o segmento 2 passa sobre ele; o segmento 1 termina quando o segmento 0 passa sobre ele; e o segmento 2 termina quando o segmento 1 cruza sobre ele. Assim, a matriz que descreve o nó é [2, 0, 1]. Em geral, o segmento x começa onde o segmento x-1 mod n parou e termina onde o segmento K [x] cruza sobre ele.
A imagem abaixo mostra diagramas de nós, com segmentos rotulados e as matrizes correspondentes que descrevem o nó.
Os três diagramas superiores são verdadeiros nós, enquanto os três inferiores são laços de corda que se cruzam sobre si mesmos, mas não são realmente atados (mas que ainda possuem códigos correspondentes).
Sua tarefa é escrever uma função que utilize uma matriz de números inteiros K (você poderia chamar de algo diferente) que descreva um nó (ou laço de corda que não seja realmente atado) e que produz o diagrama de nó correspondente, conforme descrito na descrição acima. exemplos. Se você puder, forneça uma versão não-armazenada do seu código ou uma explicação e também forneça saídas de amostra do seu código. O mesmo nó geralmente pode ser representado de várias maneiras diferentes, mas se o diagrama do nó que a sua função obtiver satisfizer tiver a entrada como uma de suas representações possíveis, sua solução será válida.
Isso é código-golfe, então o código mais curto em bytes vence. A linha que representa a corda pode ter uma espessura de 1 pixel, no entanto, as passagens por baixo e por cima devem ser claramente distinguíveis (o tamanho da quebra na corda deve ser maior que a espessura da corda por pelo menos um pixel de cada lado) .
Promoverei respostas que dependem dos recursos internos da teoria dos nós, mas a que foi selecionada no final não pode contar com os recursos internos da teoria dos nós.
Tudo o que sei sobre minha notação: acredito que existem sequências de valores que parecem não corresponder a nenhum nó ou nó. Por exemplo, a sequência [2, 3, 4, 0, 1] parece impossível de desenhar.
Além disso, suponha que você faça uma travessia e, a partir dessa travessia, siga o caminho da corda em uma direção e rotule cada travessia não identificada que você encontrar com valores integrais sucessivamente maiores. Para nós alternados, existe um algoritmo simples para converter minha notação em uma rotulagem e, para nós alternados, é trivial converter essa rotulação em um código de Gauss:
template<size_t n> array<int, 2*n> LabelAlternatingKnot(array<int, n> end_at)
{
array<int, n> end_of;
for(int i=0;i<n;++i) end_of[end_at[i]] = i;
array<int, 2*n> p;
for(int& i : p) i = -1;
int unique = 0;
for(int i=0;i<n;i++)
{
if(p[2*i] < 0)
{
p[2*i] = unique;
p[2*end_of[i] + 1] = unique;
++unique;
}
if(p[2*i+1] < 0)
{
p[2*i+1] = unique;
p[2*end_at[i]] = unique;
++unique;
}
}
return p;
}
template<size_t n> auto GetGaussCode(array<int, n> end_at)
{
auto crossings = LabelAlternatingKnot(end_at);
for(int& i : crossings) ++i;
for(int i=1;i<2*n;i+=2) crossings[i] = -crossings[i];
return crossings;
}
fonte
KnotData
no Mathematica ...: '(Knot
builtin! Exemplo de uso:<< Units`; Convert[Knot, Mile/Hour]
rendimentos1.1507794480235425 Mile/Hour
. (Eu acho que isso é engraçado, independentemente de saber se é verdadeiro ou falso; mas é realmente verdade.)Respostas:
GNU Prolog,
622634668 bytes na página de códigos 850Atualização : A versão anterior do programa às vezes tornava os cruzamentos tão rígidos que não renderizavam corretamente, o que viola as especificações. Eu adicionei um código extra para evitar isso.
Atualização : Aparentemente, as regras do PPCG exigem código extra para fazer o programa sair e restaurar o estado exatamente como estava no início. Isso torna o programa um pouco mais longo e não agrega nenhum interesse algorítmico a ele, mas, no interesse da conformidade com as regras, eu mudei.
Programa de golfe
Usando o GNU Prolog porque possui uma sintaxe do solucionador de restrições um pouco menor que a sintaxe aritmética portátil do Prolog, economizando alguns bytes.
Algoritmo
Esse é um desses problemas em que é difícil saber como começar. Não é óbvio como calcular a forma do nó a partir da notação fornecida, porque não informa se você pretende dobrar a linha para a esquerda ou para a direita em qualquer local (e, como tal, o notação pode ser ambígua). Minha solução foi, efetivamente, usar o antigo modo de espera para golfe: escreva um programa incrivelmente ineficiente que gere todas as saídas possíveis e depois veja se elas correspondem à entrada. (O algoritmo usado aqui é um pouco mais eficiente, pois o Prolog pode eliminar o beco sem saída ocasional, mas não possui informações suficientes para melhorar a complexidade computacional.)
A saída é via terminal art. O GNU Prolog parece querer um conjunto de caracteres de byte consistente com o ASCII, mas não se importa com qual deles é usado (pois trata os caracteres com o bit alto definido como opaco). Como resultado, usei o IBM850, que é amplamente suportado e possui os caracteres de desenho de linha que precisamos.
Saída
O programa pesquisa todas as imagens de nó possíveis, na ordem do tamanho da caixa delimitadora, e sai quando encontra a primeira. Aqui está a aparência da saída
m([0]).
:Demorou 290.528 segundos para executar no meu computador; o programa não é muito eficiente. Deixei em funcionamento por duas horas
m([0,1])
e acabei com isso:Versão ungolfed com comentários
O marcador de sintaxe do Stack Exchange parece ter o símbolo de comentário errado para o Prolog; portanto, em vez de
%
comentários (que o Prolog realmente usa), esta explicação usa% #
comentários (que são obviamente equivalentes devido ao início%
, mas destacam corretamente).fonte