如何使用 T-SQL 生成 Mandelbrot?

发布于 2024-07-09 12:10:21 字数 267 浏览 11 评论 0原文

学习了一些关于 T-SQL 的知识,并认为一个有趣的练习是用它生成 Mandelbrot 集。

事实证明已经有人拥有了(而且最近出现了)。 我会让其他人将其作为答案发布,但我很好奇可以进行哪些优化。

或者,您会采取什么措施使代码更具可读性?

我将选择最具可读性(但相当紧凑)的版本作为接受的答案(太糟糕了,我们还没有代表赏金!),除非有人确实进行了出色的优化。

奖励点是那些教我一些关于 T-SQL 的答案。

-亚当

Learning a little about T-SQL, and thought an interesting exercise would be to generate a Mandelbrot set with it.

Turns out someone already has (and recently, it appears). I'll let someone else post it as an answer, but I'm curious what optimizations can be made.

Alternately, what would you do to make the code more readable?

I'll select the most readable (yet reasonably compact) version as the accepted answer (too bad we don't have rep bounties yet!) unless someone really comes along with a great optimization.

Bonus points to those answers that teach me a little something about T-SQL.

-Adam

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

往日情怀 2024-07-16 12:10:21

来自 thedailywtf.com

-- AUTHOR: GRAEME JOB
-- CREATED: 12-OCT-2008
-- BECAUSE: SINGLE SQL COMMAND < 50 LINES. JUST BECAUSE.
WITH 
      XGEN(X, IX) AS (              -- X DIM GENERATOR
            SELECT CAST(-2.2 AS FLOAT) AS X, 0 AS IX UNION ALL
            SELECT CAST(X + 0.031 AS FLOAT) AS X, IX + 1 AS IX
            FROM XGEN
            WHERE IX < 100
      ),
      YGEN(Y, IY) AS (              -- Y DIM GENERATOR
            SELECT CAST(-1.5 AS FLOAT) AS Y, 0 AS IY UNION ALL
            SELECT CAST(Y + 0.031 AS FLOAT) AS Y, IY + 1 AS IY
            FROM YGEN
            WHERE IY < 100
      ),
      Z(IX, IY, CX, CY, X, Y, I) AS (           -- Z POINT ITERATOR
            SELECT IX, IY, X, Y, X, Y, 0
            FROM XGEN, YGEN   
            UNION ALL
            SELECT IX, IY, CX, CY, X * X - Y * Y + CX AS X, Y * X * 2 + CY, I + 1
            FROM Z
            WHERE X * X + Y * Y < 16
            AND I < 100
      )
SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
      REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
      REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
      (X0+X1+X2+X3+X4+X5+X6+X7+X8+X9+X10+X11+X12+X13+X14+X15+X16+X17+X18+X19+
      X20+X21+X22+X23+X24+X25+X26+X27+X28+X29+X30+X31+X32+X33+X34+X35+X36+X37+X38+X39+
      X40+X41+X42+X43+X44+X45+X46+X47+X48+X49+X50+X51+X52+X53+X54+X55+X56+X57+X58+X59+
      X60+X61+X62+X63+X64+X65+X66+X67+X68+X69+X70+X71+X72+X73+X74+X75+X76+X77+X78+X79+
      X80+X81+X82+X83+X84+X85+X86+X87+X88+X89+X90+X91+X92+X93+X94+X95+X96+X97+X98+X99),
      'A',' '),   'B','.'),   'C',','),   'D',','),   'E',','),   'F','-'),   'G','-'),
      'H','-'),   'I','-'),   'J','-'),   'K','+'),   'L','+'),   'M','+'),   'N','+'),
      'O','%'),   'P','%'),   'Q','%'),   'R','%'),   'S','@'),   'T','@'),   'U','@'),
      'V','@'),   'W','#'),   'X','#'),   'Y','#'),   'Z',' ')
FROM (
      SELECT 'X' + CAST(IX AS VARCHAR) AS IX,
      IY,   SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ', ISNULL(NULLIF(I, 0), 1), 1) AS I
      FROM Z) ZT
PIVOT (
      MAX(I) FOR IX IN (
      X0,X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18,X19,
      X20,X21,X22,X23,X24,X25,X26,X27,X28,X29,X30,X31,X32,X33,X34,X35,X36,X37,X38,X39,
      X40,X41,X42,X43,X44,X45,X46,X47,X48,X49,X50,X51,X52,X53,X54,X55,X56,X57,X58,X59,
      X60,X61,X62,X63,X64,X65,X66,X67,X68,X69,X70,X71,X72,X73,X74,X75,X76,X77,X78,X79,
      X80,X81,X82,X83,X84,X85,X86,X87,X88,X89,X90,X91,X92,X93,X94,X95,X96,X97,X98,X99)
) AS PZT

