El pequeño Chandler está triste. Dibujale una nube para animarlo

57

El pequeño Chandler está triste. Dibujale una nube para animarlo.
Nota: Dibujar una nube en realidad no lo animará.

Un círculo se puede definir como una tupla de 3 (x,y,r)donde xestá la posición x del círculo en un plano cartesiano, yes la posición y del círculo en un plano cartesiano y res el radio del círculo. xy ypuede ser negativo rSiempre es positivo. La entrada es una lista de círculos en forma de 3-tuplas separadas por espacios. Por ejemplo:

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

El 3,1,1significa "Un círculo con punto central en 3,1con 1 radio. 3,2,1.5Significa" Un círculo con punto central en 3,2con 1,5 radios.

Si dibujamos todos estos círculos de la entrada en un gráfico, se ve así (he incluido líneas de cuadrícula y etiquetas solo para mayor claridad; no son necesarias):

Grafico

Observe cómo todos los círculos son cohesivos . Es decir, todos se superponen de manera tal que forma un grupo grande sin ningún grupo pequeño de círculos separados del resto. La entrada está garantizada para ser cohesiva.

Supongamos ahora que dibujamos una línea que viaja alrededor del "borde" formado por estos círculos, sin ninguna de las otras líneas. Sería como dibujar el borde de la silueta formada por todos los círculos. La nube resultante se vería así:

nube

Entonces, esta nube se formó dibujando solo los arcos de los círculos en la entrada que forman un borde, dando como resultado una sola forma. En otras palabras, la nube se forma dibujando solo los arcos que no están dentro de otro círculo. Su programa tomará datos en el formulario explicado anteriormente y generará una imagen que muestra la nube resultante. La forma general de la nube debe ser correcta, pero la escala, el color, el grosor de la línea y el aspecto de los vértices depende de usted. Tenga en cuenta que la nube debe ser visible, por lo que no puede extraer algo como "Este programa dibuja una nube blanca sobre un fondo blanco", "Este programa dibuja una nube a una escala infinitamente pequeña", "Este programa dibuja una nube con 0 grosor de línea ", etc. Tenga también en cuenta que el color del borde debe ser diferente del color del relleno o del fondo.

Otro ejemplo. Entrada:

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

Salida:

nube2

Si hay un "agujero" en la nube, también debe dibujar el agujero. 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 

Salida:

nube3

Aquí hay una regla importante: su programa debe dibujar solo las líneas que forman el borde. Esto significa que NO PUEDE dibujar los círculos completamente, y luego dibujar los círculos un poco más pequeños con un relleno blanco, porque ese método todavía dibuja líneas que no forman un borde, simplemente las cubre después. El propósito de la regla era evitar las implementaciones de "dibujar los círculos, luego dibujar los círculos nuevamente con un relleno blanco", o algo similar a eso. Se espera que la respuesta realmente calcule dónde dibujar cosas antes de dibujarla.

Este es el código de golf, por lo que gana el recuento de caracteres más corto.

Ajenjo
fuente
13
+1 para una pregunta de salida gráfica con un criterio ganador objetivo (y el primer párrafo).
Dennis
2
¿Cómo puede saber si dibujamos una línea y la borramos después? ¿Está bien renderizar dichas líneas en mapas de bits internos? Si no, ¿dónde está el borde entre un vector y una representación de mapa de bits? En caso afirmativo, ¿por qué no hacer lo mismo con el lienzo primario (que sabemos que tiene doble memoria intermedia, de modo que el usuario no pueda ver nuestras líneas temporales)?
John Dvorak
1
@ JanDvorak El propósito de la regla era evitar las implementaciones de "dibujar los círculos, luego dibujar los círculos nuevamente con un relleno blanco", o algo similar a eso. Se espera que la respuesta realmente calcule dónde dibujar cosas antes de dibujarla. Lo editaré para que quede más claro.
ajenjo
15
Esta pregunta es absolutamente graciosa con Cloud to Butt ( chrome.google.com/webstore/detail/cloud-to-butt-plus/… ) instalado.
Erty Seidohl el
99
@SomeKittens Lo perdí en "Si hay un" agujero "en la nube, también debes dibujar el agujero".
Erty Seidohl

Respuestas:

25

Mathematica 177 126 121 119

Resolver por regiones de disco: el enfoque del matemático

La lógica es

  • Crear Región 1 (R1), los círculos (sin sus interiores);
  • Cree la Región 2 (R2), los discos (sin los bordes del círculo).
  • Crear Región 3 (R3 = R1-R2).
  • -

inferencia de la región

Este es precisamente el enfoque adoptado a continuación. Produjo las 3 figuras de arriba.

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]

La región implícita # 1 es la unión de los círculos. La región implícita # 2 es la unión de los discos que se encuentran dentro de los círculos. Su diferencia es la frontera.

RegionDifference [
ImplicitRegion [(- 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ón 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}]]


Resolver por regiones de disco: el enfoque del ingeniero (119 caracteres)

