『今週の問題』第226回 解答


◆東京都 明 さんからの解答

【問題1】のプログラムです。(10進BASICです。)

----------------------
DECLARE EXTERNAL SUB combp
DECLARE EXTERNAL SUB zyun
LET LS$="ABCDEFGHIJKLMNOPQRm"
DIM AL(19)          ! 記号列
DATA 1,3,5,7,9,11
DATA 13,14,15,16,17,18
DATA 12,4,8,2,6,10,19
MAT READ AL 

REM 方程式の解
DIM AR(12,19)      ! 方程式表示配列
!    A,C,E,G,I,K,M,N,O,P,Q,R,L,D,H,B,F,J,m
DATA 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,-1
DATA 0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,-1
DATA 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,-1
DATA 0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,-1
DATA 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,-1
DATA 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,-1
DATA 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,-1
DATA 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,-1
DATA 0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,-1
DATA 0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,-1
DATA 0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,-1
DATA 0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,-1

MAT READ AR
DIM OP(12,19)      ! 演算過程表示配列
DIM DM(12)
DIM IDP(2)
MAT DM=ZER
MAT OP=ZER
FOR J=1 TO 12
   LET OP(J,J)=1
NEXT J
LET Q=1
FOR J=1 TO 19 
   FOR K=1 TO 12
      IF AR(K,J)<>0 AND DM(K)=0 THEN
         LET DM(K)=1
         LET DV=AR(K,J)
         FOR L=1 TO 19
            LET AR(K,L)=AR(K,L)/DV
            LET OP(K,L)=OP(K,L)/DV
         NEXT L
         FOR M=1 TO 12
            IF M<>K THEN
               LET MP=AR(M,J)
               FOR N=1 TO 19
                  LET AR(M,N)=AR(M,N)-MP*AR(K,N)
                  LET OP(M,N)=OP(M,N)-MP*OP(K,N)
               NEXT N
            END IF
         NEXT M
         EXIT FOR
      END IF
      IF K=12 AND Q<=2 THEN
         LET  IDP(Q)=J
         LET Q=Q+1
      END IF
   NEXT K
NEXT J

PRINT " 方程式の解 "
FOR J=1 TO 19
   PRINT " ";LS$(AL(J):AL(J));
   IF J=19 THEN PRINT ELSE PRINT ",";
NEXT J
 
FOR J=1 TO 12
   FOR K=1 TO 19
      PRINT USING"-%":AR(J,K);
      IF K=19 THEN PRINT ELSE PRINT ",";
   NEXT K
NEXT J

PRINT
PRINT " 演算過程表示 "
LET LS2$=" 1 2 3 4 5 6 7 8 9101112"
FOR J=1 TO 12
   PRINT LS2$(2*J-1:2*J);")";
   IF J=12 THEN PRINT
NEXT J

FOR J=1 TO 12
   FOR K=1 TO 19
      PRINT USING"-%":OP(J,K);
      IF K=19 THEN PRINT ELSE PRINT ",";
   NEXT K
NEXT J


REM 数入れ探索
LET N=18
LET K=5
DIM NA(N+1)
DIM NAC(N+1)
DIM NAC2(N+1)
DIM CK(N)
DIM CKC(N)
DIM CKC2(N)
DIM CKC3(N)
DIM VL(N)
DIM VO(N,2)
MAT VO=CON
FOR J=1 TO N
   LET VL(J)=J
   LET VO(J,1)=J
NEXT J
FOR J=1 TO K
   LET VO(J,2)=0
NEXT J
LET L=5
LET M=3
DIM VO2(L,2)
DIM VL2(L)
LET P=3
DIM VL3(P)
LET IDP1=AL(IDP(1))
LET IDP2=AL(IDP(2))

PRINT
PRINT " 数入れの解 "
FOR J=1 TO 19
   PRINT " ";LS$(J:J);
   IF J=19 THEN PRINT ELSE PRINT ",";
NEXT J
DO
   CALL serch
   CALL combp(K,N,EX,VL,VO)
LOOP UNTIL EX=0
PRINT "終了"
STOP

SUB serch
   MAT NA=ZER
   MAT CK=ZER
   MAT VO2=CON
   FOR J=1 TO L
      LET VO2(J,1)=VL(J)
      LET VL2(J)=VL(J)
   NEXT J
   FOR J=1 TO M
      LET VO2(J,2)=0
   NEXT J
   DO
      CALL serch2
      CALL combp(M,L,EX,VL2,VO2)
   LOOP UNTIL EX=0    
END SUB

SUB serch2
   LET NA(12)=VL2(1)    ! L代入
   LET NA(4)=VL2(2)     ! D代入
   LET NA(8)=VL2(3)     ! H代入
   LET CK(NA(12))=1
   LET CK(NA(4))=1
   LET CK(NA(8))=1
   LET RN=VL2(1)
   FOR J=2 TO 3 
      LET RN=RN+VL2(J)-VL2(J+2)
   NEXT J
   IF RN<=VL(5) THEN EXIT SUB
   FOR J=1 TO 2
      LET VL3(J)=VL2(J+3)
   NEXT J
   IF RN>18 THEN EXIT SUB
   LET VL3(3)=RN
   LET SUM=0
   FOR J=1 TO 3
      LET SUM=SUM+VL2(J)+VL3(J)
   NEXT J
   IF MOD(SUM+6,12)<>0 THEN EXIT SUB
   LET TM=(SUM+6)/12+28
   IF TM>43 THEN EXIT SUB
   LET NA(19)=TM        ! m代入
   MAT CKC=CK
   MAT NAC=NA
   DO
      CALL serch3
      CALL zyun(P,EX,VL3)
   LOOP UNTIL EX=0
