|
問題 点つなぎパズル
与えられた座標を順につないでできる図形が
・線対称なのか
・点対称なのか
を出力するプログラムを作成してください。
考察
線対称
2点(選び方はC(n,2)通り)を結ぶ線分の垂直二等分線を対称軸として、
各点を線対称変換させて、重複することなく元の点に重なる。
点対称
各点を重心を中心に180°回転させて、重複することなく元の点に重なる。
(終り)
SET WINDOW -1,6,-1,6
DRAW grid
!DATA 4 !点の個数
!DATA 1,5, 1,3, 4,0, 4,2 !座標(x,y) 点対称
DATA 4
DATA 0,0, 0,2, 2,2, 2,0 !線対称、点対称
!DATA 5
!DATA 0,2, 1,0, 3,0, 4,2, 2,3 !線対称
!DATA 6
!DATA 0,0, 3,0, 3,1, 5,3, 2,3, 2,2 !点対称
!DATA 6
!DATA 0,1, 1,0, 4,0, 2,1, 3,2, 2,3 !error
!DATA 19 !花
!DATA 3,0, 2,1, 0,1, 1,0, 5,0, 6,1, 4,1, 3,0, 3,3, 4,3
!DATA 5,4, 5,6, 4,5, 3,6, 2,5, 1,6, 1,4, 2,3, 3,3
READ N
DIM X(N),Y(N)
FOR i=1 TO N !点の座標を読み込む
READ X(i),Y(i)
PLOT TEXT ,AT X(i)+0.1,Y(i)+0.1: STR$(i)
DRAW disk WITH SCALE(0.1)*SHIFT(X(i),Y(i))
NEXT i
FOR i=1 TO N !点をつなぐ
PLOT LINES: X(i),Y(i);
NEXT i
PLOT LINES: X(1),Y(1) !一筆書き
!線対称
FOR P=1 TO N-1 !対称軸となる2点
FOR Q=P+1 TO N
CALL gcP2LINE(X(P),Y(P),X(Q),Y(Q), A,B,C) !垂直二等分線
SET AREA COLOR 2
FOR i=1 TO N
CALL gcSYMMETRY2(A,B,C,X(i),Y(i), XX,YY) !線対称
FOR K=1 TO N !重なるかどうか確認する
IF ABS(XX-X(K))<1E-10 AND ABS(YY-Y(K))<1E-10 THEN EXIT FOR
NEXT K
IF K>N THEN EXIT FOR !重ならない
!!PLOT TEXT ,AT XX+0.1,YY-0.1: STR$(i)
DRAW disk WITH SCALE(0.1)*SHIFT(XX,YY)
NEXT i
IF i>N THEN !すべての点が重なるなら
SET LINE COLOR 4
CALL gcDRAWLINE(A,B,C)
PRINT "線対称な図形です。"; P;Q
END IF
NEXT Q
NEXT P
!点対称
LET GX=0 !重心を求める
LET GY=0
FOR i=1 TO N
LET GX=GX+X(i)
LET GY=GY+Y(i)
NEXT i
LET GX=GX/N
LET GY=GY/N
SET AREA COLOR 4
PLOT TEXT ,AT GX+0.1,GY+0.1: "G"
DRAW disk WITH SCALE(0.1)*SHIFT(GX,GY)
SET AREA COLOR 2
FOR i=1 TO N !重心で180°回転する
CALL gcSYMMETRY(X(i),Y(i),GX,GY, XX,YY)
FOR K=1 TO N !重なるかどうか確認する
IF ABS(XX-X(K))<1E-10 AND ABS(YY-Y(K))<1E-10 THEN EXIT FOR
NEXT K
IF K>N THEN EXIT FOR !重ならない
PLOT TEXT ,AT XX+0.1,YY-0.1: STR$(i)
DRAW disk WITH SCALE(0.1)*SHIFT(XX,YY)
NEXT i
IF i>N THEN PRINT "点対称な図形です。"
END
!FV.LIB 抜粋
EXTERNAL SUB gcDRAWLINE(L,M,N) !直線Lx+My+N=0を描く
IF (L=0 AND M=0) THEN
PRINT "L=M=0なので、直線が成立しません。"; L;M;N
ELSE
ASK WINDOW x1,x2,y1,y2
IF ABS(L)>ABS(M) THEN !y=±xの傾きより大きいなら ※y軸に平行な直線を含む
PLOT LINES: -(M*y1+N)/L,y1; -(M*y2+N)/L,y2
ELSE
PLOT LINES: x1,-(L*x1+N)/M; x2,-(L*x2+N)/M
END IF
END IF
END SUB
!点A(x1,y1), B(x2,y2)を結ぶ線分ABの垂直二等分線
! 線分ABの中点を通り、線分ABの傾きに垂直な直線 Y-(y1+y2)/2=-(x2-x1)/(y2-y1)(X-(x1+x2)/2) より
EXTERNAL SUB gcP2LINE(x1,y1,x2,y2, L,M,N)
IF (x1=x2 AND y1=y2) THEN
PRINT "2点は同一点なので、線分が成立しません。"; x1;y1;x2;y2
ELSE
LET L=x2-x1
LET M=y2-y1
LET N=-(L*(x1+x2)+M*(y1+y2))/2
END IF
END SUB
EXTERNAL SUB gcSYMMETRY(X,Y,PX,PY, QX,QY) !点Aに対する点対称の点
LET QX=2*PX-X !点(X,Y)と対称点(QX,QY)の中点が点(PX,PY)なので、PX=(X+QX)/2
LET QY=2*PY-Y
END SUB
!線対称(Lx+My+N=0)の点
! 点A(x1,y1)、対称点A'(x2,y2)とする。
! 点A,A'の中点は直線上の点なので、L((x1+x2)/2)+M((y1+y2)/2)+N=0 ∴Lx2+My2=-(Lx1+My1+2N) ←式1
! また、直線AA'と直線とは直交するので、傾き((y2-y1)/(x2-x1))(-L/M)=-1 ∴Mx2-Ly2=Mx1-Ly1 ←式2
! L*式1+M*式2より、(L^2+M^2)x2=-L(Lx1+My1+2N) +M(Mx1-Ly1)=(L^2+M^2)x1-2L(Lx1+My1+N)
! M*式1-L*式2より、(L^2+M^2)y2=-M(Lx1+My1+2N) -L(Mx1-Ly1)=(L^2+M^2)y1-2M(Lx1+My1+N)
EXTERNAL SUB gcSYMMETRY2(L,M,N,PX,PY, QX,QY) !線対称(Lx+My+N=0)の点
LET m3=L*L+M*M
IF m3=0 THEN
PRINT "L=M=0なので、直線が成立しません。"; L;M;N
ELSE
LET t=(L*PX+M*PY+N)/m3
LET QX=PX-2*L*t
LET QY=PY-2*M*t
END IF
END SUB
|
|