Tarefa
Você receberá um conjunto de círculos no plano com seus centros na linha y = 0 . É garantido que nenhum par de círculos tenha mais de um ponto em comum.
Sua tarefa é determinar em quantas regiões as quais os círculos dividem o plano. Uma região é um conjunto contíguo máximo de pontos de inclusão que não cruza nenhum dos círculos.
Você deve escrever um programa que calcule essa resposta quando receber uma descrição dos círculos.
Aqui está um exemplo:
No lado esquerdo, você vê os círculos desenhados no avião. No entanto, na metade direita da imagem, as regiões produzidas pelos círculos são coloridas distintamente (uma cor por região). Existem seis regiões neste exemplo.
Entrada
A primeira linha da entrada contém um número N
, o número de descrições de círculo a seguir. Essa linha é opcional, se sua solução funcionar sem ela, tudo bem.
As seguintes N
linhas de cada uma contém dois números inteiros, x i e r i > 0 , o que representa um círculo com o centro (x i , 0) e raio r i .
É garantido que nenhum par de círculos tenha mais de um ponto em comum. É ainda garantido que x i e r i não exceder 10^9
em valor absoluto (de modo que eles se encaixam confortavelmente em um número inteiro de 32-bit).
A entrada pode ser:
leia de STDIN
ler de um arquivo nomeado
I
no diretório atual
Como alternativa, a entrada pode ser:
disponível como uma sequência (incluindo novas linhas) em uma variável global
na pilha
Saída
Deve ser um número inteiro único, o número de regiões produzidas. Isso deve ser gravado em STDOUT ou em um arquivo nomeado O
no diretório atual.
Regras
O menor código em bytes ganha
Pena de 200 bytes, se o seu código não tiver um polinômio de tempo de execução + complexidade de espaço em
n
Bônus de -100 bytes para pior execução esperada + complexidade de espaço
O(n log n)
Bônus de -50 bytes para pior execução esperada + complexidade de espaço
O(n)
Bônus de -100 bytes para tempo de execução determinístico + complexidade de espaço
O(n)
Ao avaliar o tempo de execução:
Suponha que as tabelas de hash tenham
O(1)
tempo de execução esperado para inserção, exclusão e pesquisa, independentemente da sequência de operações e dos dados de entrada. Isso pode ou não ser verdade, dependendo se a implementação usa randomização.Suponha que o tipo interno da sua linguagem de programação leve
O(n log n)
tempo determinístico , onden
é o tamanho da sequência de entrada.Suponha que as operações aritméticas nos números de entrada levem apenas
O(1)
tempo.Não assuma que os números de entrada estejam vinculados por uma constante, embora, por razões práticas, sejam. Isso significa que algoritmos como classificação de raiz ou classificação de contagem não são tempo linear. Em geral, fatores constantes muito grandes devem ser evitados.
Exemplos
Entrada:
2
1 3
5 1
Saída: 3
Entrada:
3
2 2
1 1
3 1
Saída: 5
4
7 5
-9 11
11 9
0 20
Entrada:
9
38 14
-60 40
73 19
0 100
98 2
-15 5
39 15
-38 62
94 2
Saída: 11
Dicas
Podemos usar a seguinte idéia para uma solução muito compacta. Vamos cruzar o conjunto de círculos com o eixo X e interpretar os pontos de interseção como nós em um gráfico planar:
Cada círculo produz exatamente 2 arestas neste gráfico e até dois nós. Podemos contar o número de nós usando uma tabela de hash para acompanhar o número total de bordas esquerdas ou direitas distintas.
Em seguida, podemos usar a fórmula da característica de Euler para calcular o número de faces de um desenho do gráfico:
V - E + F - C = 1
F = E - V + C + 1
Para calcular C
o número de componentes conectados, podemos usar uma pesquisa profunda .
Nota: Esta ideia do problema foi emprestada de um concurso recente de programação croata , mas não trapaceie olhando os contornos da solução. :)
n log n
bônus? Além disso, tenho uma nova solução conceitualmente nova. Devo postar uma nova resposta para substituir a antiga? (Eu prefiro o primeiro, no caso minha nova solução não é realmente correto)Respostas:
Mathematica,
125122-150 = -28 caracteresNão conheço a complexidade da função interna
ConnectedComponents
.Uso:
fonte
ConnectedComponents
complexidade esperada linear do pior caso, portanto, se houver componentes O (n), isso seria bom. Eu não entendo o Mathematica, então não sei dizer se é O (n) geral e se qualifica para o bônus -150? Eu acho que sim. Eu apenas o executo com entrada no STDIN?Ruby -
312306285273269259 caracteresEsta resposta foi substituída por minha outra abordagem, que usa consideravelmente menos caracteres e é executada
O(n log n)
.OK, vamos lá. Para iniciantes, eu só queria uma implementação funcional, portanto isso ainda não está otimizado por algoritmo. Classifico os círculos do maior para o menor e construo uma árvore (os círculos incluídos em outros círculos são filhos dos maiores). Ambas as operações levam
O(n^2)
na pior eO(n log n)
na melhor das hipóteses. Então eu percorro a árvore para contar as áreas. Se os filhos de um círculo preenchem todo o seu diâmetro, existem duas novas áreas, caso contrário, há apenas uma. Essa iteração levaO(n)
. Portanto, tenho complexidade geralO(n^2)
e não me qualifico para recompensa nem penalidade.Este código espera que a entrada sem o número de círculos seja armazenada em uma variável
s
:Versão ungolfed (espera entrada na variável
string
):fonte
11
. Para aquele em seu comentário9
.10
e8
com a minha versão não-golfada, mas11
e9
com a minha versão atual do golfe: DRuby,
203183173133 - 100 = 33 caracteresEntão, aqui está uma abordagem diferente. Desta vez, ordeno os círculos pelo ponto mais à esquerda. Os círculos que tocam no ponto mais à esquerda são classificados do maior para o menor. Isso é necessário
O(n log n)
(bem, Ruby usa classificação rápida, portanto, na verdade, aO(n^2)
implementação da classificação de mesclagem / heap provavelmente está além do escopo desse desafio). Depois, percorro esta lista, lembrando todas as posições da esquerda e da direita dos círculos que visitei. Isso me permite detectar se uma série de círculos se conecta por todo o círculo maior. Nesse caso, existem duas subáreas, caso contrário, apenas uma. Essa iteração requer apenasO(n)
uma complexidade totalO(n log n)
qualificada para a recompensa de 100 caracteres.Esse snippet espera que a entrada seja fornecida por meio de um arquivo nos argumentos da linha de comando sem o número de círculos:
Versão ungolfed (espera entrada em uma variável
string
):fonte
-1 1 1 1 0 2 4 2 0 6
. Vou pensar em como consertar isso amanhã à noite (espero).Julia - 260 -100 (bônus?) = 160
ATUALIZAR: Ao pensar um pouco, descobri que o problema com o meu método era apenas quando os círculos não estavam conectados, então tive uma ideia: por que não conectá-los artificialmente? Portanto, o todo satisfará a fórmula de Euler.
F = 2 + EV (V = 6, E = 9)
[Não trabalhe com círculos aninhados, por isso não é uma resposta do problema para casos gerais]
Código :
fonte
2 -10 1 10 1
.n=2
, os círculos são(C=(-10,0), r=1)
e(C=(10,0), r=1)
4 0 2 1 1 10 2 11 1
Mas eu não acho que eu posso dar-lhe muito mais casos de teste, que seria um pouco injustoSpidermonkey JS,
308, 287, 273 - 100 = 173Eu acho que se eu reescrevesse isso em Ruby ou Python eu poderia salvar caracteres.
Código:
Algoritmo:
Eu não sou muito bom com a notação O grande, mas acho que é O (n), pois estou efetivamente percorrendo cada círculo três vezes (criar, esquerda, direita) e também classificando as chaves do mapa (e eu classifico para O ( n log n) mas isso desaparece). Isso é determinístico?
fonte
r
loop e ol
loop em uma declaração, eu agradeceria.JavaScript (ES6) -
255254 caracteres -100250 bônus =1554Supõe que a sequência de entrada esteja na variável
S
e emita o número de regiões para o console.A complexidade do tempo agora é O (N).
Caso de teste 1
Saídas:
3
Caso de teste 2
Saídas:
5
Caso de teste 3
Saídas:
6
Caso de teste 4
Saídas:
11
Caso de teste 5
Saídas:
105
Versão anterior
Com comentários:
A complexidade do tempo total é O (N) para tudo, exceto a classificação que é O (N.log (N)) - no entanto, substituindo-o por uma classificação em bucket, isso reduz a complexidade total para O (N).
A memória necessária é O (N).
Adivinhe o que vem a seguir na minha lista de tarefas ... classifique com menos de 150 caracteres.Feitofonte
O(n)
(na verdadeO(n+k)
), masO(n^2)
ouO(n log n)
pior caso, dependendo do algoritmo de classificação utilizados dentro de baldes, então você precisa fazê-lo em 50 caracteres.