END SUB

SUB serch3
   MAT CK=CKC
   MAT NA=NAC
   LET NA(2)=VL3(1)     ! B代入
   LET NA(6)=VL3(2)     ! F代入
   LET NA(10)=VL3(3)    ! J代入
   LET CK(NA(2))=1
   LET CK(NA(6))=1
   LET CK(NA(10))=1
   MAT CKC2=CK
   MAT NAC2=NA
    
   REM 従属変数を求める
   LET X=1
   DO
      MAT CK=CKC2
      IF CK(X)=0 THEN
         LET CK(X)=1
         MAT CKC3=CK
         LET Y=1
         DO
            MAT CK=CKC3
            CALL lokdep
            LET Y=Y+1
         LOOP WHILE Y<=18
      END IF
      LET X=X+1
   LOOP WHILE X<=18
END SUB

SUB lokdep
   IF CK(Y)=1 THEN EXIT SUB
   MAT NA=NAC2
   LET NA(IDP1)=X
   LET NA(IDP2)=Y
   LET CK(Y)=1     
   FOR RAW=1 TO 12
      FOR J=1 TO 12
         IF AR(RAW,J)=1 THEN
            LET IDX=AL(J)
            FOR U=J+1 TO 19
               LET NA(IDX)=NA(IDX)-NA(AL(U))*AR(RAW,U)
            NEXT U
            IF NA(IDX)>0 AND NA(IDX)<=18 AND CK(NA(IDX))=0 THEN
               LET CK(NA(IDX))=1
            ELSE
               EXIT SUB
            END IF
            EXIT FOR
         END IF
      NEXT J
   NEXT RAW
    
   FOR J=1 TO 19
      PRINT USING"##":NA(J);
      IF J=19 THEN PRINT ELSE PRINT ",";
   NEXT J                      
END SUB

END

REM N個の数列VO(,)からK個の数列VL()を取る組合せ
EXTERNAL SUB combp(K,N,EX,VL(),VO(,))
LET EX=0
LET P=K
DO WHILE P>=1
   LET IDX=1
   DO WHILE IDX<=N-(K-P)
      IF VO(IDX,2)=1 AND VO(IDX,1)>VL(P) THEN
         LET EX=1
         FOR J=IDX-1 TO 1 STEP -1 
            IF VO(J,2)=0 AND VO(J,1)=VL(P) THEN
               LET VO(J,2)=1
               LET VO(IDX,2)=0
               LET VL(P)=VO(IDX,1)
               LET IDY=P+1
               DO WHILE IDY=<K
                  FOR L=IDX TO N
                     IF VO(L,2)=1 THEN                       
                        LET VL(IDY)=VO(L,1)
                        LET IDY=IDY+1
                        LET VO(L,2)=0
                        EXIT FOR
                     END IF
                  NEXT L
               LOOP
               LET ID=K+1
               FOR L=1 TO N
                  IF VO(L,2)=1 THEN 
                     LET VL(ID)=VO(L,1)
                     LET ID=ID+1
                  END IF
               NEXT L
               EXIT SUB
            END IF
         NEXT J
      END IF
      LET IDX=IDX+1
   LOOP
   FOR J=N TO 1 STEP -1
      IF VO(J,2)=0 AND VO(J,1)=VL(P) THEN 
         LET VO(J,2)=1
         EXIT FOR
      END IF
   NEXT J
   LET P=P-1
LOOP 
END SUB

REM K個の数列N()の順列
EXTERNAL SUB zyun(K,EX,N())
DECLARE EXTERNAL SUB seiretu
LET EX=0
LET J=1
DO
   IF J>=K THEN EXIT DO
   IF N(K-J)<N(K-J+1) THEN
      CALL seiretu(J,K,N)
      LET L=1
      DO
         IF N(K-J)>=N(K-J+L) THEN 
            LET L=L+1
         ELSE
            LET B=N(K-J)
            LET N(K-J)=N(K-J+L)
            LET N(K-J+L)=B
            LET EX=1
            EXIT DO
         END IF
      LOOP
      EXIT DO
   ELSE 
      LET J=J+1          
   END IF
LOOP
END SUB

!配列の整列
EXTERNAL  SUB seiretu(G,K,N())
LET D=G
DO
   LET J=K-D+1
   IF J>=K THEN EXIT DO
   LET B=J
   DO WHILE J<K
      LET J=J+1
      IF N(B)>N(J) THEN
         LET T=N(B)
         LET N(B)=N(J)
         LET N(J)=T
      END IF
   LOOP
   LET D=D-1
LOOP
END SUB
----------------------


 ◆ 問題へもどる

 ◆ 今週の問題

数学の部屋へもどる