Lo siguiente toma la unión de las regiones del disco, discretiza esa región y encuentra su límite. Los puntos en el diagrama delimitan los intervalos de la malla de Delaunay. Mostramos la región discretizada a continuación para resaltar el objeto que proporciona el límite de interés (el contorno de la nube).

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"

El límite de la región está discretizado.

reg1


Resolviendo mediante la detección de bordes: el enfoque del fotógrafo - 121 caracteres

detección de bordes

Dibuja los discos en negro, rasteriza la imagen, detecta los bordes e invierte en blanco y negro.

s=StringSplit;ColorNegate@EdgeDetect@Rasterize@Graphics[Disk[{#,#2},#3]&@@@
((ToExpression/@s[#,","])&/@s[InputString[]])]
DavidC
fuente
Afeitado de 5 bytes:RegionBoundary@DiscretizeRegion@RegionUnion[{#,#2}~Disk~#3&@@@ToExpression[#~s~","]&@s@InputString[s=StringSplit]]
Martin Ender
¿Potencialmente s=StringSplitdentro del aviso? Intenta moverlo al frente nuevamente, aún debe ser más corto que tu versión actual.
Martin Ender
27

T-SQL 235 234 229 212 171 73 bytes

Esto hace uso de la funcionalidad espacial en SQL Server 2012+. Cuando se ejecuta en SSMS (SQL Server Management Studio) se produce un panel de resultados espaciales. La entrada es de la variable @i. Podría reducirlo aún más si la entrada pudiera tomarse de una tabla.

Dado que la entrada de la tabla ahora está permitida.

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

He dejado la solución anterior a continuación.

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 : Retire el espacio callejero, el superávit en y subconsulta

171: Se reemplazó la creación de tablas con CTE y @s con @.

ingrese la descripción de la imagen aquí

Desglose del 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
fuente
Recibo un error que dice'A' has fewer columns than were specified in the column list
Jesan Fafon
@JesanFafon Asegúrese de que su variable de entrada @i esté configurada correctamente. 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'. Desafortunadamente, no puedo probar en este momento y SQLfiddle no está jugando bien para 2012.
MickyT
Buen trabajo con funciones de geometría SQL. ¡Buenas noticias! La entrada por tabla preexistente ahora está explícitamente permitida . La creación de tablas y la población no necesitan incluirse en el recuento de bytes.
BradC
Golfé algunos personajes. El enlace no produce un resultado. Pero funciona en el estudio de administración de servidores ms-sql. El guión está aquí , disfruta. Siéntase libre de usarlo
t-clausen.dk
@ t-clausen.dk gracias por eso, pero como voy a actualizarlo, lo cambiaré a la entrada de tabla permitida. No iba a dragar esta copia de seguridad, pero ...
MickyT
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}]

Recuerdo por la discusión en el sandbox que se suponía que este enfoque era válido, pero no estoy completamente seguro de cómo se ajusta a la nueva redacción de las reglas, así que @Lilac, avíseme si cree que esto viola las reglas.

Básicamente, estoy creando una condición lógica que es verdadera para todos los puntos dentro de la nube y falsa para todos los puntos fuera de ella. Estoy alimentando aquello RegionPlotque luego representa la región de todos los puntos donde está la expresión True, así como un contorno a su alrededor.

ingrese la descripción de la imagen aquí

Sin golf:

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
fuente
1
ImplicitRegionencuentra automáticamente los valores adecuados de x e y para el trazado. 122 caracteres:s = StringSplit; RegionPlot@ ImplicitRegion[ Or @@ (((x - #)^2 + (y - #2)^2 < #3^2) & @@@ (ToExpression[#~s~","] &@(s@InputString[]))), {x, y}]
DavidC
@DavidCarraher Desafortunadamente, esto distorsiona la relación de aspecto de la imagen. (Bueno saber todas aquellas funciones región, aunque - también los que utilizó - Sólo he visto RegionPlothasta ahora.)
Martin Ender
Probablemente ya haya notado que ,AspectRatio-> 1el código vuelve a 149 bytes, exactamente donde está ahora.
DavidC
2
¿Soy yo o esta imagen se parece a Marvin the Paranoid Android?
paqogomez
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)))

Requiere una consola de 80 caracteres de ancho, que sé que es la predeterminada en Windows. Funciona mejor si su consola tiene una fuente cuadrada. Aquí hay algunos extractos de algunas de las entradas de prueba.

Original:

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

Otro:

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

Agujero:

                              ############
                            ###           ##
                          ###               ##
                         ##                   #
                  ########                     #######
                ###                                   ##
              ###                                       ##
             ##                                           #
            ##                                             #
           ##                                               #
          ##                                                 #
         ##                                                   #
        ##                                                     #
       ##                                                       #
      ##                                                         #
      #                                                          #
     ##                                                           #
     #                                                            #
    ##                                                             #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
   ##                                                               #
  ##                                                                 #
  #                                                                  #
 ##                                                                   #
 #                                                                    #
##                                                                     #
#                                 ####                                 #
#                                ##   #                                #
#                               ##     #                               #
#                              ##       #                              #
#                              #        #                              #
#                              #        #                              #
#                               #      ##                              #
#                                #    ##                               #
#                                 #  ##                                #
#                                  ###                                 #
 #                                                                    ##
 #                                                                    #
  #                                                                  ##
  #                                                                  #
   #                                                                ##
    #                                                              ##
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
    #                                                              #
     #                                                            ##
     #                                                            #
      #                                                          ##
      #                                                          #
       #                                                        ##
        #                                                      ##
         #                                                    ##
          #                                                  ##
           #                                                ##
            #                                              ##
             #                                            ##
              #                                          ##
               ##                                      ###
                 ##                                  ###
                   #######                    ########
                          #                  ##
                           ##              ###
                             ##          ###
                               ###########
recursivo
fuente
1
Me encanta que esta sea la única solución de arte ascii.
vmrob
sin importaciones ... impresionante!
Richard Green
15

Python - 253 249 215 199

Este es un anuncio de la impresionante biblioteca de formas , cuyas operaciones de geometría hicieron que escribir la solución sea sencillo al dibujar los contornos de la unión de círculos superpuestos (= puntos almacenados):

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()

Salida:

tres nubes

Editar (s):

  • 249: reemplazado sys.argv[1:]por raw_input().split(), guardando unimport sys
  • 215: k={'color':'k'}lujo eliminado , reemplazado savefigporshow
  • 199: reemplazado map(float,s.split(','))poreval(s)
ojdo
fuente
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
fuente
2
Esto tiene un gran potencial para seguir jugando golf, por ejemplo, from math import*eliminando espacios innecesarios, utilizando solo nombres de variables de una letra, utilizando la comprensión de la lista (por ejemplo, cc=[z for z in a if z!=a2 and (z[0]…)]). También eche un vistazo a los consejos para jugar golf en Python .
Wrzlprmft
Puede guardar algunos caracteres usando un nombre de variable de una letra en lugar de a2.
ProgramFOX
gracias wrzl ... Probablemente comenzaré a jugar al golf esta noche (otras cosas que hacer en este momento pero quería poner una estaca en el suelo)
Richard Green
1
sí @ProgramFOX ... esta era una versión que funcionó y que pude depurar ... la acortaré esta noche ...
Richard Green el
3
@JamesWilliams si quieres tomar la batuta ... por favor hazlo ... ¡¡No soy protector del código !! Agrega a él como su propia entrada (siempre y cuando incluya el 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()

El crédito va a @ richard-green (se le dio permiso) para la solución original, lo he reducido un poco.

James Williams
fuente
77
bueno, eso tiene mi voto ...
Richard Green
1
Es posible que pueda guardar algo más importando en pylablugar de matplotlib.pyplot.
ojdo
@odjo Actualmente en el móvil, si lo usara, ¿ from pylab import *podría seguir llamando show()y scatter()sin referencias?
James Williams el
1
@JamesWilliams confirmado! Pylab es un contaminador del espacio de nombres, que incluye muchas funciones similares a MATLAB :-)
ojdo
Puede acortar esto usando [eval(i)for i in raw_input().split()]como los pitones se evalconvierten 1,2,3en una tupla. Por supuesto, también tendrá que cambiar el [x,y,r]a a (x,y,r).
KSab
7

JavaScript (E6) + HTML 322

JSFiddle

Cada círculo se subdivide en aproximadamente 100 arcos pequeños, y cada arco se dibuja si su punto medio no está dentro de ninguno de los otros 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
fuente
7

Python 274 bytes

Esto toma la entrada de stdin y verifica cada punto de la pantalla, dibujando los píxeles uno por uno a medida que avanza. No es exactamente eficiente pero sigue todas las reglas.

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()

Tenga en cuenta que la pantalla de pygame finalizará tan pronto como se complete el dibujo, no estaba seguro de si debería incluirlo como parte de mi respuesta, pero para verlo puede raw_inputagregar un final al final o agregar un pequeño bucle si desea que el sistema operativo deje de quejarse de que no responde y tal:

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

Imágenes de ejemplo:

1,4,2 5,2,1 3,1,1 3.5,2,1.2 3,3,0.7, 1,2,0.7 ingrese la descripción de la imagen aquí

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 ingrese la descripción de la imagen aquí

KSab
fuente
3
@ edc65 No estoy muy seguro de lo que quieres decir. Lo que hace con precisión es llenar cualquier píxel que esté entre 0 y 0.1 unidades (entre 0 y 2.5 píxeles) fuera de los círculos. ¿Estás diciendo que matemáticamente debería encontrar los arcos correctos para dibujar? Al leer la pregunta, no parecía que eso fuera una restricción para mí.
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)."
"

Escribe un archivo pbm en stdout.

Imagen de prueba (convertida a png):

Segunda imagen de prueba (convertida a png)

faubi
fuente