ピタゴラス数を列挙するには?

解決


タモリ魚斎  2005-08-06 01:03:09  No: 16890

3≦a<b≦100を満たすピタゴラス数
(a,b,c,),(a*a+b*b=c*c)
をすべて出力し、その総数も出力するというプログラムを作成したいのですが、どのようにしたらよいのでしょうか。内容を教えていただけませんでしょうか。


夏休み?  2005-08-06 01:28:06  No: 16891

最近、夏休みの宿題っぽい質問が多く見受けられますが、
宿題を成し遂げる意義について、少しはお考え下さい。


これが答えだ  2005-08-06 01:41:57  No: 16892

まず、基礎数学を勉強し、次にDelphiを勉強する。
最後に自分でコーディングする


もうこの際  2005-08-06 04:59:32  No: 16893

答えをインラインアセンブラを利用して記述するなんでどうですかね…


とおりすがりん  2005-08-06 05:19:21  No: 16894

実は答えたい気持ちがいっぱい。
数理アルゴリズムとしては結構いい例題な気がします。

つい最近同じ事を書いたけど、
まず、自分がどんな風に考え、どこで判らないのかを説明しては?

宿題?について教えを請うこと自体は否定しませんが、真摯な姿勢が感じられないと、この手の「課題教えて」っぽい質問にはまともな答えは返ってこない気がします。


ウリャ  2005-08-06 06:52:51  No: 16895

諸先輩方の意見に賛成です。
でもやっちゃいました。本能には逆らえません。
感想としては、結構難しかったです。
まだまだ高速化できますが、可読性が悪くなるのでこの辺に留めておきます。

unit Unit1;

interface

uses
  Windows, SysUtils, Classes, Controls, Forms, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    function getPythagoras(MaxValue:integer; var count:integer):string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var str:string;
    c:Cardinal;
    MaxValue,count:integer;
begin
  MaxValue:=100;
  c:=GetTickCount;
  str:= getPythagoras(MaxValue,count);
  c:=GetTickCount - c;
  str:= '算定範囲 = ' + inttostr(MaxValue) + #13#10 +
        '総数 = ' + inttostr(count) + '個' + #13#10 +
        '処理にかかった時間 = ' + inttostr(c) + 'ミリ秒' + #13#10 +
        str;
  Memo1.Text:=Str;
end;

function TForm1.getPythagoras(MaxValue: integer; var count:integer): string;
// MaxValue:a,bの最大値
// count:総数
var
  a,b,c,d,m,n: integer;
  cList      : array of integer;
  function noMuch(index:integer):boolean;
  var i:integer;
  begin
    for i:= 0 to Length(cList)-1 do
      if cList[i]=index then
      begin
        Result:=False;
        exit;
      end;
    SetLength(cList,Length(cList)+1);
    cList[Length(cList)-1]:=index;
    Result:=True;
  end;
begin
 n:=0;
 repeat
   inc(n);
   m:=n;
   repeat
     inc(m);
     a:=(m*m-n*n);
     b:=(2*m*n)  ;
     c:=(m*m+n*n);
     d:=0;
     repeat
       inc(d);
       if (a*d <= MaxValue) and (b*d <= MaxValue) and
          (noMuch(c*d)=True) then
       if a<b then
         Result:=Result +
                 inttostr(a*d) +#9+
                 inttostr(b*d) +#9+
                 inttostr(c*d) + #13#10
         else
         Result:=Result +
                 inttostr(b*d) +#9+
                 inttostr(a*d) +#9+
                 inttostr(c*d) + #13#10
     until (a*d > MaxValue) or (b*d > MaxValue);
   until (a > MaxValue) or (b > MaxValue);
   m:=n;
   a:=(m*m-n*n);
   b:=(2*m*n)  ;
 until (a > MaxValue) or (b > MaxValue);
 count:=Length(cList);
end;

end.


ちがってない?  2005-08-06 07:23:26  No: 16896

ウリャさん、勢いはわかるけど答えがちがうよ


ウリャ  2005-08-06 07:51:30  No: 16897

うーん…
エクセルで検算したけど答えに間違えは無い気がするのですが…
取りこぼしあるのかな?
間違えでは無いですが、
m,nは互いに素で片方が偶数、片方が奇数という判別はしてません。
例えばでよいので
足りない(a,b,c)もしくは間違ってる(a,b,c)を教えてくれませんか?


ウリャ  2005-08-06 08:46:22  No: 16898

足りない…
もうひと頑張りします orz


ウリャ  2005-08-06 09:11:28  No: 16899

ご指導ありです。
もっとスマートに解きたいですけどもう疲れました。
気合のある方挑戦してみてはいかがでしょうか?

function TForm1.getPythagoras2(MaxValue: integer; var count:integer): string;
// MaxValue:a,bの最大値
// count:総数
var
  a,b,c,d,e,m,n: integer;
  aList,bList,cList : array of integer;
  function noMuch(a,b,c:integer):boolean;
  var i:integer;
  begin
    for i:= 0 to Length(cList)-1 do
      if (cList[i]=c) and (aList[i]=a) and (bList[i]=b) then
      begin
        Result:=False;
        exit;
      end;
    i:= Length(cList);
    SetLength(aList,i+1);
    SetLength(bList,i+1);
    SetLength(cList,i+1);
    aList[i]:=a;
    bList[i]:=b;
    cList[i]:=c;
    Result:=True;
  end;
