O pequeno Chandler está triste. Desenhe uma nuvem para animá-lo

57

O pequeno Chandler está triste. Desenhe uma nuvem para animá-lo.
Nota: Desenhar uma nuvem não vai animá-lo.

Um círculo pode ser definido como uma tupla de 3, (x,y,r)onde xé a posição x do círculo em um plano cartesiano, yé a posição y do círculo em um plano cartesiano e ré o raio do círculo. xe ypode ser negativo. ré sempre positivo. A entrada é uma lista de círculos na forma de três tuplas separadas por espaço. Por exemplo:

3,1,1 3,2,1.5 1,2,0.7 0.9,1.2,1.2 1,0,0.8

Os 3,1,1meios "Um círculo com ponto central 3,1com 1 raio. 3,2,1.5Significa" Um círculo com ponto central 3,2com 1,5 raio.

Se desenharmos todos esses círculos da entrada em um gráfico, será assim (incluí linhas e rótulos de grade apenas para maior clareza; eles não são necessários):

Gráfico

Observe como todos os círculos são coesos . Ou seja, todos eles se sobrepõem, formando um grande grupo sem pequenos grupos de círculos separados do resto. A entrada é garantida para ser coesa.

Suponha que agora desenhemos uma linha que viaja ao redor da "borda" formada por esses círculos, sem nenhuma das outras linhas. Seria como desenhar a borda da silhueta formada por todos os círculos. A nuvem resultante ficaria assim:

nuvem

Portanto, essa nuvem foi formada desenhando apenas os arcos dos círculos na entrada que formam uma borda, resultando em uma única forma. Em outras palavras, a nuvem é formada apenas desenhando os arcos que não estão dentro de outro círculo. Seu programa terá entrada na forma explicada acima e saída uma imagem que exibe a nuvem resultante. A forma geral da nuvem deve estar correta, mas a escala, a cor, a espessura da linha e a aparência dos vértices dependem de você. Observe que a nuvem deve estar visível; portanto, não é possível extrair algo como "Este programa desenha uma nuvem branca em fundo branco", "Este programa desenha uma nuvem em uma escala infinitesimalmente pequena", "Este programa desenha uma nuvem com 0 espessura da linha ", etc. Observe também que a cor da borda deve ser diferente da cor do preenchimento ou do plano de fundo.

Outro exemplo. Entrada:

1,4,2 5,2,1 3,1,1 3.5,2,1.2 3,3,0.7 1,2,0.7

Resultado:

cloud2

Se houver um "buraco" na nuvem, você deve desenhá-lo também. Entrada:

0,5,4 3,4,4 4,3,4 5,0,4 4,-3,4 3,-4,4 0,-5,4 -3,-4,4 -4,-3,4 -5,0,4 -4,3,4 -3,4,4 

Resultado:

cloud3

Aqui está uma regra importante: seu programa deve desenhar apenas as linhas que formam a borda. Isso significa que você NÃO PODE simplesmente desenhar os círculos completamente e, em seguida, desenhar os círculos um pouco menores com um preenchimento branco - porque esse método ainda desenha linhas que não formam uma borda, apenas as cobre posteriormente. O objetivo da regra era impedir as implementações "desenhe os círculos e desenhe os círculos novamente com um preenchimento branco", ou qualquer coisa semelhante a isso. Espera-se que a resposta realmente calcule onde desenhar as coisas antes de desenhá-las.

Isso é código de golfe, portanto, a menor contagem de caracteres vence.

