|
with p as ( ---------- 每层Y坐标,有几个点
SELECT 0 y,1 cnt from dual
union all select 1,2 FROM DUAL
union all select 2,1 FROM DUAL
union all select 3,2 FROM DUAL
union all select 4,3 FROM DUAL
union all select 5,2 FROM DUAL
union all select 6,3 FROM DUAL
union all select 7,2 FROM DUAL
union all select 8,1 FROM DUAL
)
,p2 as ( ---------- 生成每个点的坐标,把原图纵向拉伸从等边三角形变成等腰直角三角形
select 1-cnt+(level-1)*2 x,y,CHR(64+ROW_NUMBER() OVER(ORDER BY Y,LEVEL)) id
from p
connect by y=prior y and level<=cnt and prior sys_guid() is not null
order by id
)
,v as ( ---------- 找出所有可能的线段,要么是纵向(斜率999)要么是斜线,斜率1或-1
select s.id s_id
,e.id e_id
,case when s.x=e.x then 999 else (e.y-s.y)/(e.x-s.x) end as k
,s.id||e.id id
,s.x
,s.y
,e.x x2
,e.y y2
from p2 s,p2 e
where s.id<>e.id and s.x=e.x or s.x<>e.x and (e.y-s.y)/(e.x-s.x) in (1,-1)
)
,crossing AS ( ------ 找出所有两两交叉的线段
SELECT m1.id,m2.id id2
FROM v m1, v m2
WHERE m1.id<>m2.id
AND ((m1.x-m2.x)*(m1.y-m2.y2)-(m1.x-m2.x2)*(m1.y-m2.y))*((m1.x2-m2.x)*(m1.y2-m2.y2)-(m1.x2-m2.x2)*(m1.y2-m2.y))<=0
AND ((m2.x-m1.x)*(m2.y-m1.y2)-(m2.x-m1.x2)*(m2.y-m1.y))*((m2.x2-m1.x)*(m2.y2-m1.y2)-(m2.x2-m1.x2)*(m2.y2-m1.y))<=0
)
,tp as (select substr(s,level)||substr(s,1,level-1) tp from (select '12345' s from dual) connect by level<=5) ---- TRANSLATE使用的循环变形模版
,tp2 as (select tp from tp union all select reverse(tp) from tp) ------ 对称翻转模版
select count(*) from (
select distinct min(translate('12345',tp2.tp,s))
from (
select v1.s_id||v2.s_id||v3.s_id||v4.s_id||v5.s_id s
from v v1,v v2,v v3,v v4,v v5 ----------- 五条线段,首位相接,相邻两条的斜率不能相等
where v1.e_id=v2.s_id and v1.k<>v2.k
and v2.e_id=v3.s_id and v2.k<>v3.k
and v3.e_id=v4.s_id and v3.k<>v4.k
and v4.e_id=v5.s_id and v4.k<>v5.k
and v5.e_id=v1.s_id and v5.k<>v1.k
and v2.e_id<>v1.s_id
and v3.e_id not in (v1.s_id,v2.s_id)
and v4.e_id not in (v1.s_id,v2.s_id,v3.s_id)
-----------不能有交叉
and NOT EXISTS (SELECT 1 FROM crossing c where (c.id,c.id2) in ((v1.id,v3.id),(v1.id,v4.id),(v2.id,v4.id),(v2.id,v5.id),(v3.id,v5.id)))
),tp2
group by s
)
;
COUNT(*)
----------
140
---------------------例子
with p as (
SELECT 0 y,4 cnt from dual
union all select 1,3 FROM DUAL
union all select 2,2 FROM DUAL
)
,p2 as (
select 1-cnt+(level-1)*2 x,y,CHR(64+ROW_NUMBER() OVER(ORDER BY Y,LEVEL)) id
from p
connect by y=prior y and level<=cnt and prior sys_guid() is not null
order by id
)
,v as (
select s.id s_id
,e.id e_id
,(e.y-s.y)/(e.x-s.x) as k
,s.id||e.id id
,s.x
,s.y
,e.x x2
,e.y y2
from p2 s,p2 e
where s.id<>e.id and s.y=e.y or s.x<>e.x and (e.y-s.y)/(e.x-s.x) in (1,-1)
)
,crossing AS (
SELECT m1.id,m2.id id2
FROM v m1, v m2
WHERE m1.id<>m2.id
AND ((m1.x-m2.x)*(m1.y-m2.y2)-(m1.x-m2.x2)*(m1.y-m2.y))*((m1.x2-m2.x)*(m1.y2-m2.y2)-(m1.x2-m2.x2)*(m1.y2-m2.y))<=0
AND ((m2.x-m1.x)*(m2.y-m1.y2)-(m2.x-m1.x2)*(m2.y-m1.y))*((m2.x2-m1.x)*(m2.y2-m1.y2)-(m2.x2-m1.x2)*(m2.y2-m1.y))<=0
)
,tp as (select substr(s,level)||substr(s,1,level-1) tp from (select '12345' s from dual) connect by level<=5)
,tp2 as (select tp from tp union all select reverse(tp) from tp)
select count(*) from (
select distinct min(translate('12345',tp2.tp,s))
from (
select v1.s_id||v2.s_id||v3.s_id||v4.s_id||v5.s_id s
from v v1,v v2,v v3,v v4,v v5
where v1.e_id=v2.s_id and v1.k<>v2.k
and v2.e_id=v3.s_id and v2.k<>v3.k
and v3.e_id=v4.s_id and v3.k<>v4.k
and v4.e_id=v5.s_id and v4.k<>v5.k
and v5.e_id=v1.s_id and v5.k<>v1.k
and v2.e_id<>v1.s_id
and v3.e_id not in (v1.s_id,v2.s_id)
and v4.e_id not in (v1.s_id,v2.s_id,v3.s_id)
and NOT EXISTS (SELECT 1 FROM crossing c where (c.id,c.id2) in ((v1.id,v3.id),(v1.id,v4.id),(v2.id,v4.id),(v2.id,v5.id),(v3.id,v5.id)))
),tp2
group by s
)
;
COUNT(*)
----------
9
|
|