6 个月! 3 道 SQL 没做出来!

共 3589字,需浏览 8分钟

 ·

2021-09-23 12:04

1年多过去了,这三道SQL题,有人解出来了么?


你也来试试


这 3 道巨难的题目,来自 itpub 的 SQL 数据库编程大赛。说起 itpub 就不得不说它与 Oracle 的渊源,多少大师都在这里诞生。想成为 SQL 大师,有个最快的方法,就是刷题。如果能刷遍这里的题,Oracle 工作,十拿九稳。当年支付宝首席数据库架构师冯大-冯春培,就是典范。


好了,闲话不说,上题!



1,5X5方格棋盘难题



在5X5的方格棋盘中(如图),每行、列、斜线(斜线不仅仅包括对角线)最多可以放两个球,如何摆放才能放置最多的球,这样的摆法总共有几种?输出所有的摆法。


要求:用一句SQL实现。


输出格式:

从方格棋盘第一行至第5行,每行从第一列到第5列依次输出,0表示不放球,1表示放球。


例如:

1001000000000000000000000。


一行输出一个行号和一个解,按解所在的列字符串顺序从大到小排序。


详情:http://www.itpub.net/thread-1400067-1-1.html
答案:http://www.itpub.net/thread-1407072-1-1.html
我想说:尽量自己做,否则即使看了答案,对提高技能也无帮助

难理解的是,最长的对角线上也不能有 3 个 1



2,挖地雷之标出有地雷的格子



在M*N的矩阵中,单元格中的数字表示该单元格周围地雷的数目,有数字的单元格肯定不是地雷。其余的单元格要么是地雷,要么是空位而且四周都没有地雷。


周围的定义为紧挨着的单元格,例如:


若单元格在矩阵的内部,则周围有8个单元格,如图a所示


若单元格在矩阵的四边,则周围有5个单元格,如图b所示


若单元格在矩阵的四角,则周围有3个单元格,如图c所示



输入输出格式:



用3个变量v_height、v_width、v_cnt表示雷区的长度、宽度和地雷个数,其中v_height、v_width均为大于0且小于32的整数,v_cnt为大于0且小于或等于v_height*v_width的整数。


var v_width NUMBER;EXEC :v_width := 4;
var v_height NUMBER;EXEC :v_height := 4;
var v_cnt NUMBER;EXEC :v_cnt := 3;



用1个字符串变量表示从矩阵第一行至最后一行,每行从第一列到最后一列依次输出

如矩阵(为明显起见,用下划线表示空格,实际做题的输入输出仍用空格)

1 1 1 _2 * 1 _* 3 2 11 2 * 1


的字符串表示为:


VAR v_str VARCHAR2(1000);exec :v_str :='111 2 1  32112 1'


正题 1):挖地雷之标出有地雷的格子 

题目要求:用一句SQL实现


有若干地雷分布在图中,它们都有*标记,请把矩阵中的数字标出来。
如输入字符串为:

VAR v_str VARCHAR2(1000);exec :v_str :='     *  *     * '

输出格式:在输入字符串中有地雷的位置保留'*',同时对它周围的单元格标上地雷数,若单元格周围没有地雷,则保持空格,对上述输入,则输出:
111 2*1 *32112*1

正题 2)挖地雷之标出有地雷的格子

题目要求:用一句SQL实现或用一个PL/SQL函数实现。

(如果用PL/SQL实现,则函数必须为

create or replace function    winmine(p_str varchar2 ,p_width NUMBER ,p_height NUMBER ,p_cnt NUMBER) return varchar2
asbegin...return ...;end;/


结果在sqlplus用


select winmine(:v_str,:v_width,:v_height,:v_cnt) from dual;



输出


如果有相应授权需要把grant语句一并给出,用户名为scott)


有C个地雷分布在图中,根据输入字符串提供的格子周围地雷数,把所有埋了地雷的格子标出来。

如输入字符串为:

VAR v_str VARCHAR2(1000);exec :v_str :='111 2 1  32112 1'


输入地雷数为:

var v_cnt NUMBER;EXEC :v_cnt := 3;


