有人提出了一个SQL挑战,我无法想出一个好的解决方案,他们想看看在保龄球比赛中检测分裂的最佳方法。
对于一些背景,我可以找到定义从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.
字符串
所以假设我们有一张这样的table...
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
型
为了简单起见,我只写出了每个帧的第一个抛出,所有这些都应该构成一个分割,但是我想不出SQL来检测它而不硬编码。
我觉得我需要先遍历站立的引脚来寻找相邻的选项。然后我需要比较另一个引脚。我认为这仍然需要硬编码,我不想对每一个可能的场景都这样做
3条答案
按热度按时间i7uq4tfw1#
下面的算法有三个部分:
1.使用递归
cte
,将引脚命中标准化,添加standing引脚,并找到standing和hit引脚运行之间的间隙。1.然后,在
frame_results
中,将差距id
s分组,并记录间隙的大小和间隙的类型(直立或撞击销)。1.最后,在主查询中,有一个检查,以确保击中头部引脚,并且在长度为
2
或更长的站立引脚运行之后直接存在命中引脚,或者在两个或更多个站立引脚之间存在命中引脚。字符串
See fiddle(包括其他测试用例)
ddrv8njm2#
我想提出一个解决方案,可以简单地应用于确定固定引脚组合是否为
Split
。有1024种可能的组合瓶在保龄球场。
这些组合中的一些被称为
Split
。根据术语的含义,很明显,剩余的数字应该被分成2个或更多的组。但是,还有一些附加条件,如必须将Pin 1 hited。在玩家使用的术语中,有一些组合形式上不符合条件,但也被称为Split。一些最常见的,以及继续游戏的最难的组合,都有自己的名字。因此,我建议创建一个可能的组合表,并在其中确定此组合是否为拆分。有这样一个表,解决问题相当简单。
字符串
例如
| 配子体|掷出号码|帧|pins点击次数|是拆分|引脚支架|vHit| vStand|分割Name| ID|
| --|--|--|--|--|--|--|--|--|--|
| 1 | 1 | 1 |一、二、三、六、七、九、十| 0 |四、五、八| 871 | 152 || 871 |
| 1 | 1 | 2 |一、二、四、五、六、七、八、九| 1 |三、十| 507 | 516 |婴儿裂开| 507 |
| 1 | 1 | 3 |一、二、三、五、八、九| 1 |四、六、七、十| 407 | 616 || 407 |
| 1 | 1 | 4 |1、4、5、6、7、8、9、10位| 0 |二、三| 1017 | 6 || 1017 |
| 1 | 1 | 5 |一、二、三、四、五、八、十| 1 |六、七、九| 671 | 352 || 671 |
| 1 | 1 | 6 |1、2、3、4、5、6、7、8、9、10位| 0 || 1023 | 0 || 1023 |
| 1 | 1 | 7 |1、2、3、4、5、6、8、9、10位| 0 | 7 | 959 | 64 || 959 |
| 1 | 1 | 8 |一、二、三、八、十| 0 |四、五、六、七、九| 647 | 376 || 647 |
| 1 | 1 | 9 |一、二、五、八| 1 |三、四、六、七、九、十| 147 | 876 |希腊主教座堂| 147 |
这样一个表
Splits
可以这样创建和填充:1.定义引脚和引脚邻域。这是我们将放置
standPins
集合元素的字段型
2.并检查这个无向图上集合的完全连通性。
也许这才是任务中最有趣的部分。
型
1.彻底检查连通性。
我们取集合中的第一个元素,然后用递归查询遍历树。如果结果是遍历了集合中的所有元素,则集合在此图上是完全连通的,并且组合不是Split。否则,它们被称为
disconnected
- Split。型
表已准备好。可以创建一次表并将其存储在数据库中。
型
| ID| vHit| pins点击次数|vStand|引脚支架|站计数|是拆分|分割Name|
| --|--|--|--|--|--|--|--|
| 0 | 0 || 1023 |1、2、3、4、5、6、7、8、9、10位| 10 | 0 ||
| 147 | 147 |一、二、五、八| 876 |三、四、六、七、九、十| 6 | 1 ||
| 407 | 407 |一、二、三、五、八、九| 616 |四、六、七、十| 4 | 1 ||
| 507 | 507 |一、二、四、五、六、七、八、九| 516 |三、十| 2 | 1 ||
| 576 | 576 |七、十| 447 |一、二、三、四、五、六、八、九| 8 | 0 ||
| 647 | 647 |一、二、三、八、十| 376 |四、五、六、七、九| 5 | 0 ||
| 671 | 671 |一、二、三、四、五、八、十| 352 |六、七、九| 3 | 1 ||
| 871 | 871 |一、二、三、六、七、九、十| 152 |4、5、8个| 3 | 0 ||
| 959 | 959 |1、2、3、4、5、6、8、9、10位| 64 | 7 | 1 | 0 ||
| 1017 | 1017 |1、4、5、6、7、8、9、10位| 6 |二、三个| 2 | 0 ||
| 1023 | 1023 |1、2、3、4、5、6、7、8、9、10位| 0 || 0 | 0 ||
Fiddle here和updated
备注1.我考虑的是
Split
=disconnected
更新2。关于vHit和vStand。我使用数字来方便,简洁地指定组合。
我们可以用从0到1023的数字或10位的二进制数来表示10个管脚的任意组合,管脚{1,3,5,7}的集合用二进制记数法表示为数字0001010101,其中1 - standPin,0 - hitPin。
另一示例
型
omqzjyyz3#
我有一个解决方案,它使用管脚集拓扑结构(10行种子数据)来构建构成分割的上/下管脚组合(24行)的短列表。然后,可以将这些短列表与任何可能的管脚组合(2^10 = 1024种可能性)进行比较,以确定该组合是否构成分割。
某些参考情况可能与参考情况本身不构成分割的管脚组合匹配,但这仅发生在至少一个其它规则可能适用于其它管脚的布局中。例如,对于4 - 5 - 7 - 8 - 9管脚集,"7 - 9,缺少2"参考分割将匹配。即使引脚7和9被完全覆盖,并且是集群的一部分。但是,"4 - 5缺失2"参考案例也匹配,所以这仍然是一个分裂。
其逻辑概括如下:
1.定义一组10个管脚,以及相关的位掩码位置和表示管脚位置的3轴坐标值-从前到后、对角线从左到右和对角线从右到左。
1.对于每个引脚组合(不包括头引脚),使用坐标来找到公共前导/覆盖引脚,以及到该公共前导引脚和从该公共前导引脚开始的所有中间引脚。如果两个当前引脚在同一行上,也包括在同一行中的任何管脚。所选的管脚成为"上管脚",而所有其他的(不包括上引脚)成为"下引脚"。如果下引脚集为空,则此引脚组合不能为拆分,并且可以跳过。所产生的24个参考案例存储在表中。
1.要测试某个特定的引脚组合是否为拆分,请检查参考表中所有(两个)上引脚都存在且至少有一个下引脚不存在的匹配项。如果有匹配项,则正在检查的组合为拆分。还要检查头引脚(引脚1)是否存在,如果存在,则结果始终为不拆分,从而覆盖匹配逻辑。
1.还生成了所有1024个管脚组合的查找表,并为每个管脚组合设置了"已拆分"指示符。
1.一旦定义了上述内容,对任意引脚组合的测试就只是一个简单的表格查找。
管脚组合以整数位的形式存储,并使用按位运算执行比较。
如需演示,请参阅**this MySql fiddle或等效的this SQL-Server fiddle**。
研究结果包括样本案例、以及所有1024种引脚组合的详尽列表(从没有管脚到所有10个管脚都朝上)。结果还包含额外的列,显示上/下管脚列表和剩余管脚组合的可视化。最后一个查询仅是可用于测试其他答案的数据生成器。游戏111包含所有拆分,而游戏222包含所有非拆分。分裂(至少根据我对规则的解释)。
代码并不是最少的。它包含了一些可以做成函数的重复逻辑。它还计算了几个文本结果,这些结果只供参考和调试之用。
定义管脚号/名称/掩码/坐标查找表:
字符串
生成参考分割数据:
型
通过将命中管脚列表转换为位掩码,然后扫描所有上行管脚匹配和所有下行管脚匹配的任何行的参考数据,计算结果。
型
样品结果:
| 配子体|掷出号码|帧|pins点击次数|是否拆分|
| - -|- -|- -|- -|- -|
| 1| 1| 1|一、二、三、六、七、九、十|真|
| 1| 1| 2|一、二、四、五、六、七、八、九|真|
| 1| 1| 3|一、二、三、五、八、九|真|
| 1| 1| 4| 1、4、5、6、7、8、9、10位|真|
| 1| 1| 5|一、二、三、四、五、八、十|真|
生成所有可能引脚组合的参考表,并计算每个组合的IsSplit值。(请注意,以下部分计算数据仅用于调试演示或可视化目的。)
型
拆分检查现在只是一个查找:
型
一个有趣的统计数据是,如果你排除了头钉站立的情况,剩下的512个钉组合中只有10%(51)不被认为是分裂。然而值得注意的是,绝大多数分裂组合(如4 - 5 - 6 - 7 - 8 - 9 - 10)将几乎不可能实现是一个真正的游戏。