结果如下
(来源:thedailywtf.com

From thedailywtf.com

-- AUTHOR: GRAEME JOB
-- CREATED: 12-OCT-2008
-- BECAUSE: SINGLE SQL COMMAND < 50 LINES. JUST BECAUSE.
WITH 
      XGEN(X, IX) AS (              -- X DIM GENERATOR
            SELECT CAST(-2.2 AS FLOAT) AS X, 0 AS IX UNION ALL
            SELECT CAST(X + 0.031 AS FLOAT) AS X, IX + 1 AS IX
            FROM XGEN
            WHERE IX < 100
      ),
      YGEN(Y, IY) AS (              -- Y DIM GENERATOR
            SELECT CAST(-1.5 AS FLOAT) AS Y, 0 AS IY UNION ALL
            SELECT CAST(Y + 0.031 AS FLOAT) AS Y, IY + 1 AS IY
            FROM YGEN
            WHERE IY < 100
      ),
      Z(IX, IY, CX, CY, X, Y, I) AS (           -- Z POINT ITERATOR
            SELECT IX, IY, X, Y, X, Y, 0
            FROM XGEN, YGEN   
            UNION ALL
            SELECT IX, IY, CX, CY, X * X - Y * Y + CX AS X, Y * X * 2 + CY, I + 1
            FROM Z
            WHERE X * X + Y * Y < 16
            AND I < 100
      )
SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
      REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
      REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
      (X0+X1+X2+X3+X4+X5+X6+X7+X8+X9+X10+X11+X12+X13+X14+X15+X16+X17+X18+X19+
      X20+X21+X22+X23+X24+X25+X26+X27+X28+X29+X30+X31+X32+X33+X34+X35+X36+X37+X38+X39+
      X40+X41+X42+X43+X44+X45+X46+X47+X48+X49+X50+X51+X52+X53+X54+X55+X56+X57+X58+X59+
      X60+X61+X62+X63+X64+X65+X66+X67+X68+X69+X70+X71+X72+X73+X74+X75+X76+X77+X78+X79+
      X80+X81+X82+X83+X84+X85+X86+X87+X88+X89+X90+X91+X92+X93+X94+X95+X96+X97+X98+X99),
      'A',' '),   'B','.'),   'C',','),   'D',','),   'E',','),   'F','-'),   'G','-'),
      'H','-'),   'I','-'),   'J','-'),   'K','+'),   'L','+'),   'M','+'),   'N','+'),
      'O','%'),   'P','%'),   'Q','%'),   'R','%'),   'S','@'),   'T','@'),   'U','@'),
      'V','@'),   'W','#'),   'X','#'),   'Y','#'),   'Z',' ')
FROM (
      SELECT 'X' + CAST(IX AS VARCHAR) AS IX,
      IY,   SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ', ISNULL(NULLIF(I, 0), 1), 1) AS I
      FROM Z) ZT
PIVOT (
      MAX(I) FOR IX IN (
      X0,X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18,X19,
      X20,X21,X22,X23,X24,X25,X26,X27,X28,X29,X30,X31,X32,X33,X34,X35,X36,X37,X38,X39,
      X40,X41,X42,X43,X44,X45,X46,X47,X48,X49,X50,X51,X52,X53,X54,X55,X56,X57,X58,X59,
      X60,X61,X62,X63,X64,X65,X66,X67,X68,X69,X70,X71,X72,X73,X74,X75,X76,X77,X78,X79,
      X80,X81,X82,X83,X84,X85,X86,X87,X88,X89,X90,X91,X92,X93,X94,X95,X96,X97,X98,X99)
) AS PZT

Here's the result
(source: thedailywtf.com)

咆哮 2024-07-16 12:10:21
Create PROCEDURE dbo.mandlebrot
@left float,
@right float,
@Top float,
@Bottom float,
@Res float,
@MaxIterations Integer = 500
As
Set NoCount On

Declare @Grid Table (
    X float Not Null, 
    Y float Not Null,
    InSet Bit
   Primary Key (X, Y))