输出格式:在输入字符串中有地雷的位置标上'*',同时保留它周围的单元格标的地雷数,若单元格周围没有地雷,则保持空格,对上述输入,则输出:
111 2*1 *32112*1

本题不需要考虑错误处理,如果输入错误(比如地雷数输入变量和实际不符、雷区不是矩形、字符串中标的地雷数字错误),就允许任何输出。

数据库平台:Oracle 11g R2 版本(不能用12c,因为它有在sql语句中编写自定义函数功能)

详情:http://www.itpub.net/thread-1825024-1-1.html



3,井字棋



两个玩家,一个打圈(O),一个打叉(X),轮流在3乘3的井字格上打自己的符号,最先以任意一行、一列或对角线连成一线则为胜。规定X先手。


一个终局棋谱(MOVES)指的是从开始下子到一方获胜或者下完9个子出现平局,从头到尾的下子情况。一方获胜后,本局即终止。不得提前认输。


格子从上到下,从左到右,依次编号1-9


MOVES的第一位表示第一子位置,第二位表示第二子位置,......如果一方获胜,MOVES的长度有可能<9。


局面(BOARD)表示棋盘上呈现的局面,也是按照从上到下,从左到右排列。用X和0填入相应的格子。减号“-” 表示空位。


这里有个棋局:



表示出来是:

MOVES=3175968,

BOARD=O-X-OOXXX,

WINNER=X


第一题 :求出所有可能终局棋谱和相应的局面,插入如下的表中:

CREATE TABLE TICTACTOE (MOVES VARCHAR2(9) PRIMARY KEY,BOARDVARCHAR2(9),WINNER VARCHAR2(1));


格式要求:


首先CREATE 上述TICTACTOE表。然后用一个能直接放在“insert into TICTACTOE ”后面成功运行的SQL查询语句,一次性插入所有满足标准的棋谱和相应的局面、胜者(WINNER=X或O或D,其中D表示平局)



注意:本题要求生成所有可能的终局棋谱,只要符合规则即可,哪怕其中有些走法可能看起来很愚蠢,也得包含进去。还没下完的棋谱不要列入。


如果两个终局的局面(BOARD)相同,但是其下子顺序(MOVES)不同,则视为不同棋谱,两个都必须出现在结果中。


如果两个棋谱的MOVES不同,但是其终局局面(BOARD)经过旋转、翻转后重合,仍然被视为不同棋谱,两个都必须出现在结果中。



第二题:给定一个局面,假定该局面一定为有效(不会出现一方比另一方多两子的情况,或者两方都有三子连线的情况),用SQL判断出哪一方有必胜策略,以及获胜方最多再下几子必定会获胜。比如输入:V_BOARD='X-0------' 则输出'X3',表示WINNER=X,下子数=3,因为不管对手怎么走,X最多再下3子一定获胜。(不计入O再下的子数)


如果O方有失误,也有可能X再下两子就取胜的;X方也有可能下错而输掉,但这些都不在本题考虑范围,假定双方都是完美棋手,即双方都尽可能取胜,不能取胜则尽可能求和,不能求和则尽可能多下几子。


如果给定的局面中一方已经获胜,则输出获胜方符号和子数0,例如输入:V_BOARD='OXX—XOOX', 则输出'X0'


如果不存在必胜策略(比如一个空局:V_BOARD='---------'),则输出'D'。


输出中都不含单引号。


格式要求:


首先在sqlplus中声明变量var v_BOARDvarchar2(9),再对变量赋值(如:exec :v_BOARD:='X-O------')。然后用一个包含变量v_BOARD的查询语句,返回对应此棋局的结果字符串(X数字,或O数字,或D表示平局)



第三题:m,n,k游戏是指两个对手在m*n的棋盘上轮流下子,谁先在纵、横、四十五度斜线上连续取得k个子就获胜的一种游戏,井字棋游戏其实就是3,3,3的一种特例。五子棋则为15,15,5游戏。


上述按第二题的要求,使得SQL能够适用于m,n,k大于等于3的情况 。


详情来源:http://www.itpub.net/thread-1943911-1-1.html
浏览 34
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报