begin
 n:=0;
 repeat
   inc(n);
   m:=n;
   repeat
     inc(m);
     a:=(m*m-n*n);
     b:=(2*m*n)  ;
     c:=(m*m+n*n);
     if a>b then
     begin
       e:=a; a:=b; b:=e;
     end;
     d:=0;
     repeat
       inc(d);
       if (a*d <= MaxValue) and (b*d <= MaxValue) and
          (noMuch(a*d,b*d,c*d)=True) then
       begin
         Result:=Result +
                 //inttostr(m) +#9+
                 //inttostr(n) +#9+
                 //inttostr(d) +#9+
                 inttostr(a*d) +#9+
                 inttostr(b*d) +#9+
                 inttostr(c*d) +#13#10;
       end
     until (a*d > MaxValue) or (b*d > MaxValue);
   until (a > MaxValue) or (b > MaxValue);
   m:=n;
   a:=(m*m-n*n);
   b:=(2*m*n)  ;
 until (a > MaxValue) or (b > MaxValue);
 count:=Length(cList);
end;


タモリ魚斎  2005-08-06 10:05:24  No: 16900

みなさん、ご回答ありがとうございました。特にウリャさん、プログラムを示していただいて大変参考になりました。
皆さんの指摘どおり、これは提出課題のひとつです。
ただ、自分を始めこの授業の履修者は授業で主に図形描写のプログラミングを学習し、さらにDelphiのプログラミングについて体系だって教えられたわけでもないのに(ごく簡単なfor文、if文程度)、突然高度な数式を扱う試験課題を出されて、かなり困惑している状況でした。自分自身いろいろな本を参照したのですが、なにせ四則演算、数の大小・範囲設定、方程式の解の出力の仕方などを詳しく習ってないため、数学的な知識をうまく生かせなかったのです。
時間的にも急だったので失礼な質問文になってしまいました。ご回答いただいきありがとうございました。


Fusa  2005-08-06 23:45:46  No: 16901

>ただ、自分を始めこの授業の履修者は授業で主に図形描写のプログラミングを学習し、さらにDelphiのプログラミングについて体系だって教えられたわけでもないのに(ごく簡単なfor文、if文程度)、突然高度な数式を扱う試験課題を出されて、かなり困惑している状況でした。

そういう不適切な課題を出されたら
出す人(先生?)に指摘して修正させる方がいいよー。

君がここで教えられたものをそのままコピペして
先生に提出すると、君は不正に成績を稼ぐとともに

その先生自身が"不適切な難しさの課題を提出している"
という間違った行為に気がつかないから、
間違った教育が続く事になるんだ。

そういう事に対してみんなが不愉快感を感じているのかもね。


ウォレス  2005-08-07 02:42:51  No: 16902

出遅れ・・

こんなんでどう?
※mathをusese節に追加すること

procedure TForm1.Button1Click(Sender: TObject);
var
  count :Integer;
  Bf:AnsiString;
  a,b :Integer;
  c :Double;
begin
  {
    100以下なら時間もたいしてかららないので、
    しらみつぶしに挙げる方がラク。
    最大値が増えると指数的に計算量が増えるので注意  
  }
  count := 0;
  for a:=3 to 99 do
  begin
    for b:=a+1 to 100 do
    begin
      c := sqrt(a*a + b*b);
      if abs(c - Trunc(c + 0.5)) < MinDouble then  //sqrt(a^2 + b^2) が整数かどうか荒くチェック
      begin
        if ( Trunc(c + 0.5)*Trunc(c + 0.5) = a*a + b*b) then //再チェック
        begin
          Bf := Format('a:%3d, b:%3d, c;%3d',[a,b,Trunc(c+0.5)]);
          Memo1.Lines.add(Bf);
          Inc(count);
          Bf := '';
        end;
      end;
    end;
  end;

  Bf := Format('count:%d',[count]);
  Memo1.Lines.add(Bf);
end;


ウォレス  2005-08-07 09:25:17  No: 16903

(u^2-v^2)^2 + (2*u*v)^2 = (u^2+v^2)^2
から、u,vを総当りで代入すれば(a,b,c)の組み合わせが全部求められるものと思っていましたが、(a,b,c)の素数倍はこれでは作れないようです。知りませんでした。
(ということは素数を列挙する必要があることになります。)
各要素が数十万まで求めるとなると総当りではかなりしんどくなりますので、一旦素数を列挙してから作っていくことになります。たぶん。
そこまでは求められていないでしょうね。

それから、一度荒くチェックする必要はあまりないですね。
ほとんどが弾かれる上記のケースでは最初に荒く判定し枝狩りにしようと思ってましたが、どうみても「荒くチェック」の部分は無駄です。


ウォレス  2005-08-07 18:44:34  No: 16904

あ〜・・
ウリャさんは既にm,nを使っちゃんと全部の解を求められていますね。
かなり恥ずかしい。
リストで重複チェックすれば素数かどうかを気にせず総当りでも可能、ということですね。

(駄レス申し訳ありません)


タモリ魚斎  2005-08-12 22:23:31  No: 16905

レス遅れてすみません。
ウリャさん、ウォレスさん、ありがとうございました。
再現してみたところ、63通りの答えがちゃんと出力されました。
一方的なお願いにもかかわらずにレスをいただいたことに感謝します。

>Fusaさん
多分教官のほうも、生徒がすべての課題を自力で解いてくる事を想定していないと思われます。もし教官が生徒が自力で解いてくるものと思っているなら、相当生徒のことを把握していない教官でしょう。後者のような教官はだいたい採点がいい加減なので別にいいんですが。
失礼な「教えて」型の書き込みをしてしまいすみませんでした。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加