Declare @Xo float, @Yo float, @Abs float
Declare @PtX Float, @PtY Float
Declare @Iteration Integer Set @Iteration = 0
Select @Xo = @Left, @Yo = @Bottom

While @Yo <= @Top Begin
    While @Xo <= @Right Begin
        Select @PtX = @Xo, @PtY = @Yo
        While @Iteration < @MaxIterations 
            And (Square(@PtX) + Square(@PtY)) < 4.0 Begin
            Select @PtX = Square(@PtX) - Square(@PtY) + @Xo,
                   @PtY = 2* @PtX * @PtY + @Yo
            Select @Iteration, @PtX, @PtY
            Set @Iteration = @Iteration + 1
        End
        Insert @Grid(X, Y, InSet) 
        Values(@Xo, @Yo, Case 
            When @Iteration < @MaxIterations
                    Then 1 Else 0 End)
        Set @Xo = @Xo + @res
        Set @Iteration = 0
    End
    Select @Xo = @Left, 
           @Yo = @Yo + @Res
End

Select * From @Grid
Create PROCEDURE dbo.mandlebrot
@left float,
@right float,
@Top float,
@Bottom float,
@Res float,
@MaxIterations Integer = 500
As
Set NoCount On

Declare @Grid Table (
    X float Not Null, 
    Y float Not Null,
    InSet Bit
   Primary Key (X, Y))

Declare @Xo float, @Yo float, @Abs float
Declare @PtX Float, @PtY Float
Declare @Iteration Integer Set @Iteration = 0
Select @Xo = @Left, @Yo = @Bottom

While @Yo <= @Top Begin
    While @Xo <= @Right Begin
        Select @PtX = @Xo, @PtY = @Yo
        While @Iteration < @MaxIterations 
            And (Square(@PtX) + Square(@PtY)) < 4.0 Begin
            Select @PtX = Square(@PtX) - Square(@PtY) + @Xo,
                   @PtY = 2* @PtX * @PtY + @Yo
            Select @Iteration, @PtX, @PtY
            Set @Iteration = @Iteration + 1
        End
        Insert @Grid(X, Y, InSet) 
        Values(@Xo, @Yo, Case 
            When @Iteration < @MaxIterations
                    Then 1 Else 0 End)
        Set @Xo = @Xo + @res
        Set @Iteration = 0
    End
    Select @Xo = @Left, 
           @Yo = @Yo + @Res
End

Select * From @Grid
听你说爱我 2024-07-16 12:10:21

希望这也能教会一些有关 T-SQL 的知识,它以基于集合的方法完成所有操作,这是 TSQL 的优势(即没有 while 循环)或变量:

SET NOCOUNT ON;

--populate
;WITH Numbers ([row]) AS
(
   SELECT TOP 100 CAST(ROW_NUMBER() OVER (ORDER BY NEWID()) AS FLOAT) [row]
   FROM sys.columns
)
SELECT A.row AS x, 
   B.row AS y, 
   0 AS iter, 
   A.row AS iterx, 
   B.row AS itery, 
   '.' AS symbol
INTO #GRID
FROM Numbers A, Numbers B
WHERE B.[row] <= 24
GO

-- scale
UPDATE #GRID
SET x = x * 3.0 / 100.0 - 2,
   y = y * 2.0 / 24.0 - 1,
   iterx = x * 3.0 / 100.0 - 2,
   itery = y * 2.0 / 24.0 - 1
GO

--iterate
UPDATE #GRID
SET iterx = iterx*iterx - itery*itery + x,
    itery = 2*iterx*itery + y,
    iter = iter+1
WHERE iterx*iterx+itery*itery <= 2*2
GO 257

UPDATE #GRID SET symbol = CHAR(64+(iter%26)) WHERE NOT iter = 257
GO

