Маленький Чендлер грустный. Нарисуй ему облако, чтобы подбодрить его

57

Маленький Чендлер грустный. Нарисуй ему облако, чтобы подбодрить его.
Примечание: рисование облака на самом деле не поднимет его настроение.

Круг может быть определен как 3-кортеж, (x,y,r)где x- это положение x круга на декартовой плоскости, yэто положение y круга на декартовой плоскости и rрадиус этого круга. xи yможет быть отрицательным. rвсегда позитивно Вход представляет собой список окружностей в виде разделенных пробелами 3-х кортежей. Например:

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,11 радиус. 3,2,1.5Означает» круг с центральной точкой на 3,21,5 радиуса.

Если мы нарисуем все эти круги ввода на графике, это будет выглядеть так (я добавил линии сетки и метки только для ясности; они не обязательны):

график

Обратите внимание, как все круги сплочены . То есть все они перекрываются друг с другом, так что он образует одну большую группу без каких-либо маленьких групп кругов, отделенных от остальных. Вход гарантированно будет согласованным.

Предположим теперь, что мы нарисуем линию, которая проходит вокруг «границы», образованной этими кругами, без каких-либо других линий. Это все равно что нарисовать границу силуэта, образованного всеми кругами. Получившееся облако будет выглядеть примерно так:

облако

Таким образом, это облако было сформировано путем рисования только дуг окружностей на входе, которые образуют границу, в результате чего получается единая фигура. Другими словами, облако формируется только путем рисования дуг, которые не находятся внутри другого круга. Ваша программа примет входные данные в форме, описанной выше, и выведет изображение, отображающее полученное облако. Общая форма облака должна быть правильной, но масштаб, цвет, толщина линий и то, как они выглядят на вершинах, зависит от вас. Обратите внимание, что облако должно быть видимым, поэтому вы не можете нарисовать что-то вроде «Эта программа рисует белое облако на белом фоне», «Эта программа рисует облако в бесконечно малом масштабе», «Эта программа рисует облако с 0 толщина линии »и т. д. Также обратите внимание, что цвет рамки должен отличаться от цвета заливки или фона.

Другой пример. Входные данные:

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

Выход:

cloud2

Если в облаке есть «дыра», вы также должны нарисовать эту дыру. Входные данные:

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 

Выход:

cloud3

Вот важное правило: ваша программа должна рисовать только те линии, которые образуют границу. Это означает, что вы НЕ МОЖЕТЕ просто нарисовать круги полностью, а затем нарисовать круги немного меньшего размера с белой заливкой - потому что этот метод по-прежнему рисует линии, которые не образуют границы, он просто покрывает их впоследствии. Цель правила состояла в том, чтобы предотвратить реализацию «нарисовать круги, а затем снова нарисовать круги с белой заливкой» или что-нибудь подобное. Ожидается, что ответ на самом деле рассчитать, где рисовать вещи, прежде чем рисовать его.

Это код гольф, поэтому выигрывает самое короткое число персонажей.

абсент
источник
13
+1 за вопрос с графическим выводом с объективным критерием победы (и первый абзац).
Деннис
2
Как вы можете сказать, если мы рисуем линию и стираем ее потом? Рендерит ли указанные строки на внутренние растровые изображения? Если нет, то где находится граница между вектором и растровым представлением? Если да, почему бы не позволить нам сделать то же самое с основным холстом (который, как мы знаем, имеет двойную буферизацию, чтобы пользователь не мог видеть наши временные строки)?
Джон Дворжак
1
@JanDvorak Цель правила состояла в том, чтобы предотвратить реализацию «нарисовать круги, а затем снова нарисовать круги с белой заливкой», или что-то похожее на это. Ожидается, что ответ на самом деле рассчитать, где рисовать вещи, прежде чем рисовать его. Я отредактирую, чтобы сделать это более ясным.
Абсент
15
Этот вопрос очень веселый с установленным Cloud to Butt ( chrome.google.com/webstore/detail/cloud-to-butt-plus/… ).
Эрти Сейдохл
9
@SomeKittens Я потерял его в «Если в облаке есть« дыра », вы должны также нарисовать эту дыру».
Эрти Сейдохл

Ответы:

25

Mathematica 177 126 121 119

Решение по регионам диска: подход математика

Логика заключается в

  • Создать область 1 (R1), круги (без их внутренних частей);
  • Создайте Region 2 (R2), диски (без границ круга).
  • Создайте регион 3 (R3 = R1-R2).
  • -

вывод региона

Это именно тот подход, который принят ниже. Он произвел 3 цифры выше.

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 + х) ^ 2 + (-2 + у) ^ 2 == 2,25 || (-1 + x) ^ 2 + (-2 + y) ^ 2 == 0,49 || (-0,9 + х) ^ 2 + (-1,2 + у) ^ 2 == 1,44 || (-1 + x) ^ 2 + y ^ 2 == 0.64, {x, y}],
ImplicitRegion [(- 3 + x) ^ 2 + (-1 + y) ^ 2 <1 || (-3 + х) ^ 2 + (-2 + у) ^ 2 <2,25 || (-1 + x) ^ 2 + (-2 + y) ^ 2 <0,49 || (-0,9 + х) ^ 2 + (-1,2 + у) ^ 2 <1,44 || (-1 + x) ^ 2 + y ^ 2 <0.64, {x, y}]]


