Someone brought up a SQL challenge and I couldn’t come up with a good solution to it. They wanted to see the best way to detect a split in a game of bowling.
For some background, what I could find on defining a split from usbc:
2h. Split
A split is a setup of pins left standing after the first delivery, provided the head pin is down and at least one pin is down:
1. Between two or more standing pins; e.g., 7-9 or 3-10.
2. Immediately ahead of two or more standing pins; e.g., 5-6.
So presume we have a table as such…
gameid | throwNum | frame | pinsHit
1 | 1 | 1 | 1,2,3,6,7,9,10 -- 4,5,6 standing
1 | 1 | 2 | 1,2,4,5,6,7,8,9 -- 3,10 standing
1 | 1 | 3 | 1,2,3,5,8,9 -- 4,6,7,10 standing
1 | 1 | 4 | 1,4,5,6,7,8,9,10 -- 2,3 standing
1 | 1 | 5 | 1,2,3,4,5,8,10 -- 6,7,9 standing
For simplicity I only wrote out the first throw of each frame. All of these should constitute a split, but I can’t think of the SQL to detect that without hard coding it.
I feel like I need to loop through the standing pins to look for the adjacent option first. Then I need to compare the other pin. I think this still requires hard coding, and I don’t want to do this for every possible scenario
2
Answers
The algorithm below has three parts:
cte
, the pin hits are normalized, standing pins are added, and the gaps between runs of standing and hit pins are found.frame_results
, the gapid
s are grouped, and the size of the gaps and the type of gap (standing or hit pins) are recorded.2
or more or there is a hit pin between two or more standing pins.See fiddle (Includes additional test cases)
I want to propose a solution that can be simply applied to determine whether the standing pins combination is
Split
.There 1024 possible combinations of pins in bowling field.
Some of these combinations are called
Split
. According to the meaning of the term, it is clear that the remaining figures should be divided into 2 or more groups.However, there are some additional conditions, such as that Pin 1 must be hited. In the terminology used by the players, there are combinations that formally do not fit the condition, but are also called Split. Some of the most common, as well as the most difficult combinations to continue the game, have their own names.Therefore, I suggest creating a table of possible combinations and determining in it whether this combination is Split. Having such a table, the solution to the problem is quite simple.
For example
Such a table
Splits
can be created and filled like this:1.Define pins and pins neighbourhood. This is the field where we will place the elements of the
standPins
set2.And check the complete connectivity of the set on this undirected graph.
Perhaps this is the most interesting part of the task.
We take the first (any) element of the set and traverse the tree with a recursive query. If as a result we go through all the elements of the set, then the set is completely connected on this graph and the combination is not Split. Otherwise, they are called
disconnected
– Split.Table is ready. The table can be created 1 time and stored in the database.
Some examples
Fiddle here
Remark 1. I was considering
Split
=disconnected
Update2. About vHit and vStand. I use numbers for convenient, concise designations of combinations.
We can denote any combination of 10 pins with number from 0 to 1023 or binary number with 10 bit.
The set of Pins {1,3,5,7} as number 0001010101 in binary notation, where 1 – standPin,0 – hitPin.
Another example