absinto
fonte
13
+1 para uma pergunta de saída gráfica com um critério de vitória objetivo (e o primeiro parágrafo).
Dennis
2
Como você pode saber se traçamos uma linha e a apagamos depois? A renderização dessas linhas em bitmaps internos está OK? Caso contrário, onde está a borda entre um vetor e uma representação de bitmap? Se sim, por que não fazer o mesmo com a tela principal (que sabemos ter buffer duplo, para que o usuário não possa ver nossas linhas temporárias)?
John Dvorak
1
@JanDvorak O objetivo da regra era impedir as implementações "desenhe os círculos e desenhe os círculos novamente com um preenchimento branco", ou qualquer coisa semelhante a isso. Espera-se que a resposta realmente calcule onde desenhar as coisas antes de desenhá-las. Vou editar para deixar mais claro.
absinthe
15
Essa pergunta é absolutamente hilária com o Cloud to Butt ( chrome.google.com/webstore/detail/cloud-to-butt-plus/… ) instalado.
Erty Seidohl 23/09/14
9
@SomeKittens Perdi-o em "Se houver um" buraco "na nuvem, você também deve desenhar o buraco".
Erty Seidohl 23/09

Respostas:

25

Mathematica 177 126 121 119

Resolução por regiões de disco: a abordagem do matemático

A lógica é

  • Crie a Região 1 (R1), os círculos (sem o interior);
  • Crie a região 2 (R2), os discos (sem as bordas do círculo).
  • Crie a região 3 (R3 = R1-R2).
  • -

inferência da região

Essa é precisamente a abordagem adotada abaixo. Produziu as 3 figuras acima.

