Skip to content

Commit 1bf1757

Browse files
Add files via upload
1 parent a208e0a commit 1bf1757

File tree

2 files changed

+380
-0
lines changed

2 files changed

+380
-0
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/*********************************************************************
2+
Scott Peters
3+
Random Walk
4+
https://advancedsqlpuzzles.com
5+
Last Updated: 07/25/2022
6+
7+
This script is written in SQL Server's T-SQL
8+
9+
---------------------------------------------------------------------
10+
11+
The following solves a random walk for the following problem:
12+
13+
You are the dinner host of a weekly gathering of 8 friends (including yourself).
14+
You want to determine who hosts the next dinner party using the following scheme:
15+
16+
After dinner, the guests sit around a round table. You (the current host) flip a fair coin.
17+
If it comes up heads, you pass it to the person on your right, and if it comes up tails, you pass it to person on your left.
18+
The person who receives the coin repeats the procedure, flipping it and passing it right or left, depending on the outcome of the flip.
19+
This process keeps going until all but one dinner guest has held the coin.
20+
The last member who has not yet touched the coin is then declared the winner and must host the next dinner party.
21+
22+
**********************************************************************/
23+
SET NOCOUNT ON;
24+
25+
---------------------
26+
---------------------
27+
--Tables used in script
28+
DROP TABLE IF EXISTS #Numbers;
29+
DROP TABLE IF EXISTS #ParticipantsASC;
30+
DROP TABLE IF EXISTS #ParticipantsDESC;
31+
DROP TABLE IF EXISTS #Participants;
32+
DROP TABLE IF EXISTS #CoinFlipResults;
33+
DROP TABLE IF EXISTS #WinnerResults;
34+
DROP TABLE IF EXISTS #WinnerResultsHistory;
35+
GO
36+
37+
---------------------
38+
---------------------
39+
--Create #WinnerResultsHistory table
40+
CREATE TABLE #WinnerResultsHistory
41+
(
42+
Iteration INTEGER IDENTITY(1,1) PRIMARY KEY,
43+
Participant INTEGER NOT NULL,
44+
CoinFlips INTEGER NOT NULL
45+
);
46+
GO
47+
48+
------------------------
49+
------------------------
50+
------------------------
51+
--Create #Numbers table
52+
CREATE TABLE #Numbers
53+
(
54+
Number INTEGER IDENTITY(0,1) PRIMARY KEY, -- Begin at 0 and increate by 1
55+
InsertDate DATETIME NOT NULL
56+
);
57+
GO
58+
59+
INSERT INTO #Numbers(InsertDate) VALUES (GETDATE());
60+
GO 300
61+
62+
------------------------
63+
------------------------
64+
------------------------
65+
--Create #ParticipantsASC table
66+
CREATE TABLE #ParticipantsASC
67+
(
68+
CoinFlipSum INTEGER IDENTITY(0,1) PRIMARY KEY, -- Begin at 0 and increase by 1
69+
Participant INTEGER
70+
);
71+
GO
72+
73+
--Create ###ParticipantsDESC table
74+
CREATE TABLE #ParticipantsDESC
75+
(
76+
CoinFlipSum INTEGER IDENTITY(-1,-1) PRIMARY KEY, -- Begin at -1 and increate by -1
77+
Participant INTEGER
78+
);
79+
GO
80+
81+
--Create #Participants table
82+
CREATE TABLE #Participants
83+
(
84+
CoinFlipSum INTEGER NOT NULL,
85+
Participant INTEGER NOT NULL
86+
);
87+
GO
88+
89+
------------------------
90+
------------------------
91+
------------------------
92+
--Create and populate the #Participants table
93+
--For simplicity, I create seperate sequences and tables
94+
DROP SEQUENCE IF EXISTS dbo.MySequenceASC;
95+
DROP SEQUENCE IF EXISTS dbo.MySequenceDESC;
96+
GO
97+
98+
--Start with 0, increment by 1
99+
CREATE SEQUENCE dbo.MySequenceASC AS INTEGER
100+
START WITH 0
101+
INCREMENT BY 1
102+
MINVALUE 0
103+
MAXVALUE 7-----------------Set to number of participants!
104+
CYCLE;
105+
GO
106+
107+
--Start with 7, increment by -1
108+
CREATE SEQUENCE dbo.MySequenceDESC AS INTEGER
109+
START WITH 7
110+
INCREMENT BY -1
111+
MINVALUE 0
112+
MAXVALUE 7-----------------Set to number of participants!
113+
CYCLE;
114+
GO
115+
116+
INSERT INTO #ParticipantsASC (Participant)
117+
SELECT (NEXT VALUE FOR dbo.MySequenceASC) AS Participant;
118+
GO 300
119+
120+
INSERT INTO #ParticipantsDESC (Participant)
121+
SELECT (NEXT VALUE FOR dbo.MySequenceDESC) AS Participant;
122+
GO 300
123+
124+
INSERT INTO #Participants (CoinFlipSum, Participant)
125+
SELECT CoinFlipSum, Participant FROM #ParticipantsASC
126+
UNION ALL
127+
SELECT CoinFlipSum, Participant FROM #ParticipantsDESC;
128+
GO
129+
130+
------------------------
131+
------------------------
132+
------------------------
133+
--Perform an evaluation of the #Participants and #Numbers table
134+
--Ensure you have enough records in the #Participants and #Numbers tables
135+
IF((SELECT COUNT(*) FROM #Participants) < (SELECT COUNT(*) FROM #Numbers))
136+
BEGIN
137+
PRINT('#Participants record count is less than #Numbers')
138+
RETURN;
139+
END;
140+
GO
141+
------------------------
142+
------------------------
143+
------------------------
144+
--Create table #CoinFlipResults
145+
CREATE TABLE #CoinFlipResults
146+
(
147+
StepNumber INTEGER PRIMARY KEY,
148+
WindowSum INTEGER
149+
);
150+
GO
151+
152+
------------------------
153+
------------------------
154+
------------------------
155+
--Create table #WinnerResults
156+
CREATE TABLE #WinnerResults
157+
(
158+
Participant INTEGER PRIMARY KEY,
159+
StepNumberFirstTouched INTEGER
160+
);
161+
GO
162+
163+
------------------------
164+
------------------------
165+
------------------------
166+
--Set the number of iterations
167+
DECLARE @Iterations INTEGER = 1000;
168+
169+
------------------------
170+
------------------------
171+
------------------------
172+
--Perform the random walk
173+
WHILE @Iterations >= 1
174+
BEGIN
175+
176+
SET @Iterations = @Iterations - 1;
177+
178+
TRUNCATE TABLE #CoinFlipResults;
179+
TRUNCATE TABLE #WinnerResults;
180+
181+
------------------------
182+
------------------------
183+
------------------------
184+
--Insert into #CoinFlipResults table
185+
;WITH cte_RandomNumber AS
186+
(
187+
SELECT Number AS StepNumber
188+
,ABS(CHECKSUM(NEWID()) % 2) + 1 AS RandomNumber
189+
FROM #Numbers
190+
WHERE Number > 0
191+
),
192+
cte_Pass AS
193+
(
194+
SELECT StepNumber
195+
,(CASE RandomNumber WHEN 1 THEN -1 WHEN 2 THEN 1 END) AS PassDetermination
196+
FROM cte_RandomNumber
197+
)
198+
INSERT INTO #CoinFlipResults
199+
SELECT StepNumber
200+
,SUM(PassDetermination) OVER (ORDER BY StepNumber) AS WindowSum
201+
FROM cte_Pass
202+
ORDER BY StepNumber;
203+
204+
------------------------
205+
------------------------
206+
------------------------
207+
--Insert into #WinnerResults table
208+
WITH cte_ResultsView AS
209+
(
210+
SELECT A.*, '----' AS ID, B.*
211+
FROM #CoinFlipResults a LEFT OUTER JOIN
212+
#Participants b on a.WindowSum = b.CoinFlipSum
213+
)
214+
INSERT INTO #WinnerResults
215+
SELECT Participant,
216+
MIN(StepNumber) AS StepNumberFirstTouched
217+
FROM cte_ResultsView
218+
GROUP BY Participant
219+
ORDER BY 2 DESC;
220+
221+
------------------------
222+
------------------------
223+
------------------------
224+
--Insert into #WinnerResultsHistory table
225+
INSERT INTO #WinnerResultsHistory (Participant, CoinFlips)
226+
SELECT
227+
(SELECT TOP 1 Participant FROM #WinnerResults WHERE Participant <> 0 ORDER BY StepNumberFirstTouched DESC),
228+
(SELECT TOP 1
229+
StepNumberFirstTouched
230+
FROM #WinnerResults
231+
WHERE StepNumberFirstTouched < (SELECT MAX(StepNumberFirstTouched) FROM #WinnerResults)
232+
ORDER BY StepNumberFirstTouched DESC);
233+
234+
END--END LOOP
235+
GO
236+
237+
------------------------
238+
------------------------
239+
------------------------
240+
--Display summary statistics of the results
241+
SELECT Participant,
242+
COUNT(*) AS Count,
243+
MIN(CoinFlips) AS Min,
244+
MAX(CoinFlips) AS Max,
245+
AVG(CoinFlips) AS Avg,
246+
MAX(CoinFlips) - MIN(CoinFlips) AS Range,
247+
STDEV(CoinFlips) AS StandardDeviation
248+
FROM #WinnerResultsHistory
249+
GROUP BY Participant
250+
UNION
251+
SELECT 99999 AS Participant,
252+
COUNT(*) AS Count,
253+
MIN(CoinFlips) AS Min,
254+
MAX(CoinFlips) AS Max,
255+
AVG(CoinFlips) AS Avg,
256+
MAX(CoinFlips) - MIN(CoinFlips) AS Range,
257+
STDEV(CoinFlips) AS StandardDeviation
258+
FROM #WinnerResultsHistory;
259+
GO
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*----------------------------------------------------
2+
Scott Peters
3+
Markov Chains
4+
https://AdvancedSQLPuzzles.com
5+
6+
This script is written in SQL Server's T-SQL
7+
8+
---------------------------------------------------------------------
9+
10+
Below will solve for the following:
11+
12+
In Probability Land, on a sunny day there is an equal probability of the next day being sunny or rainy.
13+
On a rainy day, there is a 70% chance it will rain the next day, and a 30% chance it will be sunny the next day.
14+
15+
On average, how many rainy days are there in Probability Land?
16+
17+
*/----------------------------------------------------
18+
19+
-------------------------------
20+
-------------------------------
21+
--Tables used in script
22+
DROP TABLE IF EXISTS #Probabilities;
23+
DROP TABLE IF EXISTS #Numbers;
24+
DROP TABLE IF EXISTS #RandomNumbers;
25+
DROP TABLE IF EXISTS #ProbabilitesFinal;
26+
GO
27+
28+
-------------------------------
29+
-------------------------------
30+
--Create and populate table #Probabilities
31+
CREATE TABLE #Probabilities
32+
(
33+
CurrentState INTEGER NOT NULL,
34+
FutureState INTEGER NOT NULL,
35+
Probability INTEGER NOT NULL,
36+
);
37+
GO
38+
39+
--1 is Rainy, 2 is Sunny
40+
INSERT INTO #Probabilities (CurrentState, FutureState, Probability) VALUES
41+
(1,1,1),(1,1,2),(1,1,3),(1,1,4),(1,1,5),(1,1,6),(1,1,7),(1,2,8),(1,2,9),(1,2,10),
42+
(2,2,1),(2,2,2),(2,2,3),(2,2,4),(2,2,5),(2,1,6),(2,1,7),(2,1,8),(2,1,9),(2,1,10);
43+
GO
44+
45+
-------------------------------
46+
-------------------------------
47+
--Declare and set the variables
48+
--This equates to the number of days to simulate
49+
DECLARE @vTotalNumbers INTEGER = 10000;
50+
51+
-------------------------------
52+
-------------------------------
53+
--Insert into #Numbers table using recursion
54+
WITH cte_Recursion (Number)
55+
AS (
56+
SELECT 1 AS Number
57+
UNION ALL
58+
SELECT Number + 1
59+
FROM cte_Recursion
60+
WHERE Number < @vTotalNumbers
61+
)
62+
SELECT Number AS StepNumber
63+
INTO #Numbers
64+
FROM cte_Recursion
65+
OPTION (MAXRECURSION 0);
66+
67+
-------------------------------
68+
-------------------------------
69+
--Insert into #RandomNumbers table
70+
SELECT StepNumber,
71+
CAST(NULL AS INTEGER) AS CurrentState,
72+
ABS(CHECKSUM(NEWID()) % 10) + 1 AS Probability
73+
INTO #RandomNumbers
74+
FROM #Numbers;
75+
GO
76+
77+
--Seed the first record in the #RandomNumbers table
78+
--I'm arbitrarily setting this to 1 (Rain).
79+
UPDATE #RandomNumbers
80+
SET CurrentState = 1
81+
WHERE StepNumber = 1;
82+
GO
83+
84+
-------------------------------
85+
-------------------------------
86+
--Insert into #ProbabilitesFinal using recursion
87+
WITH cte_Recursion AS
88+
(
89+
SELECT StepNumber
90+
,Probability
91+
,CurrentState
92+
FROM #RandomNumbers a WHERE StepNumber = 1
93+
UNION ALL
94+
SELECT n.StepNumber
95+
,n.Probability
96+
,CAST(p.FutureState AS INTEGER) AS CurrentState
97+
FROM cte_Recursion cte
98+
INNER JOIN
99+
#RandomNumbers n ON (cte.StepNumber + 1) = n.StepNumber
100+
INNER JOIN
101+
#Probabilities p ON cte.Probability = p.Probability AND cte.CurrentState = p.CurrentState
102+
)
103+
SELECT StepNumber
104+
,CurrentState
105+
,(CASE CurrentState WHEN 1 THEN 'Rainy' WHEN 2 THEN 'Sunny' END) AS [Description]
106+
,Probability
107+
INTO #ProbabilitesFinal
108+
FROM cte_Recursion
109+
ORDER BY StepNumber
110+
OPTION (MAXRECURSION 0);
111+
GO
112+
113+
-------------------------------
114+
-------------------------------
115+
--Display a summary of counts
116+
SELECT [Description],
117+
COUNT(*) AS [Count]
118+
FROM #ProbabilitesFinal
119+
GROUP BY [Description]
120+
ORDER BY 1;
121+
GO

0 commit comments

Comments
 (0)