两种颜色的重叠圆


22

编写一个程序或函数,以您选择的合理格式接收以下输入:

  • 两个正整数W和H定义要生成的图像的宽度和高度。

  • 两种RGB颜色C1和C2将用于为图像着色。

  • 形式的三元组列表,(r, x, y)用于定义在图像平面中具有半径r和中心的圆x, yr是一个正整数,x并且y是任何整数。图像的左上像素为0, 0,x轴向右增加,y轴向下增加。

输出尺寸为W x H的图像,并用C1和C2着色,以使所有重叠圆所定义的两个相邻区域都不是同一颜色。

例如:如果输入是

W = 300
H = 200
C1 = (255, 200, 0)
C2 = (128, 0, 255)
Circles = (25, 50, 80), (40, 80, 120), (300, -100, 6), (17, 253, 162)

那么圆边界看起来像这样:

示例1圆边界

圆圈创建的图像中有六个不同的连续区域。每个区域必须用C1(黄色)或C2(紫色)上色,以使没有两个相邻的区域具有相同的颜色。

有两种方法可以做到这一点,它们唯一的区别是可以交换颜色:

示例1输出1 示例1输出2

因此,对于示例输入,这两个图像中的任何一个都是有效输出。

喜欢的东西是因为两个黄地区彼此相邻无效的输出。

您的输出图像应遵循以下准则:

  • 除了C1和C2,第三种中性色(例如黑色或白色)也可以用于圆形边界,只要它们的厚度不超过5像素即可。(上面的示例中存在黑色的1像素厚边界。)

  • 但是,圆边界不是必需的。这些区域可以彼此直接相邻:

    示例1输出3 示例1输出4

    这两个都是以上示例的另一个有效输出。

  • 使用圆图绘制算法或图形库提供的任何内容,圆应尽可能合理地准确。

  • 通常,不需要像素完美,但是如果输入参数越来越大地按比例缩放,则生成的图像将变得越来越准确。

  • 允许抗锯齿,但不是必需的。

  • 不允许在后台使用网格线或轴标签等。

以字节为单位的最短代码获胜。

更多例子

所有这些输入都使用不同的圈子集:

W = 100
H = 60
C1 = (255, 0, 0)
C2 = (0, 0, 255)

在任何示例中,颜色都可以交换并保持有效。

Circles =
A. empty list
B. (13, 16, 20)
C. (30, 16, 20)
D. (200, 16, 20)
E. (42, 50, 20)
F. (42, 50, 20), (17, 40, 30)
G. (42, 50, 20), (17, 20, 30)
H. (42, 50, 20), (17, 10, 30), (10, 50, 30)
I. (42, 50, 20), (17, 10, 30), (35, 50, 20)
J. (18, 36, 40), (18, 63, 40), (18, 50, 20)
K. (100, -10, -20), (60, 50, -10)
L. (18, 36, 40), (18, 63, 40), (18, 50, 20), (14, 50, 20), (5, 50, 18), (20, 0, 0), (70, 22, 0), (10000, -9970, 0), (135, 100, -80) 

A. 前A B. 前B C. 前C D. 前D
E. 可执行程序 F. 前F G. 前G H. 前H
I. 前我 J. 前J K. 前K L. 前L

确保您的输出行为与所有这些示例相似。


看起来不错,我们可以用ascii输出,例如C1为1,C2为0?
马修·鲁

@MatthewRoh不,我知道这很方便,但是需要图像。
加尔文的业余爱好

1
好吧,我想我可以算数了tikz
Wheat

1
@ MatthewRoh,netpbm是此站点上常用的图像格式。
彼得·泰勒

2
@路易斯好吧。像这样的小输入变化或使y轴上升都可以。
加尔文的业余爱好

Answers:


14

Mathematica,165个字节

