前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >传说中 6 个月都未必能全解开的 3 道 SQL 题,来挑战下?

传说中 6 个月都未必能全解开的 3 道 SQL 题,来挑战下?

作者头像
Lenis
发布2019-12-26 14:59:23
5820
发布2019-12-26 14:59:23
举报
文章被收录于专栏:有关SQL有关SQL有关SQL

很久没怀疑过自己的智商了,直到遇见这 3 道题。

你也来试试!

这 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 1
1 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
as
begin
...
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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有关SQL 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档