Решение по регионам диска: подход инженера (119 символов)

Следующее берет объединение областей диска, дискретизирует эту область и находит ее границу. Точки на диаграмме разграничивают интервалы сетки Делоне. Мы отображаем дискретизированную область ниже, чтобы выделить объект, представляющий интересующую границу (контур облака).

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[]])]
DavidC
источник
Сбрил 5 байтов:RegionBoundary@DiscretizeRegion@RegionUnion[{#,#2}~Disk~#3&@@@ToExpression[#~s~","]&@s@InputString[s=StringSplit]]
Мартин Эндер
Потенциально s=StringSplitвнутри подсказки? Попробуйте переместить это вперед, должно быть все еще короче, чем ваша текущая версия.
Мартин Эндер
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
MickyT
источник
Я получаю сообщение об ошибке говорящее'A' has fewer columns than were specified in the column list
JESAN Fafon
@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
Хорошая работа с функциями геометрии SQL. Хорошие новости! Ввод по существующей таблице теперь явно разрешен . Создание таблицы и заполнение не должны быть включены в число байтов.
BradC
Я играл в гольф несколько персонажей. Ссылка не дает результата. Но это работает в студии управления сервером ms-sql. Сценарий здесь , наслаждайтесь. Не стесняйтесь использовать его
t-clausen.dk
@ t-clausen.dk спасибо за это, но так как я собираюсь обновить его, я изменю его на разрешенный ввод таблицы. Я не собирался возвращаться, но ...
MickyT
23

Mathematica, 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а также контур вокруг него.

введите описание изображения здесь

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}
]
Мартин Эндер
источник
1
ImplicitRegionавтоматически находит правильные значения x и y для построения графика. 122 s = StringSplit; RegionPlot@ ImplicitRegion[ Or @@ (((x - #)^2 + (y - #2)^2 < #3^2) & @@@ (ToExpression[#~s~","] &@(s@InputString[]))), {x, y}]
символа
@DavidCarraher К сожалению, это искажает соотношение сторон изображения. (Приятно знать, что все эти функции региона - в том числе и те, которые вы использовали - я видел RegionPlotдо сих пор.)
Мартин Эндер,
Вы, наверное, уже заметили, что ,AspectRatio-> 1код возвращается к 149 байтам, именно там, где он сейчас стоит.
DavidC
2
Это я или это изображение выглядит как Марвин Параноидальный Android?
Пакогомес
16

Python 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 art.
vmrob
нет импорта ... впечатляет!
Ричард Грин
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()

Выход:

три облака

Edit (ы):

  • 249: Заменено sys.argv[1:]на raw_input().split(), экономяimport sys
  • 215: удалена k={'color':'k'}роскошь, заменена savefigнаshow
  • 199: Заменено map(float,s.split(','))наeval(s)
ojdo
источник
11

Питон - 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
Вы можете сохранить некоторые символы, используя вместо одной буквы имя переменной a2.
Программа Fox
спасибо wrzl ... Я, вероятно, начну играть в гольф сегодня вечером (другие вещи, которые нужно сделать прямо сейчас, но хотел поставить кол в землю)
Ричард Грин,
1
да @ProgramFOX ... это была версия, которая работала и которую я мог бы отладить ... получу ее короче сегодня вечером ...
Ричард Грин
3
@JamesWilliams, если вы хотите принять эстафету ... пожалуйста, сделайте .. Я не защищаю код !! Не стесняйтесь добавлять его как свою собственную запись (при условии, что вы указали оригинал!)
Ричард Грин
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
@odjo В настоящее время на мобильном телефоне, если бы я использовал from pylab import *, смогу ли я позвонить show()и scatter()без каких-либо ссылок?
Джеймс Уильямс
1
@JamesWilliams подтвердил! Pylab - это загрязнитель пространства имен, включающий многие функции, подобные MATLAB :-)
ojdo
Вы можете сократить это, используя [eval(i)for i in raw_input().split()]как питон evalпревращается 1,2,3в кортеж. Вы также , конечно , придется изменить [x,y,r]к (x,y,r).
KSab
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>
edc65
источник
7

Python 274 байта

Он принимает входные данные от стандартного ввода и проверяет каждую точку на экране, рисуя пиксели один за другим. Не совсем эффективно, но следует всем правилам.

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 введите описание изображения здесь

KSab
источник
3
@ edc65 Я не совсем уверен, что ты имеешь в виду. Он точно заполняет любой пиксель, который находится между 0 и 0,1 единицами (между 0 и 2,5 пикселями) за пределами кругов. Вы говорите, что математически должны найти правильные дуги для рисования? Когда я прочитал вопрос, мне показалось, что это не было ограничением.
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)."
"

Записывает файл pbm в стандартный вывод.

Тестовое изображение (преобразуется в png):

Второе тестовое изображение (преобразованное в png)

faubi
источник