--print
WITH concatenated (y, c) AS 
(
   SELECT G2.y,
       (SELECT SUBSTRING(G.symbol, 1, 1) AS [data()] FROM #GRID G WHERE G.y = G2.y FOR XML PATH('')) c
   FROM (SELECT DISTINCT y FROM #GRID) AS G2
)
SELECT REPLACE(c, ' ', '') FROM concatenated ORDER BY y
GO


DROP TABLE #GRID

Hopefully, this teaches a bit about T-SQL as well, It does everything in a set based approach which is TSQL's strength (i.e. no while loops) or variables:

SET NOCOUNT ON;

--populate
;WITH Numbers ([row]) AS
(
   SELECT TOP 100 CAST(ROW_NUMBER() OVER (ORDER BY NEWID()) AS FLOAT) [row]
   FROM sys.columns
)
SELECT A.row AS x, 
   B.row AS y, 
   0 AS iter, 
   A.row AS iterx, 
   B.row AS itery, 
   '.' AS symbol
INTO #GRID
FROM Numbers A, Numbers B
WHERE B.[row] <= 24
GO

-- scale
UPDATE #GRID
SET x = x * 3.0 / 100.0 - 2,
   y = y * 2.0 / 24.0 - 1,
   iterx = x * 3.0 / 100.0 - 2,
   itery = y * 2.0 / 24.0 - 1
GO

--iterate
UPDATE #GRID
SET iterx = iterx*iterx - itery*itery + x,
    itery = 2*iterx*itery + y,
    iter = iter+1
WHERE iterx*iterx+itery*itery <= 2*2
GO 257

UPDATE #GRID SET symbol = CHAR(64+(iter%26)) WHERE NOT iter = 257
GO

--print
WITH concatenated (y, c) AS 
(
   SELECT G2.y,
       (SELECT SUBSTRING(G.symbol, 1, 1) AS [data()] FROM #GRID G WHERE G.y = G2.y FOR XML PATH('')) c
   FROM (SELECT DISTINCT y FROM #GRID) AS G2
)
SELECT REPLACE(c, ' ', '') FROM concatenated ORDER BY y
GO


DROP TABLE #GRID
楠木可依 2024-07-16 12:10:21
with points (x1,y1,x2,y2,depth) as
(
    select convert(float,-2.40), convert(float,-2.40), convert(float,2.40), convert(float,2.40), 8
    union all select x1,y1,(x1+x2)/2,(y1+y2)/2,depth-1 from points where depth>0
    union all select (x1+x2)/2,y1,x2,(y1+y2)/2,depth-1 from points where depth>0
    union all select x1,(y1+y2)/2,(x1+x2)/2,y2,depth-1 from points where depth>0
    union all select (x1+x2)/2,(y1+y2)/2,x2,y2,depth-1 from points where depth>0
),
mandelbrot(x1,y1,x2,y2,x,y,depth) as
(
    select x1,y1,x2,y2,convert(float,0),convert(float,0),20 from points where depth=0
    union all
    select x1,y1,x2,y2, x*x-y*y+x1, 2*x*y+y1,depth-1 from mandelbrot where depth > 0 and (x*x+y*y<4)
)
select geometry::STGeomFromText('POLYGON((' +
  convert(varchar,x1) + ' ' + convert(varchar,y1) + ',' +
  convert(varchar,x1) + ' ' + convert(varchar,y2) + ',' +
  convert(varchar,x2) + ' ' + convert(varchar,y2) + ',' +
  convert(varchar,x2) + ' ' + convert(varchar,y1) + ',' +
  convert(varchar,x1) + ' ' + convert(varchar,y1) + '))',0)
  from mandelbrot where depth = 0
with points (x1,y1,x2,y2,depth) as
(
    select convert(float,-2.40), convert(float,-2.40), convert(float,2.40), convert(float,2.40), 8
    union all select x1,y1,(x1+x2)/2,(y1+y2)/2,depth-1 from points where depth>0
    union all select (x1+x2)/2,y1,x2,(y1+y2)/2,depth-1 from points where depth>0
    union all select x1,(y1+y2)/2,(x1+x2)/2,y2,depth-1 from points where depth>0
    union all select (x1+x2)/2,(y1+y2)/2,x2,y2,depth-1 from points where depth>0
),
mandelbrot(x1,y1,x2,y2,x,y,depth) as
(
    select x1,y1,x2,y2,convert(float,0),convert(float,0),20 from points where depth=0
    union all
    select x1,y1,x2,y2, x*x-y*y+x1, 2*x*y+y1,depth-1 from mandelbrot where depth > 0 and (x*x+y*y<4)
)
select geometry::STGeomFromText('POLYGON((' +
  convert(varchar,x1) + ' ' + convert(varchar,y1) + ',' +
  convert(varchar,x1) + ' ' + convert(varchar,y2) + ',' +
  convert(varchar,x2) + ' ' + convert(varchar,y2) + ',' +
  convert(varchar,x2) + ' ' + convert(varchar,y1) + ',' +
  convert(varchar,x1) + ' ' + convert(varchar,y1) + '))',0)
  from mandelbrot where depth = 0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文