How to generate a Mandelbrot with T-SQL?

廉价感情. 提交于 2019-12-03 06:18:44

问题


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


回答1:


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



回答2:


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


(source: thedailywtf.com)




回答3:


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



回答4:


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


来源:https://stackoverflow.com/questions/314864/how-to-generate-a-mandelbrot-with-t-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!