input = "3,1,1 3,2,1.5 1,2,0.7 0.9,1.2,1.2 1,0,0.8";
circles = ((x - #)^2 + (y - #2)^2 == #3^2) & @@@ 
     ToExpression[#~StringSplit~","] &@(StringSplit@input);
R1 = ImplicitRegion[Or @@ circles, {x, y}];
r1 = RegionPlot[R1, PlotLabel -> "R1: circles containing borders", 
   AspectRatio -> 1, PlotRange -> {{-1, 5}, {-1, 5}}];

innerDisks = ((x - #)^2 + (y - #2)^2 < #3^2) & @@@ 
     ToExpression[#~StringSplit~","] &@(StringSplit@input);
R2 = ImplicitRegion[Or @@ innerDisks, {x, y}];
r2 = RegionPlot[R2, PlotLabel -> "R2: disks within circle borders", 
   AspectRatio -> 1, PlotRange -> {{-1, 5}, {-1, 5}}];
R3 = RegionDifference[R1, R2]
r3 = RegionPlot[R3, PlotLabel -> "R3 = R1-R2", AspectRatio -> 1, 
   PlotRange -> {{-1, 5}, {-1, 5}}];
GraphicsGrid[{{r1, r2, r3}}, ImageSize -> 600]

A região implícita nº 1 é a união dos círculos. A região implícita nº 2 é a união dos discos dentro dos círculos. A diferença deles é a fronteira.

RegionDifference [Região
implícita [(- 3 + x) ^ 2 + (-1 + y) ^ 2 == 1 || (-3 + x) ^ 2 + (-2 + y) ^ 2 == 2,25 || (-1 + x) ^ 2 + (-2 + y) ^ 2 == 0,49 || (-0,9 + x) ^ 2 + (-1,2 + y) ^ 2 == 1,44 || (-1 + x) ^ 2 + y ^ 2 == 0,64, {x, y}],
Região implícita [(- 3 + x) ^ 2 + (-1 + y) ^ 2 <1 || (-3 + x) ^ 2 + (-2 + y) ^ 2 <2,25 || (-1 + x) ^ 2 + (-2 + y) ^ 2 <0,49 || (-0,9 + x) ^ 2 + (-1,2 + y) ^ 2 <1,44 || (-1 + x) ^ 2 + y ^ 2 <0,64, {x, y}]]


Resolução por regiões de disco: a abordagem do engenheiro (119 caracteres)

A seguir, é feita a união das regiões do disco, discretiza essa região e encontra seu limite. Os pontos no diagrama demarcam os intervalos da malha de Delaunay. Exibimos a região discretizada abaixo para destacar o objeto que fornece o limite de interesse (o contorno da nuvem).

s = StringSplit;RegionBoundary@DiscretizeRegion[RegionUnion[Disk[{#, #2}, #3] &@@@
ToExpression[#~s~","] &@(s@InputString[])]]

"3,1,1 3,2,1,5 1,2,0,7 0,9,1,2,1,2 1,0,0,8"

O limite da região é discretizado.

reg1


Resolução por detecção de bordas: a abordagem do fotógrafo - 121 caracteres

detecção de borda

Desenha os discos em preto, rasteriza a imagem, detecta as bordas e inverte em preto e branco.

s=StringSplit;ColorNegate@EdgeDetect@Rasterize@Graphics[Disk[{#,#2},#3]&@@@
((ToExpression/@s[#,","])&/@s[InputString[]])]
DavidC
fonte
Raspado 5 bytes:RegionBoundary@DiscretizeRegion@RegionUnion[{#,#2}~Disk~#3&@@@ToExpression[#~s~","]&@s@InputString[s=StringSplit]]
Martin Ender
Potencialmente o s=StringSplitinterior do prompt? Tente movê-lo para a frente novamente, ainda deve ser mais curto que a sua versão atual.
Martin Ender
27

T-SQL 235 234 229 212 171 73 bytes

Isso faz uso da funcionalidade espacial no SQL Server 2012+. Quando é executado no SSMS (SQL Server Management Studio), produz um painel de resultados espaciais. A entrada é da variável @i. Eu poderia reduzir ainda mais se a entrada pudesse ser retirada de uma tabela.

Como a entrada da tabela agora é permitida.

SELECT Geometry::UnionAggregate(Geometry::Point(X,Y,0).STBuffer(R))FROM A

Deixei a solução anterior abaixo.

DECLARE @ VARCHAR(999)='WITH a AS(SELECT *FROM(VALUES('+REPLACE(@i,' ','),(')+'))A(X,Y,R))SELECT Geometry::UnionAggregate(Geometry::Point(X,Y,0).STBuffer(R))FROM a'EXEC(@)

Editar : Remover o espaço perdido, o superávit em e subconsulta

171: Criação de tabela substituída por CTE e @s por @.

insira a descrição da imagem aqui

Divisão do SQL dinâmico

DECLARE @i VARCHAR(100) = '1,4,2 5,2,1 3,1,1 3.5,2,1.2 3,3,0.7 1,2,0.7' -- Input
DECLARE @ VARCHAR(999) = '
WITH a AS(                                       --CTE to produce rows of x,y,r 
    SELECT *FROM(VALUES('+
        REPLACE(@i,' ','),(')                    --Format @i to a value set
        +'))A(X,Y,R)
)
SELECT Geometry::UnionAggregate(                 --Aggregate Buffered Points
    Geometry::Point(X,Y,0).STBuffer(R)           --Create point and buffer
    )               
FROM a                                           --from the table variable
'
EXEC(@)                                          --Execute Dynamic sql
MickyT
fonte
Estou recebendo um erro dizendo'A' has fewer columns than were specified in the column list
Jesan Fafon 26/09/14
@JesanFafon Verifique se a sua variável de entrada @i está definida corretamente. DECLARE @i VARCHAR(100) = '1,4,2 5,2,1 3,1,1 3.5,2,1.2 3,3,0.7 1,2,0.7'. Infelizmente, não posso testar em que momento e SQLfiddle não está jogando bem para 2012.
MickyT
Bom trabalho com funções de geometria SQL. Boas notícias! A entrada pela tabela preexistente agora é explicitamente permitida . A criação de tabela e a população não precisam ser incluídas na contagem de bytes.
BradC
Eu joguei alguns personagens. O link não produz um resultado. Mas funciona no estúdio de gerenciamento de servidor ms-sql. Script está aqui , aproveite. Sinta-se livre para usá-lo
t-clausen.dk
@ t-clausen.dk obrigado por isso, mas como vou atualizá-lo, alterarei para entrada de tabela permitida. Eu não ia fazer isso de novo, mas ...
MickyT 22/03
23

Mathematica, 175 158 149 bytes

s=StringSplit;l=ToExpression[#~s~","]&@s@InputString[];RegionPlot[Or@@(Norm@{x-#,y-#2}<#3&@@@l),{x,m=Min@(k={{##}-#3,{##}+#3}&@@@l),M=Max@k},{y,m,M}]

Lembro-me da discussão na sandbox que essa abordagem deveria ser válida, mas não tenho certeza de como ela se encaixa na nova redação das regras, então, @Lilac, deixe-me saber se você acha que isso viola as regras.

Basicamente, estou criando uma condição lógica que é verdadeira para todos os pontos dentro da nuvem e falsa para todos os pontos fora dela. Estou alimentando o RegionPlotque, então, renderiza a região de todos os pontos em que a expressão está Truee um contorno em torno dela.

insira a descrição da imagem aqui

Ungolfed:

s = StringSplit;
l = ToExpression[#~s~","] &@s@InputString[];
RegionPlot[
 Or @@ (Norm@{x - #, y - #2} < #3 & @@@ l), 
 {x, m = Min@(k = {{##} - #3, {##} + #3} & @@@ l), M = Max@k},
 {y, m, M}
]
Martin Ender
fonte
1
ImplicitRegionlocaliza automaticamente os valores x e y adequados para plotagem. 122 caracteres:s = StringSplit; RegionPlot@ ImplicitRegion[ Or @@ (((x - #)^2 + (y - #2)^2 < #3^2) & @@@ (ToExpression[#~s~","] &@(s@InputString[]))), {x, y}]
DavidC
@DavidCarraher Infelizmente, isso distorce a proporção da imagem. (É bom saber que todas essas funções região embora - também os que você usou - Eu só visto RegionPlot. Até agora)
Martin Ender
Você provavelmente já observou que ,AspectRatio-> 1traz o código de volta para 149 bytes, exatamente onde está agora.
DavidC
2
Sou eu ou esta imagem se parece com Marvin, o Android paranóico?
paqogomez 24/09
16

Python 3,3 ( 183 177 164 160 bytes)

B=list(map(eval,input().split()))
print("".join(" ## "[sum(any(r*r>(x-d%80/4+10)**2+(y+d//80/4-10)**2for
x,y,r in B)for d in[i,i+1,i+80])]for i in range(6400)))

Ele requer um console de 80 caracteres, que eu sei que é o padrão no Windows. Funciona melhor se o seu console tiver uma fonte quadrada. Aqui estão alguns trechos de algumas das entradas de teste.

Original:

           ########
          ##       #
         ##         #
     #####          #
    ##   #          #
   ##               #
  ##                #
 ##                 #
 #                  #
 #                 ##
  #               ##
  #       ##      #
   #      # #    ##
   #      #  #####
   #      #
    #    ##
     #  ##
      ###

Outro:

    ########
  ###       ##
 ##           #
 #            #
##             #
#              #
#              #
#              #
#              #
#               ##
#                 #
 #                 ##
 #                   ######
  #                        #
   ##      ###             #
     #    ## #             #
     #    #  #             #
      #  ## ##             #
       ###  #             ##
            #       #######
            #      ##
            #      #
             #    ##
              #####

Orifício:

                              ############
                            ###           ##
                          ###               ##
                         ##                   #
                  ########                     #######
                ###                                   ##
              ###                                       ##
             ##                                           #
            ##                                             #
           ##                                               #
          ##                                                 #
         ##                                                   #
        ##                                                     #
       ##                                                       #
      ##                                                         #
      #                                                          #
     ##                                                           #
     #                                                            #
    ##                                                             #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
   ##                                                               #
  ##                                                                 #
  #                                                                  #
 ##                                                                   #
 #                                                                    #
##                                                                     #
#                                 ####                                 #
#                                ##   #                                #
#                               ##     #                               #
#                              ##       #                              #
#                              #        #                              #
#                              #        #                              #
#                               #      ##                              #
#                                #    ##                               #
#                                 #  ##                                #
#                                  ###                                 #
 #                                                                    ##
 #                                                                    #
  #                                                                  ##
  #                                                                  #
   #                                                                ##
    #                                                              ##
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
     #                                                            ##
     #                                                            #
      #                                                          ##
      #                                                          #
       #                                                        ##
        #                                                      ##
         #                                                    ##
          #                                                  ##
           #                                                ##
            #                                              ##
             #                                            ##
              #                                          ##
               ##                                      ###
                 ##                                  ###
                   #######                    ########
                          #                  ##
                           ##              ###
                             ##          ###
                               ###########
recursivo
fonte
1
Eu amo que essa é a única solução de arte ascii.
vmrob
sem importações ... impressionante!
Richard Green
15

Python - 253 249 215 199

Este é um anúncio para a impressionante biblioteca bem torneada , cujas operações de geometria tornaram a solução da tarefa simples, desenhando o (s) contorno (s) da união de círculos sobrepostos (= pontos em buffer):

from pylab import*
from shapely.geometry import*
c=Point()
for s in raw_input().split():
 x,y,r=eval(s)
 c=c.union(Point(x,y).buffer(r))
plot(*c.exterior.xy)
for i in c.interiors:
 plot(*i.xy)
show()

Resultado:

três nuvens

Editar% s):

  • 249: Substituído sys.argv[1:]por raw_input().split(), salvando umimport sys
  • 215: k={'color':'k'}Luxo removido , substituído savefigporshow
  • 199: substituído map(float,s.split(','))poreval(s)
ojdo
fonte
11

Python - 535

import math as m
import matplotlib.pyplot as l
c = "3,1,1 3,2,1.5 1,2,0.7 0.9,1.2,1.2 1,0,0.8"
a = [[float(y) for y in x.split(",")] for x in c.split(" ")]
for a2 in a:
    for x in xrange(0,200):
        q=x*m.pi/100.0
        p=(a2[0]+m.sin(q)*a2[2], a2[1]+m.cos(q)*a2[2])
        cc = []
        for z in a:            
            if z != a2:               
                if ((z[0] - p[0]) ** 2 + (z[1] - p[1]) ** 2 ) < (z[2] ** 2) :
                    cc.append(z)
        if not cc: 
            l.scatter(p[0],p[1])
l.show()
Richard Green
fonte
2
Isso tem muito potencial para ser rebaixado ainda mais, por exemplo, por from math import* removendo espaços não selecionados, usando apenas nomes de variáveis ​​de uma letra, usando a compreensão da lista (por exemplo, cc=[z for z in a if z!=a2 and (z[0]…)]). Veja também as dicas para jogar golfe no Python .
precisa saber é o seguinte
Você pode salvar alguns caracteres usando um nome de variável de uma letra em vez de a2.
ProgramFOX
graças wrzl ... eu provavelmente vai começar golfe hoje à noite (outras coisas para fazer agora, mas queria colocar uma estaca no chão)
Richard Green
1
sim @ProgramFOX ... esta era uma versão que trabalhou e que eu poderia depurar .. vai buscá-la mais curta esta noite ...
Richard Green
3
@ JamesWilliams se você quiser pegar o bastão ... por favor .. Eu não sou protetor do código !! Sinta-se livre para adicioná-lo como sua própria entrada (desde que você credite o original!)
Richard Green
9

Python - 296 249 231 223 212

from pylab import*
a=map(eval,raw_input().split())
for x,y,r in a:
 for i in range(200):
  q=i*pi/100;p=x+r*sin(q);t=y+r*cos(q);[z for z in a if z!=(x,y,r)and(z[0]-p)**2+(z[1]-t)**2<z[2]**2]or scatter(p,t)
show()

O crédito vai para @ richard-green (foi dada permissão) para a solução original, eu a reduzi um pouco.

James Williams
fonte
7
bem que tem o meu voto ...
Richard Green
1
Você pode economizar um pouco mais importando em pylabvez de matplotlib.pyplot.
ojdo 23/09
@odjo Atualmente no celular, se eu usasse from pylab import *, ainda seria capaz de ligar show()e scatter()sem referências?
James Williams
1
@JamesWilliams confirmado! Pylab é um poluidor namespace, incluindo muitas funções MATLAB-like :-)
ojdo
Você pode encurtar isso usando [eval(i)for i in raw_input().split()]como as evaltransformações do python 1,2,3em uma tupla. É claro que você também precisará alterar o [x,y,r]para a (x,y,r).
KSab
7

JavaScript (E6) + HTML 322

JSFiddle

Cada círculo é subdividido em cerca de 100 pequenos arcos e cada arco é desenhado se o seu ponto médio não estiver dentro de nenhum dos outros círculos.

<canvas id='c'/>
<script>
t=c.getContext("2d"),z=99,c.width=c.height=400,
l=prompt().split(' ').map(c=>c.split(',').map(v=>40*v)),
l.map(c=>{
  for(i=z;--i+z;)
    s=4/z,r=c[2],x=c[0]+r*Math.cos(a=i*s),y=c[1]+r*Math.sin(a),
    t.beginPath(),
    l.some(q=>c!=q&(d=x-q[0],e=y-q[1],d*d+e*e<q[2]*q[2]))||t.arc(z+c[0],z+c[1],r,a-s,a+s),
    t.stroke()
})
</script>
edc65
fonte
7

Python 274 bytes

Isso recebe a entrada do stdin e verifica todos os pontos da tela, desenhando os pixels um a um conforme o andamento. Não é exatamente eficiente, mas segue todas as regras.

c=[eval(s)for s in raw_input().split()]
import pygame
S=pygame.display.set_mode((500,500))
S.fill([255]*3)
for p in((x,y)for x in range(500)for y in range(500)if 0<min((((x-250)/25.-a)**2+((y-250)/25.-b)**2)**.5-r for(a,b,r)in c)<.1):S.set_at(p,[0]*3)
pygame.display.update()

Observe que a exibição do pygame terminará assim que o desenho estiver concluído. Eu não tinha certeza se deveria incluí-lo como parte da minha resposta, mas para visualizá-lo, você pode raw_inputinserir um no final ou adicionar um pequeno loop, se desejar. deseja impedir que o sistema operacional se queixe de não responder e assim:

alive = True
while alive:
    pygame.display.update()
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            alive = False

Imagens de exemplo:

1,4,2 5,2,1 3,1,1 3.5,2,1.2 3,3,0.7, 1,2,0.7 insira a descrição da imagem aqui

0,5,4 3,4,4 4,3,4 5,0,4 4,-3,4 3,-4,4 0,-5,4 -3,-4,4 -4,-3,4 -5,0,4 -4,3,4 -3,4,4 insira a descrição da imagem aqui

KSab
fonte
3
@ edc65 Não sei bem o que você quer dizer. O que ele faz com precisão é preencher qualquer pixel que esteja entre 0 e 0,1 unidades (entre 0 e 2,5 pixels) fora dos círculos. Você está dizendo que ele deve encontrar matematicamente os arcos corretos para desenhar? Ao ler a pergunta, isso não me pareceu uma restrição.
KSab
4

Perl - 430

@e=map{[map{int($_*32)}split',']}(split' ',<>);for$g(@e){for(0..3){($a[$_]>($q=$$g[$_&1]+(($_>>1)*2-1)*$$g[2]))^($_>>1)&&($a[$_]=$q)}}for(2,3){$a[$_]-=$a[$_-2]-1}for(@e){($x,$y,$r)=@$_;$x-=$a[0];$y-=$a[1];for$k($x-$r..$x+$r){for$l($y-$r..$y+$r){$i=(int(sqrt(($x-$k)**2+($y-$l)**2)+0.5)<=>$r)-1;$f[$l][$k]=($j=$f[$l][$k])<-1||$i<-1?-2:$i||$j;}}}print"P1
$a[2] $a[3]
".join("
",map{join' ',map{$_+1?0:1}@$_,('0')x($a[2]-@$_)}@f)."
"

Grava um arquivo pbm no stdout.

Imagem de teste (convertida em png):

Segunda imagem de teste (convertida em png)

faubi
fonte