1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

COdeIQ:「ツイン・トライアングル」問題の解答

Last updated at Posted at 2025-04-05

Kawazoe(@riverplus)さんのCodeIQの問題です。
問題はこちらの御世話になりました。解答例もあります。
->https://blog.goo.ne.jp/r-de-r/e/45659ad975496af9b1b7de04a8d2305d
->https://blog.goo.ne.jp/r-de-r/e/44e77fc0784eef7457ffdd88c8771609
こちらにも情報があります。
->https://posfie.com/@riverplus/p/SeiCU5C

求める外接三角形の辺の長さは原始ピタゴラス数の整数倍です。
原始ピタゴラス数は3つの数が互いに素(ある2数が互いに素)なピタゴラス数です。
さらに整数辺の直角三角形の公式(a,b,c)=(I^2-J^2,2*I*J,I^2+J^2)(aが奇数)と、
三辺が(a1,b1,c1)の外接直角三角形の斜辺が、内接円の半径をrとしますと、
c1=a1-r+b1-r=a1+b1-c (2*r=c)をとなるのを利用します。
この時I,Jは互いに素かつI>Jとなります。

Prologです。
c^2=I^2+J^2<=2*L^2よりI<=√(L/√(2))
先ずloop1/6で1からNまで互いに素でない2数、a,b>Lとなる数、偶数のaを除き、
loop2/6で原始ピタゴラス数をk倍した数が題意を満たすかどうか調べます。
すなわち外接三角形の面積の倍 (a1+b1+(a1+b1-2*r))*r=a1*b1 を変形して
a1=r*(a+b+r)/(2*b),b1=r*(a+b+r)/(2*a)が整数なら返り値を1増やします。

%SWI-Prolog ver 7.42,7.64,9.25
%:-initialization(start).       %Online Prolog Compiler,ideone.    
%start.

loop2(0,_,_,_,R,R).
loop2(K,X,Y,Z,R1,R):-
   X1 is X*K,Y1 is Y*K,Z1 is Z*K,V is (X1 + Y1 + Z1) * Z1,
   ((mod(V,X1*2)=:=0,mod(V,Y1*2)=:=0)->R2 is R1+1;R2 = R1),
   K1 is K-1,loop2(K1,X,Y,Z,R2,R).
   
loop1(N0,N,I,_,R,R):-
   N<I,!.
loop1(N0,N,I,J,R1,R):-
   J =:= I,!,I1 is I+1,loop1(N0,N,I1,1,R1,R).
loop1(N0,N,I,J,R1,R):-
   gcd(I,J)=\=1,!,J1 is J+1,loop1(N0,N,I,J1,R1,R).
loop1(N0,N,I,J,R1,R):-
   X0 is I^2-J^2,J1 is J+1,((0=:=mod(X0,2);X0>N0)->loop1(N0,N,I,J1,R1,R);
  (Y0 is 2*I*J,(Y0>N0->(I1 is I+1,loop1(N0,N,I1,1,R1,R));
  (Z0 is I^2+J^2,K is min(div(N0,X0),div(N0,Y0)),loop2(K,X0,Y0,Z0,R1,R2),
   loop1(N0,N,I,J1,R2,R))))).

solve(N0,R):-N is floor(sqrt(N0/sqrt(2))),loop1(N0,N,2,1,0,R).

start:-
    f(N0,A),(solve(N0,R)->(R==A->Str=" ok  ";Str=" no  ");
    write(fail)),write(" "),write(Str),writeln(N0->R),fail.
start.

f(10,1).
f(50,7).
f(100,15).
f(456,77).
f(1000, 173).      %抜けていたので追加(2025.4.5)
f(7654,1405).
f(75319,14133).
f(90346,16972).
f(100000,18797).

以前juliaで解いていたのですが、投稿しようとして見直したときに、
自分でも何をしているのかわかりませんでした。
そこで新たにプログラムを書きましたが、
元のほうがやや速いようですのでもう一度考えてみました。

求める外接三角形の辺の長さは原始ピタゴラス数の整数倍ですが、
原始ピタゴラス数とその奇数倍のピタゴラス数では
a,cが奇数、bが偶数ですので、a*cは奇数,a+b-cは偶数となり
a*c/(a+b-c)が整数となりませんので、題意に会う外接三角形はありません。

a<bの場合を除外するとa<bとなる原始ピタゴラス数が除かれますが、
原始ピタゴラス数の二倍のピタゴラス数(2*a,2*b,2*c)があるとすれば
2*(i^2-j^2)=(h*i)^2-(2*j/h)^2からhを求めるとh=√2。これはあり得ません。
一方
2*b=2*2*i*j=(i+j)^2-(i-j)^2,2*a=2*(i^2-j^2)=2*(i+j)(i-j),
2*b>2*aなので、ピタゴラス数(2*b,2*a,2*c)が求められます。
ただしI<=√(L/√(2))のときi1=i+jとするとi<=Iなのでi1<=2*Iです。

またa1/a=b1/b=(a1+b1-c)/cからa1=a*c/(a+b-c),b1=b*c/(a+b-c)となります。

よってi<=n,j<iとなるi,jで、
i,jが互いに素でない場合,a>Lの場合,a<bの場合を除外し、
(a,b,c)のk倍の(a1,b1,c1)に関してa1*c1/(a1+b1-c1),b1*c1/(a1+b1-c1)
が整数なら返り値に1を足します。

#julia ver 1.41,1.53,1.10.3

function solve(n0,v)
    n = Int(floor(sqrt(sqrt(2)*n0))) 
    sum = 0
    for i in 2 : n
     for j in 1 : i-1
       if gcd(i,j) !=  1 
          continue   
       end
       a = i^2 - j^2  
       if a>n0      
          continue
       end
       b = 2*i*j
       if b>a  
         break
       end
       c = i^2 + j^2
       for k in 1 : div(n0,a)
         a1 = a*k
         b1  =b*k
         c1 = c*k
         am = rem(a1*c1, a1+b1-c1)  
         bm = rem(b1*c1, a1+b1-c1) 
         if am == 0 && bm == 0
           sum+=1
         end
        end
      end
    end
     s = v == sum ? "ok " : "no "
     println(s,n0,"->",sum)
end

solve(10, 1)
solve(50, 7)
solve(100, 15)
solve(456, 77)
solve(1000, 173)
solve(7654, 1405)
solve(75319, 14133)
solve(90346, 16972)
solve(100000, 18797)
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?