小钱德勒很伤心。画他的云,使他振作起来


57

小钱德勒很伤心。画他的云使他振作起来。
注意:画云实际上不会使他振作起来。

圆可以定义为三元组(x,y,r),其中x是圆在笛卡尔平面上的x位置,是圆在笛卡尔平面y上的y位置以及圆r的半径。xy可能是负面的。r永远是积极的。输入是以空格分隔的三元组形式的圆的列表。例如:

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

3,1,1意思是“在与中心点的圆3,1与1个半径。3,2,1.5是指”在与中心点的圆3,2用1.5半径。

如果我们在图形上绘制输入的所有这些圆,则看起来像这样(我仅出于清晰起见添加了网格线和标签;它们不是必需的):

图形

注意所有的圆是如何凝聚的。也就是说,它们全部重叠在一起,从而形成一个大的组,而没有其他的小圈子。输入保证是内聚的。

假设现在绘制一条绕这些圆形成的“边界”行进的线,而没有其他任何线。就像绘制所有圆组成的轮廓的边界一样。生成的云看起来像这样:

云

因此,仅通过在输入中绘制形成边界的圆弧来形成单一形状即可形成此云。换句话说,仅通过绘制不在另一个圆内的圆弧来形成云。您的程序将以上述形式接受输入,并输出显示结果云的图像。云的整体形状必须正确,但是比例,颜色,线条粗细以及在顶点处的外观取决于您。请注意,云必须是可见的,因此您不能拉出类似“此程序在白色背景上绘制白色云”,“此程序以无限小的比例绘制云”,“此程序以0绘制云”之类的内容。线宽”等。还请注意,边框的颜色必须与填充或背景的颜色不同。

另一个例子。输入:

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

输出:

云2

如果云中存在“洞”,则也应绘制该洞。输入:

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 

输出:

云3

这是一条重要规则:您的程序必须绘制形成边框的线。这意味着您不能简单地完全绘制圆,然后用白色填充将圆绘制得稍小一些,因为该方法仍会绘制不形成边界的线,之后只会将其覆盖。该规则的目的是防止“绘制圆,然后用白色填充再次绘制圆”的实现或类似的方法。预计答案将在绘制之前实际计算出绘制对象的位置。

这是代码高尔夫球,因此最短的字符数获胜。


13
+1为带有客观获胜标准的图形输出问题(和第一段)。
丹尼斯

2
您怎么知道我们是否画一条线然后抹去呢?将上述线条渲染到内部位图上可以吗?如果不是,向量和位图表示之间的边界在哪里?如果是,为什么不让我们对主画布执行相同操作(我们知道它是双缓冲的,因此用户看不到我们的临时行)?
约翰·德沃夏克

1
@JanDvorak规则的目的是防止“绘制圆圈,然后用白色填充再次绘制圆圈”实现,或类似的实现。预计答案将绘制之前实际计算出绘制对象的位置。我将进行编辑以使其更加清晰。
苦艾酒

15
安装了Cloud to Butt(chrome.google.com/webstore/detail/cloud-to-butt-plus/…),这个问题绝对很有趣。
Erty Seidohl 2014年

9
@SomeKittens我在“如果云中存在“洞”,则也应绘制该洞”时丢失了它。
Erty Seidohl 2014年

Answers:


25

数学177 126 121 119

按磁盘区域求解:数学家的方法

逻辑是

  • 创建区域1(R1),即圆圈(不包括内部);
  • 创建区域2(R2),磁盘(无圆圈边界)。
  • 创建区域3(R3 = R1-R2)。
  • --

区域推断

这正是下面采用的方法。它产生了上面的三个数字。

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]

隐式区域#1是圆的并集。隐式区域2是位于圆内的磁盘的并集。他们的区别是边界。

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}],
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}]]


按磁盘区域求解:工程师的方法(119个字符)

下面采用磁盘区域的并集,离散化该区域,并找到其边界。图中的点划定了Delaunay网格的间隔。我们在下面显示离散区域,以突出显示提供感兴趣边界(云的轮廓)的对象。

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”

区域边界是离散的。

reg1


通过检测边缘解决:摄影师的方法-121个字符

边缘检测

它以黑色绘制磁盘,光栅化图像,检测边缘并反转黑白。

