|
| 1 | +DROP TABLE IF EXISTS ##Sales; |
| 2 | +GO |
| 3 | +/********************************************************************* |
| 4 | +Scott Peters |
| 5 | +Dice Roll Game |
| 6 | +https://advancedsqlpuzzles.com |
| 7 | +Last Updated: 07/05/2022 |
| 8 | +
|
| 9 | +This script is written in SQL Server's T-SQL |
| 10 | +
|
| 11 | +
|
| 12 | +* Because you cannot go below 0, a WHILE loop is created to account for this scenario |
| 13 | +* You will need to make an assumption how many possible numbers you need in the #Numbers table, as this solution uses windowing |
| 14 | +* This script performs 1 iteration of the Dice Roll Game |
| 15 | +
|
| 16 | +**********************************************************************/ |
| 17 | + |
| 18 | +------------------------------- |
| 19 | +------------------------------- |
| 20 | +--Tables used |
| 21 | +DROP TABLE IF EXISTS #Numbers; |
| 22 | +DROP TABLE IF EXISTS #DiceRolls; |
| 23 | +DROP TABLE IF EXISTS #DiceRolls_NotSixes; |
| 24 | +DROP TABLE IF EXISTS #DiceRolls_Modified; |
| 25 | +DROP TABLE IF EXISTS #DiceRollsResults; |
| 26 | +GO |
| 27 | + |
| 28 | +------------------------------- |
| 29 | +------------------------------- |
| 30 | +--Declare and set variables |
| 31 | +--Make an assumption on the total number of rolls needed |
| 32 | +DECLARE @vDesiredScore INTEGER = 100; |
| 33 | +DECLARE @vIterations INTEGER = 100; |
| 34 | + |
| 35 | +------------------------------- |
| 36 | +------------------------------- |
| 37 | +--Create and populate a #Numbers table |
| 38 | +WITH cte_Number (Number) |
| 39 | +AS ( |
| 40 | + SELECT 1 AS Number |
| 41 | + UNION ALL |
| 42 | + SELECT Number + 1 |
| 43 | + FROM cte_Number |
| 44 | + WHERE Number < 200 --@vDesiredScore * 2 --Assuming you will not need x times the desired score for the total number of rolls needed to achieve the desired score |
| 45 | + ) |
| 46 | +SELECT Number |
| 47 | +INTO #Numbers |
| 48 | +FROM cte_Number |
| 49 | +OPTION (MAXRECURSION 0);--A value of 0 means no limit to the recursion level |
| 50 | + |
| 51 | +------------------------------- |
| 52 | +------------------------------- |
| 53 | +--Create and populate a #DiceRolls table |
| 54 | +WITH cte_Random AS |
| 55 | +( |
| 56 | +SELECT Number, |
| 57 | + ABS(CHECKSUM(NEWID()) % 6) + 1 AS DiceRoll, |
| 58 | + CAST(NULL AS INTEGER) AS DiceResult |
| 59 | +FROM #Numbers |
| 60 | +) |
| 61 | +SELECT Number AS StepNumber |
| 62 | + ,DiceRoll |
| 63 | +INTO #DiceRolls |
| 64 | +FROM cte_Random; |
| 65 | +GO |
| 66 | + |
| 67 | +/*************************************** |
| 68 | +--If you need to create test data with multiple rolls of 6 |
| 69 | +
|
| 70 | +UPDATE #DiceRolls |
| 71 | +SET DiceRoll = 6 |
| 72 | +WHERE StepNumber in (1,3,4,6,7); |
| 73 | +GO |
| 74 | + |
| 75 | +
|
| 76 | +UPDATE #DiceRolls |
| 77 | +SET DiceRoll = 5 |
| 78 | +WHERE StepNumber in (2,5); |
| 79 | +GO |
| 80 | +***************************************/ |
| 81 | + |
| 82 | +------------------------------- |
| 83 | +------------------------------- |
| 84 | +--Create and populate a #DiceRolls_NotSixes table |
| 85 | +SELECT StepNumber |
| 86 | + ,LEAD(StepNumber) OVER (ORDER BY StepNumber) - 1 AS Lead_StepNumber |
| 87 | + ,DiceRoll |
| 88 | +INTO #DiceRolls_NotSixes |
| 89 | +FROM #DiceRolls |
| 90 | +WHERE DiceRoll <> 6; |
| 91 | +GO |
| 92 | + |
| 93 | +------------------------------- |
| 94 | +------------------------------- |
| 95 | +--Create and populate a #DiceRolls_Modified table |
| 96 | +--Determines which StepNumbers need to be subtracted |
| 97 | +WITH cte_DiceRolls AS |
| 98 | +( |
| 99 | +SELECT a.Number as StepNumber, |
| 100 | + ISNULL(b.Lead_StepNumber,a.Number) AS Lead_StepNumber, |
| 101 | + c.DiceRoll AS DiceRoll_Actual, |
| 102 | + CASE WHEN a.Number = b.StepNumber THEN b.DiceRoll ELSE ISNULL(b.DiceRoll,0) * - 1 END AS DiceRoll_Modified |
| 103 | +FROM #Numbers a LEFT OUTER JOIN |
| 104 | + #DiceRolls_NotSixes b ON a.Number BETWEEN b.StepNumber AND b.Lead_StepNumber |
| 105 | + LEFT OUTER JOIN |
| 106 | + #DiceRolls c ON a.Number = c.StepNumber |
| 107 | +) |
| 108 | +SELECT 1 AS ID, |
| 109 | + StepNumber, |
| 110 | + Lead_StepNumber, |
| 111 | + DiceRoll_Actual, |
| 112 | + DiceRoll_Modified, |
| 113 | + SUM(DiceRoll_Modified) OVER (ORDER BY StepNumber) AS DiceRoll_Sum |
| 114 | +INTO #DiceRolls_Modified |
| 115 | +FROM cte_DiceRolls; |
| 116 | +GO |
| 117 | + |
| 118 | +------------------------------- |
| 119 | +------------------------------- |
| 120 | +--Create and populate a #DiceRollsResults table |
| 121 | +--Uses recursion to account for the sum not allowed to go below 0 |
| 122 | +;WITH cte_DiceRolls_Modified AS |
| 123 | +( |
| 124 | +--Add a ranking function here if needed |
| 125 | +--Test data has StepNumber to rank/sort the records. |
| 126 | +SELECT * |
| 127 | +FROM #DiceRolls_Modified |
| 128 | +), |
| 129 | +cte_Recursion AS |
| 130 | +( |
| 131 | +SELECT ID, |
| 132 | + StepNumber, |
| 133 | + DiceRoll_Actual, |
| 134 | + DiceRoll_Modified, |
| 135 | + DiceRoll_Sum, |
| 136 | + CASE WHEN DiceRoll_Modified < 0 THEN 0 |
| 137 | + WHEN DiceRoll_Modified > 1000 THEN 1000 |
| 138 | + ELSE DiceRoll_Modified |
| 139 | + END AS DiceRoll_Sum_Modified |
| 140 | +FROM #DiceRolls_Modified |
| 141 | +WHERE StepNumber = 1 |
| 142 | +UNION ALL |
| 143 | +SELECT cte.ID, |
| 144 | + t.StepNumber, |
| 145 | + t.DiceRoll_Actual, |
| 146 | + t.DiceRoll_Modified, |
| 147 | + t.DiceRoll_Sum, |
| 148 | + (CASE WHEN t.DiceRoll_Modified + cte.DiceRoll_Sum_Modified < 0 THEN 0 |
| 149 | + WHEN t.DiceRoll_Modified + cte.DiceRoll_Sum_Modified > 1000 THEN 1000 |
| 150 | + ELSE t.DiceRoll_Modified + cte.DiceRoll_Sum_Modified |
| 151 | + END) AS RunningSum |
| 152 | +FROM cte_Recursion cte |
| 153 | + INNER JOIN |
| 154 | + cte_DiceRolls_Modified t ON t.StepNumber = (cte.StepNumber + 1) AND t.ID = cte.ID |
| 155 | +) |
| 156 | +SELECT * |
| 157 | +INTO #DiceRollsResults |
| 158 | +FROM cte_Recursion |
| 159 | +ORDER BY ID, |
| 160 | + StepNumber |
| 161 | +OPTION (MAXRECURSION 0);--A value of 0 means no limit to the recursion level; |
| 162 | +GO |
| 163 | + |
| 164 | +------------------------------- |
| 165 | +------------------------------- |
| 166 | +--Display the results |
| 167 | +SELECT * |
| 168 | +FROM #DiceRollsResults |
| 169 | +WHERE StepNumber <= (SELECT MIN(StepNumber) FROM #DiceRollsResults WHERE DiceRoll_Sum_Modified >= 100) |
| 170 | +ORDER BY StepNumber DESC; |
0 commit comments