ContourPlot[Cos@Tr[Boole[Norm[{x,y}-#2]<#]Pi&@@@#4],{x,0,#},{y,0,#2},PlotPoints->5!,AspectRatio->Automatic,Frame->False,ContourShading->RGBColor@@@#3,Contours->{0}]&

具有四个参数的纯函数:宽度,高度(均为整数),0和1之间的数字的有序三对数(代表两种RGB颜色)以及{r, {x, y}}用于记录半径和中心的表单项列表圈子。例如,OP中的第一个示例将使用arguments调用[300, 200, {{1, 0.784, 0}, {0.5, 0, 1}}, {{25, {50, 80}}, {40, {80, 120}}, {300, {-100, 6}}, {17, {253, 162}}}]。y轴的正向在Mathematica中指向上方。

Norm[{x,y}-#2]<#检测点是否在给定圆内;Boole[...]Pi该转换TrueFalseπ0。在所有输入圆上计算出那些π / 0之后,Tr将它们加起来Cos并将π的偶数倍转换为1,将π的奇数倍转换为–1。ContourPlot[...,Contours->{0}]然后根据值是大于还是小于用两种颜色为平面的适当区域着色0AspectRatio->Automatic使圆圈看起来像圆圈;PlotPoints->5!给出了不错的准确性(9!如果您确实想要在未来很长时间获得惊人的图像,则可以提高准确性!);Frame->False摆脱轴心;并将ContourShading->RGBColor@@@#3输入颜色用于轮廓。

示例输出,带有第一对颜色(因为它们很漂亮),但是最后一组圆是:

样本输出


11

JavaScript / SVG / HTML5,219字节

f=// for demo
(w,h,b,f,a)=>`<svg width=${w} height=${h}><rect width=${w} height=${h} fill=rgb(${b}) /><path fill=rgb(${f}) fill-rule=evenodd d=${a.map(([r,x,y])=>[`M`+x,y-r+`a`+r,r,0,0,0,0,r+r+`a`+r,r,0,0,0,0,-r-r]).join``} /></svg>`
;//demo
[[`A`, []],
 [`B`, [[13, 16, 20]]],
 [`C`, [[30, 16, 20]]],
 [`D`, [[200, 16, 20]]],
 [`E`, [[42, 50, 20]]],
 [`F`, [[42, 50, 20], [17, 40, 30]]],
 [`G`, [[42, 50, 20], [17, 20, 30]]],
 [`H`, [[42, 50, 20], [17, 10, 30], [10, 50, 30]]],
 [`I`, [[42, 50, 20], [17, 10, 30], [35, 50, 20]]],
 [`J`, [[18, 36, 40], [18, 63, 40], [18, 50, 20]]],
 [`K`, [[100, -10, -20], [60, 50, -10]]],
 [`L`, [[18, 36, 40], [18, 63, 40], [18, 50, 20], [14, 50, 20], [5, 50, 18], [20, 0, 0], [70, 22, 0], [10000, -9970, 0], [135, 100, -80]]]
 ].forEach(([c, a])=>document.write(`<nobr><tt>&nbsp;${c}.&nbsp;</tt>${f(100, 60, [255, 0, 0], [0, 0, 255], a)}</nobr><wbr>`));


10

BBC基本,120个 117字节

http://www.bbcbasic.co.uk/bbcwin/bbcwin.html下载口译员

I.w,h,R,G,B,r,g,b:V.22,4,19;16,r,g,b,275;16,R EORr,G EORg,B EORb,24,0;0;w;h;16
5I.r,x,y:V.25,4,x;h-y;25,154,r;0;:G.5

BBC Basic具有多种颜色模式,可让您根据基本逻辑运算来绘制栅格图形:或,与,异或等。

它还支持调色板重新编程,这意味着例如在这里2色图像可以将其颜色重新编程为4096色中的任何一种。这里使用的实现与原始BBC实现有一些(未记录)差异,在原始BBC实现中,不需要EOR运算符。

不打高尔夫球

  INPUTw,h,R,G,B,r,g,b:                           :REM Input size and colours
  VDU22,4                                         :REM Change to MODE 4 (2 colours) as the default mode gives odd behaviour
  VDU19,0,16,r,g,b,19,1,16,R EORr,G EORg,B EORb   :REM Reprogram the colours to R,G,B and R^r,G^g,B^b
  VDU24,0;0;w;h;16                                :REM Setup a graphics viewport of the right size, and "clear" it to change background colour
5 INPUTr,x,y                                      :REM take input coordinates
  VDU25,4,x;h-y;                                  :REM move to x,y (h-y required as BBC BASIC y axis increases upward, reverse of spec)
  VDU25,154,r;0;                                  :REM draw circle in "logical inverse colour" of existing pixels (this implementation seems however to XOR with colour 1 instead)
  GOTO5                                           :REM repeat infinitely until user presses escape

典型输出画面

示例图像按10单位放大/ 5像素放大(BBC基本使用1像素= 2单位。)

在此处输入图片说明


10

MATL30 29 25字节

2ZG:i:!J*+2&!-|i<so2&!1YG

输入格式:

  • Colormap作为介于0到255之间的值的矩阵,其中每行定义一种颜色
  • w ^
  • H
  • 基于1的中心坐标的列向量作为复数值(x是实部,y是虚部)
  • 半径的列向量。

MATL Online上尝试要么验证最后一个测试用例。(解释器仍处于试验阶段。您可能需要刷新页面,如果不起作用,请重试)。

说明

该代码使用复数来定义点的网格并计算距离,并在广播中大量使用数组运算。

2ZG    % Implicitly input matrix of colors. Set as colormap
:      % Implicitly input W. Push [1 2 ... W]
i:     % Input H. Push [1 2 ... H]
!J*    % Transpose, multiply by 1i
+      % Add element-wise with broadcast. Gives H×W grid of points as
       % complex numbers, 1-based 
2&!    % Permute first dimension with the third. Gives a 1×W×H array
-|     % Implicitly input center coordinates. Subtract grid from them,
       % element-wise with broadcast. Gives a C×H×W array, where C is the
       % number of circles
i      % Input column vector of circle radii
<      % Less than, element-wise with broadcast
so     % Sum along first dimension, modulo 2. Gives a 1×W×H array
2&!    % Permute first dimension with the third. Gives a a H×W array
1YG    % Display as scaled image

2
我说保存那些字节!:D
格雷格·马丁

1
@GregMartin你是对的。谁会在乎可以保存4个字节的高雅!:-)做
路易斯·门多

1
@LuisMendo codegolf越短越好,无论它变得多么丑陋。;)
Kevin Cruijssen

6

使用Python pypng140个 138字节

import png
f=lambda W,H,c,d,C:png.from_array([[[c,d][sum(abs(x-X+1j*(y-Y))<r for r,x,y in C)%2]for X in range(W)]for Y in range(H)],'RGB')

用法示例:

W = 100
H = 60
C1 = (255, 0, 0)
C2 = (0, 0, 255)
Circles = (18, 36, 40), (18, 63, 40), (18, 50, 20), (14, 50, 20), (5, 50, 18), (20, 0, 0), (70, 22, 0), (10000, -9970, 0), (135, 100, -80)
f(W, H, C1, C2, Circles).save('test.png')

感谢xnor节省2个字节。


欢迎参加编码高尔夫!要检查点是否在圆上,一个技巧是使用复杂的范数:abs(x-X+1j*(y-Y))<r
xnor

3

数学(非竞争性)

(idk如何在PPCG中做LaTeX,所以我使用了LaTeX to png工具)

说明

多个圆方程((x-a)^2+(y-b)^2-r^2)> = 0 的乘积将构成该问题所需的图形。在等式中,n是数组的大小,(x, y or r)_k是第kth个(x, y, or r)元素。

(0,0,2),(2,2,2)

(谢谢WolframAlpha)

(由WolframAlpha绘制的不平等图)

WolframAlpha的获取/运行方程式

获取脚本:完成

运行脚本:尚未完成

现在使其与Mathematica一起使用...


我想知道这是否有效吗?
马修·罗

您需要列出一个特定的预先存在的解释器,该解释器将根据给定输入的所需形式绘制输出。这样就可以计算其中的字节数。目前的问题是,由于它不依赖于解释器,也不依赖于表示方程式的特定格式,因此该符号是非正式的,无法客观地进行计数。有很多程序可以在周围绘制方程式图,因此可能值得尝试找到一种简洁的输入格式。

@ ais523哦。我将尝试使其与WolframAlpha一起使用。
马修·鲁

1

Python的2.x中,166 158

import re;def f(W,H,c,d,C):print'P3',W,H,255,re.sub('[^0-9]',' ',repr([[d,c][sum([abs(x-X+1j*(y-Y))<r for r,x,y in C])%2]for Y in range(H)for X in range(W)]))

该函数在标准输出上生成一个PPM文件。

例:

W = 300
H = 200
C1 = (255, 200, 0)
C2 = (128, 0, 255)
Circles = [(25, 50, 80), (40, 80, 120), (300, -100, 6), (17, 253, 162)]

f(W, H, C1, C2, Circles)

例


1

普通Lisp + Quicklisp + ZPNG 260 + 20 = 280个字符

这是我用CL编写的最广泛的代码,如果我不做代码高尔夫,我将对其进行重组以使其更容易阅读...

前奏(20个字符)

(ql:quickload 'zpng)

打高尔夫球(260个字符)

(lambda(w h g b c)(make-instance'zpng:png :image-data(coerce(loop :for j :below h :nconc(loop :for i :below w :append(if(evenp(count t(mapcar(lambda(c)(<(abs(complex(-(cadr c)i)(-(caddr c)j)))(car c)))c)))g b)))'(array(unsigned-byte 8)(*))):width w :height h))

取消高尔夫:

(使用defun允许进行测试,并使用更长的变量名以提高可读性)

(defun mk-png (width height color1 color2 circles)
  (make-instance 'zpng:png
                 :image-data (coerce (loop :for j :below height
                                           :nconc (loop :for i :below width
                                                        :append (if (evenp (count t (mapcar (lambda (circ)
                                                                                              (< (abs (complex (- (cadr circ) i) (- (caddr circ) j)))
                                                                                                 (car circ)))
                                                                                            circles)))
                                                                    color1 color2)))
                                     '(array (unsigned-byte 8) (*)))
                 :width width
                 :height height))

用法示例:

(let ((png (mk-png 300 200 '(255 200 0) '(128 0 255) '((25 50 80) (40 80 120) (300 -100 6) (17 253 162)))))
  (zpng:write-png png #p"path/to/file.png"))

讲解

(lambda (circ)
   (< (abs (complex (- (cadr circ) i) (- (caddr circ) j)))
      (car circ)))

如果点(i,j)落在给定的圆circ内,则返回true。欧几里德距离是通过取复数的绝对值来计算的,该复数表示从(i,j)到圆心的向量。

(evenp (count t (mapcar ___
                         circles)))

在圆形列表中映射该功能,并检查给定点(i,j)是否在偶数个圆形内。

(if ____
     color1 color2)

根据测试选择颜色。

(loop :for j :below height
       :nconc (loop :for i :below width
                    :append ____))

通过循环遍历图像中的每个(i,j)并将结果列表附加在一起,收集所有rgb字节的平面列表。

(coerce ____
         '(array (unsigned-byte 8) (*)))

将字节列表转换为适当的字节数组,以便zpng可以正确提取它。

(make-instance 'zpng:png
                :image-data ____
                :width width
                :height height)

创建png对象。

(defun mk-png (width height color1 color2 circles)
   ___)

创建函数以获取宽度,高度,两种颜色和圆形列表,然后返回创建的png对象。


0

JavaScript(ES6),224个字节

我看到了JS + SVG解决方案,但是我只需要创建一个基于画布的解决方案;-)这是一个返回画布元素的函数。如果可以提供现有的canvas元素,则删除40个字节。

打电话喜欢 f(width, height, [[r1, g1, b1], [r2, g2, b2]], [[r1, x1, y1], [r2, x2, y2], ...])

let f =
(w,h,a,c,O=document.createElement`canvas`)=>{O.width=w;O.height=h;C=O.getContext`2d`;for(y=0;y<h;y++)for(x=0;x<w;x++)C.fillStyle=`rgb(${a[c.filter(([R,X,Y])=>(X-x)**2+(Y-y)**2<R**2).length%2]})`,C.fillRect(x,y,1,1);return O}

let tests = A.innerHTML.match(/.+/g);
A.innerHTML = "";
for (let i of tests) {
  let p = document.createElement("span");
  p.innerHTML = "<br>" + i.slice(0, 3);
  p.style["font-family"] = "monospace";
  A.append(p);
  A.append(f(100, 60, [[255,0,0], [0,0,255]],
    eval(`[${ i.slice(3).replace(/\(/g, "[").replace(/\)/g, "]") }]`)
  ));
}
<div id=A>
A. 
B. (13, 16, 20)
C. (30, 16, 20)
D. (200, 16, 20)
E. (42, 50, 20)
F. (42, 50, 20), (17, 40, 30)
G. (42, 50, 20), (17, 20, 30)
H. (42, 50, 20), (17, 10, 30), (10, 50, 30)
I. (42, 50, 20), (17, 10, 30), (35, 50, 20)
J. (18, 36, 40), (18, 63, 40), (18, 50, 20)
K. (100, -10, -20), (60, 50, -10)
L. (18, 36, 40), (18, 63, 40), (18, 50, 20), (14, 50, 20), (5, 50, 18), (20, 0, 0), (70, 22, 0), (10000, -9970, 0), (135, 100, -80)
</div>

输出示例:

两色圆圈


0

Löve2D,353个字节。

o=love.graphics
a=arg
w,h,r,g,b,R,G,B=...c={}for i=9,#a,3 do
c[#c+1]={a[i],a[i+1],a[i+2]}end
C=o.newCanvas(w,h)o.setCanvas(C)o.clear(R,G,B)for k,v in pairs(c)do
o.stencil(function()o.circle("fill",v[2],v[3],v[1],9^3)end,"invert",1,true)end
o.setStencilTest("greater",0)o.setColor(r,g,b)o.rectangle("fill",0,0,w,h)local
C:newImageData():encode("png","c")
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.