s=StringSplit;ColorNegate@EdgeDetect@Rasterize@Graphics[Disk[{#,#2},#3]&@@@
((ToExpression/@s[#,","])&/@s[InputString[]])]

缩减5个字节:RegionBoundary@DiscretizeRegion@RegionUnion[{#,#2}~Disk~#3&@@@ToExpression[#~s~","]&@s@InputString[s=StringSplit]]
Martin Ender 2014年

潜在的s=StringSplit内部提示?尝试再次将其移到最前面,但仍应比当前版本短。
Martin Ender 2014年

27

T-SQL 235 234 229 212 171 73字节

这利用了SQL Server 2012+中的空间功能。当它在SSMS中运行时(SQL Server Management Studio)将产生一个空间结果窗格。 输入来自变量@i。如果可以从表中获取输入,我可以进一步减少它。

由于现在允许表输入。

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

我在下面留下了先前的解决方案。

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

编辑:删除流浪空间,过剩和子查询

171:将表创建替换为CTE,将@s替换为@。

在此处输入图片说明

动态SQL的分解

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

'A' has fewer columns than were specified in the column list
说错了

@JesanFafon确保正确设置了输入变量@i。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'。不幸的是,我目前无法测试,SQLfiddle在2012
表现也不佳。– MickyT 2014年

SQL几何函数很好用。好消息!现在明确允许使用预先存在的表进行输入。表的创建和填充不必包含在字节数中。
BradC

我打了几个角色。链接不会产生结果。但是它可以在ms-sql服务器管理工​​作室中使用。脚本在这里,尽情享受。随时使用它
t-clausen.dk

@ t-clausen.dk对此表示感谢,但是由于我将对其进行更新,因此我将其更改为允许的表输入。我本来不会疏通备份的,但是……
MickyT

23

数学,175个 158 149字节

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}]

我记得在沙盒中的讨论中该方法应该是有效的,但是我不完全确定它与规则的新措辞之间的关系,因此@Lilac,让我知道您是否认为这违反了规则。

基本上,我正在创建一个逻辑条件,该条件对云内部的所有点都为真,而对云外部的所有点均为假。我正在提供该内容RegionPlot,然后呈现表达式所在的所有点的区域True以及其周围的轮廓。

在此处输入图片说明

取消高尔夫:

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}
]

1
ImplicitRegion自动找到适当的x和y值进行绘图。122个字符:s = StringSplit; RegionPlot@ ImplicitRegion[ Or @@ (((x - #)^2 + (y - #2)^2 < #3^2) & @@@ (ToExpression[#~s~","] &@(s@InputString[]))), {x, y}]
DavidC

@DavidCarraher不幸的是,这会扭曲图像的纵横比。(虽然很高兴知道所有这些区域函数-以及您所使用的那些函数- RegionPlot到目前为止我只看过。)
Martin Ender 2014年

您可能已经注意到,这,AspectRatio-> 1使代码重新回到了149个字节,与现在的位置完全一样。
DavidC 2014年

2
是我还是这张图片看起来像Marvin the Paranoid Android?
paqogomez

16

蟒3.3(183个 177 164个 160字节)

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

它需要一个80字符宽的控制台,我知道这是Windows的默认设置。如果您的控制台为方形字体,则效果最佳。以下是一些测试输入的摘录。

原版的:

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

另一个:

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

洞:

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

1
我喜欢这是唯一的ASCII艺术解决方案。
vmrob 2014年

没有进口...令人印象深刻!
理查德·格林

15

蟒蛇- 253 249 215 199

这是一个很棒的匀称库的广告,它的几何运算通过绘制重叠圆并(=缓冲点)的联合轮廓来使编写解决方案变得简单:

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

输出:

三朵云

编辑:

  • 249:替换sys.argv[1:]raw_input().split(),保存一个import sys
  • 215:删除k={'color':'k'}奢华,取而代之savefigshow
  • 199:替换map(float,s.split(','))eval(s)

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

2
这具有很大的潜力,例如通过from math import*删除无用空格,仅使用一个字母的变量名,使用列表理解(例如cc=[z for z in a if z!=a2 and (z[0]…)])来进行进一步的挖掘。还可以看看Python打高尔夫球技巧
Wrzlprmft 2014年

您可以使用一个字母的变量名代替来保存一些字符a2
ProgramFOX 2014年

谢谢wrzl ...我今晚可能会开始打高尔夫球(其他目前正在做的事情,但想放一部分钱)
理查德·格林

1
是的@ProgramFOX ...这是一个有效的版本,我可以调试..它将使其在今晚更短...
Richard Green

3
@JamesWilliams,如果你想拿接力棒...请做..我对代码没有保护!随时将其添加为您自己的条目(只要您注明原文即可!)
Richard Green

9

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

最初的解决方案功劳归功于@ richard-green(已获得许可),我只是稍微降低了一下。


7
好让我投票……
理查德·格林

1
您也许可以通过导入pylab而不是来保存更多内容matplotlib.pyplot
ojdo 2014年

目前@odjo移动,如果我用from pylab import *我仍然能够调用show()scatter()没有任何的参考?
詹姆斯·威廉姆斯

1
@JamesWilliams确认!Pylab是一个名称空间污染者,包括许多类似MATLAB的函数:-)
ojdo

您可以通过将[eval(i)for i in raw_input().split()]python eval变成1,2,3元组来缩短此时间。您当然也必须将更[x,y,r]改为(x,y,r)
KSab 2014年

7

JavaScript(E6)+ HTML 322

JSFiddle

每个圆细分为约100个小圆弧,并且如果圆弧的中点不在其他任何圆内,则绘制每个圆弧。

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

7

Python 274字节

这从stdin接收输入,并检查显示器上的每个点,并一一画出像素。效率不高,但遵循所有规则。

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

请注意,pygame显示会在绘图完成后立即终止,我不确定是否应将其作为答案的一部分,但要查看它,您可以raw_input在末尾添加一个或如果您添加一个小循环,想要阻止操作系统抱怨它没有响应,例如:

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

图片示例:

1,4,2 5,2,1 3,1,1 3.5,2,1.2 3,3,0.7, 1,2,0.7 在此处输入图片说明

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 在此处输入图片说明


3
@ edc65我不太清楚您的意思。精确地执行的操作是在圆外填充0到0.1个单位之间(0到2.5个像素之间)的任何像素。您是说应该在数学上找到正确的弧线绘制吗?从阅读问题开始,似乎对我来说并不是一个限制。
KSab 2014年

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)."
"

将pbm文件写入stdout。

测试图像(转换为png):

第二张测试图像(转换为png)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.