2008-11-24 5 views
8

Ein wenig über T-SQL lernen, und eine interessante Übung wäre, ein Mandelbrot-Set damit zu erzeugen.Wie man ein Mandelbrot mit T-SQL erzeugt?

Stellt sich heraus, jemand hat bereits (und vor kurzem scheint es). Ich werde es jemand anderen als Antwort geben lassen, aber ich bin gespannt, welche Optimierungen gemacht werden können.

Alternativ, was würden Sie tun, um den Code lesbarer zu machen?

Ich wähle die lesbarste (und doch relativ kompakte) Version als akzeptierte Antwort aus (zu schade, dass wir noch keine Rep-Bounties haben!), Es sei denn, jemand kommt wirklich mit einer großartigen Optimierung.

Bonuspunkte zu diesen Antworten, die mir etwas über T-SQL beibringen.

-Adam

Antwort

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

Von 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 http://img.thedailywtf.com/images/200811/madlebrot.png

+0

Am besten im Textmodus natürlich angesehen .. – GregD

+1

Sorry, sollte das Bild von dem, wie es aussieht, enthalten. – Elie

+1

Das ist einfach nur böse ;-) – toolkit

5

Hoffentlich lehrt dieses ein wenig über T-SQL als auch, Es tut alles in einem Satz basierten Ansatz, der ist TSQL-Stärke (dh keine while-Schleifen) oder Variablen:

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

Haha, netter Trick "keine Schleifen oder Variablen", mit Ausnahme der "GO 257", die im Wesentlichen eine Schleife ist. Immer noch ziemlich cool. – ConstantineK

1
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