0
0

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:「スクエア・カルテット」問題の解答

0
Last updated at Posted at 2026-09-05

Kawazoe(@riverplus)さんのCodeIQの問題です。
こちらに問題と解答例があります。
->https://sw-logic.com/Portfolio/Programing/CodeIQ/2628.php
こちらにも情報があります。
->https://posfie.com/@riverplus/p/N1aRlyj

問題
 要約すると、自然数x,y,a,bにおいて、あるa,bに対して、
 x^2+a^2 = y^2+b^2
 解となるx,yすべてに対する x+y の総和 F(a,b) を求める問題です。

式を変形すると (x+y)*(x-y)=b^2-a^2 なので
n=|b^2-a^2| を素因数分解し(2026.9.5訂正->素因数分解して組合せ)、
大きいほうが x+y 小さいほうが |x-y|  
しかし n を i = x-y (i=1,2..、x > y) で割ったほうが簡単そうです。
あるiに対して(x,y)は高々一組
x+y > x-y より i < √n
x,yが自然数なので (x+y)+(x-y) = 2*x は偶数(偶数ならx,yがある)

偶々ですが前回投稿した「マルチプル・テーブル 」を簡単にした感じです。

#julia ver 1.0,1.41,1.53,1.85,1.12.1

function solve(a,b,v)
    n = abs(a^2-b^2)
    sum = 0
    for i in 1 : Int(floor(sqrt(n)-1))
        (d,m) = divrem(n,i)
        if m == 0 && iseven(d + i)
            sum += d
        end
    end
    s = sum ==  v ? "ok " : "no "
   println(s,sum)
end
solve(3,10,104)
solve(10,26,716)
solve(20 100,15022)
solve(19126,98765,16043311668)

Picatでも書きました。
Picatはvscode(下記ページ参照) 
 https://qiita.com/smallbigcats/items/9167bfcb01deb3da6f85
または Attempt This Online(https://ato.pxeger.com)
というところからrunをクリックしてPicatを選べば実行できます。

% Picat v 3.9#7

solve(A,B,R) => 
    N = abs(A*A-B*B),
    Sum = 0,
    foreach(I in 1 .. floor(sqrt(N) -1),N rem I =:= 0 )
       D := N div I,
       if (D+I) rem 2 =:= 0 then 
          Sum := Sum + D, 
       end, 
    end,
    R = Sum.

main =>    
  Data = [(3,10,104),(10,26,716),(20,100,15022),(19126,98765,16043311668)],
  foreach((A,B,N) in Data)
    if solve(A,B,R) then
      Str = cond(R == N, " ok  ", " no  "),
      printf(" %s %w,%w -> %w%n", Str, A,B, R)
    else
      printf(" fail %w,%w%n", A,B)
    end,
  end.

2026.9.5日訂正追記
投稿後 https://posfie.com/@riverplus/p/N1aRly を見に行って
間違いに気づきました。すべてのテストケースを把握していませんで、
ininsanusさんのhttps://yuppe19.bitbucket.io/sqquartet.html
の中のa=10,b=50の問題の答えが合いません。
私の過去のコードが

   for i in 1 : Int(floor(sqrt(n)))
      (d,m) = divrem(n,i)
      if m == 0 && iseven(d + i) && i != d
          sum += d
      end

だったのを簡略化して投稿のコードにしたのですが、そのままにするか

for i in 1 : Int(floor(sqrt(n-1)))

にすべきでした。二つのコードを訂正するのは紙面の無駄でしょうから、
ininsanusさんのデータをコピーさせていただく容易さにより、
Picatの訂正をします

solve(A,B,R) => 
    N = abs(A*A-B*B),
    Sum = 0,
    foreach(I in 1 .. floor(sqrt(N)),N rem I =:= 0 )
       D := N div I,
       if ((D+I) rem 2 =:= 0, I != D) then 
          Sum := Sum + D, 
       end, 
    end,
    R = Sum.

main =>    
  Data = [(3, 10104),
    (10, 50, 3500),
    (20, 100, 15022),
    (4, 5, 9),
    (10, 26, 716),
    (11, 389, 291886),
    (123, 456, 294166),
    (35672, 61243, 5082405064),
    (71200, 82321, 2490724704),
    (19126, 98765, 16043311668)],
  foreach((A,B,N) in Data)
    if solve(A,B,R) then
      Str = cond(R == N, " ok  ", " no  "),
      printf(" %s %w,%w -> %w%n", Str, A,B, R)
    else
      printf(" fail %w,%w%n", A,B)
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?