- ベストアンサー
アルゴリズムだけでも教えてください。
C言語ド初心者のものです。 以下のプログラムを書かないといけないのですが、どのように組み立てればいいか、アイデアさえ思いつきません。 アルゴリズムだけでも教えていただけないでしょうか? できればプログラムのほうもお願いしたいのですが・・・。 よろしくお願いします。 問題文: 「以下の例で、左が1時間ごとの時間、右のデータが火山に設置されたメーターによって計測された、地面の角度(水平方向とのなす角、°)を示します。「噴火が起きる」という定義は、値が1時間前の値より10%以上下がっている時とします。 例: 00 20.54 01 20.62 02 20.77 03 20.92 04 18.63 05 18.50 06 20.12 07 21.39 08 21.52 09 20.55 10 21.46 11 22.71 12 22.83 13 23.01 14 18.01 15 15.73 16 15.68 17 16.03 という入力に対して、出力は: 山は3において膨張している 噴火が3と4の間で起きている 噴火が5と6の間で終わる 山は8において膨張している 膨張は9において終わる 山は12において膨張している 噴火が13と14の間で起きている 噴火が16と17の間で終わる 」 と言う風に出力されればOKです。 if文やwhile文など基本的な構造でできるそうですが、混乱してわかりません。 よろしくお願いします。
- みんなの回答 (10)
- 専門家の回答
質問者が選んだベストアンサー
3-1.結果が< 現在の値 > 前回の値 >の時さらに分岐します としてみてください。
その他の回答 (9)
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
プログラムは書けたということですが。 このような問題では、 ・今の状況はどうか? ・その状況下でどのような条件が起こったらどうするか という2段階で考えておくと混乱が少なくなります。「ステート遷移」という考え方です。 たとえば 【現在の状態:静止状態】 この条件下で、 1)今の値が前の値より大きい→現在の状態を「膨張」に変更 2)今の値は前の値より小さいが、減少率は 10%未満→なにもしない 3)今の値は前の値より小さく、減少率は 10%以上 → 現在の状態を「噴火が起きている」に変更 【現在の状態:膨張】 1)今の値が前の値より大きい→なにもしない(膨張のまま) 2) 2)今の値は前の値より小さいが、減少率は 10%未満→現在の状態を「膨張が終わる(=静止状態)」に変更 3)今の値は前の値より小さく、減少率は 10%以上 → 現在の状態を「噴火が起きている」に変更 【現在の状態:噴火が起きている】 1)今の値が前の値より大きい→現在の状態を「噴火が終わる(=静止状態)」に変更 2) 2)今の値は前の値より小さいが、減少率は 10%未満→なにもしない 3)今の値は前の値より小さく、減少率は 10%以上 → なにもしない あと、それぞれ状態が遷移したときに適切な表示をします。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
とりあえず、アルゴリズムをPerlで。 #6の補足が戴けないので、ちょっと適当(例のような出力にはなりません)です。 ---------------------------------------------------------------- use encoding "UTF-8", STDOUT => "cp932"; $undefined = -100.0; #未定義値 ${'前角度'} = $undefined; #あり得ない数値で初期化 ${'噴火'} = ""; #噴火の状態 while($line=<DATA>){#ファイルからデータがある間一行読み出す $message = null; (${'時間'}, ${'角度'}) = split(/ /, $line);#一行を切り分ける if(${'前角度'} != $undefined){ #前角度が有る時比較をする if(${'前角度'} < ${'角度'}){ #角度が増えた $message = sprintf("山は%dにおいて膨張している", ${'時間'}); if(${'噴火'} eq "噴火中"){ #噴火中の時噴火終了 ${'噴火'}=null; $message = sprintf("噴火が%dと%dの間で終わる",${'時間'}-1,${'時間'}); } } elsif(${'前角度'} > ${'角度'}){#角度が減った if(${'前角度'}*0.9 < ${'角度'} ){#10%未満 $message = sprintf("膨張は%dにおいて終わる",${'時間'}) if ${'噴火'} ne "噴火中";#噴火中ではない } else { #10%以上 $message = sprintf("噴火が%dと%dの間で起きている", ${'時間'}-1, ${'時間'}); ${'噴火'} = "噴火中"; } } } if($message ne null){#メッセージが設定されている時出力 printf "$message\n"; } ${'前角度'} = ${'角度'};#前角度として角度を保存 } __DATA__ 00 20.54 01 20.62 02 20.77 03 20.92 04 18.63 05 18.50 06 20.12 07 21.39 08 21.52 09 20.55 10 21.46 11 22.71 12 22.83 13 23.01 14 18.01 15 15.73 16 15.68 17 16.03
お礼
回答ありがとうございます。 「膨張」には特に制約はありません。 ただ、まだド初心者なのでbluepixyさんのアルゴリズムは難しくて分かりませんでした。わざわざありがとうございます。
- Trick--o--
- ベストアンサー率20% (413/2034)
今の段階で私が言えることは全て言いました。 どのように表示するかはあなたの好みです。 とりあえず、#4の?に適切と思われる言葉を入れてください。 おかしいところがあれば指摘します。 出来たのなら、それをそのままコーディングすればよいのです。
お礼
1.現在の値を調べます 2.<現在の値>と<前回の値>を比べます 3.比べた結果によって分岐します 3-1.結果が<現在の値<=前回の値>の時さらに分岐します 3-1-1.<現在の値<=0.9×前回の値>の時「噴火始まり」と出力します 3-1-2.<現在の値>=0.9×前回の値>の時「膨張終わり」と出力します 3-2.結果が<現在の値>前回の値>の時「膨張中」と出力します 3-3.結果が<???>の時「???」と出力します 4.最初に戻ります 3-3がわかりません。「噴火終了」としたいのですが・・・。 これをプログラムすると、連続して値が大きくなっているとき、「膨張中」がそのつど表示されてしまいます。 どうすればいいでしょうか?
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#1補>膨張する⇒値が、前の値よりも上がっている だと 山は1において膨張している 山は2において膨張している 山は3において膨張している となりませんか? それとも、膨張というにはもう少し制約となる条件があるのでしょうか?
- Trick--o--
- ベストアンサー率20% (413/2034)
あぁ、ちょっと2は書き方が悪くて分かりにくかったですね 2.<現在の値>と<前回の値>を比べます です。
お礼
回答ありがとうございます。 今プログラムしているのですが、噴火が終わった後に「噴火終わり」と表示するためにはどのように分岐すればよいのでしょうか? また、「噴火始まり」の条件になったときに、 「山は(1つ前の値で)膨張している」 「噴火が(現在の値で)起きている」 と表示するようにプログラムすればいいのでしょうか? よろしくお願いします。
- Trick--o--
- ベストアンサー率20% (413/2034)
基本的な流れを確認しましょう 1.現在の値を調べます 2.<?????>と<?????>を比べます 3.比べた結果によって分岐します 3-1.結果が<???>の時さらに分岐します 3-1-1.<???>の時「???」と出力します 3-1-2.<???>の時「???」と出力します 3-2.結果が<???>の時「???」と出力します 3-3.結果が<???>の時「???」と出力します 4.最初に戻ります 「???」に状況、<???>に条件、<?????>にデータが入ります。
お礼
回答ありがとうございます。少しずつ流れが分かってきました。 まず、最初に2つの値を読み込み、その2つを比べる、ということですか? 1の現在の値と、2の?????は別のものなのですか? よろしくお願いします。
- Trick--o--
- ベストアンサー率20% (413/2034)
では、考えられる「条件」をまとめましょう ・値が増えている ・値が10%未満減っている ・値が10%以上増えている この3つですね 4つの状況に対応させるために、条件を細かく分けます。 ・値が増えている ・噴火中に 値が増えている ・噴火していないときに 値が増えている これで状況と条件が一対一になりましたね。 最後に必要なデータを考えましょう。 上の「条件」を調べるために必要なデータを洗い出してください。 それが出来れば後一歩です。
お礼
回答ありがとうございます。 ・値が増えている ⇒次の値を求める ・値が10%未満の割合で減っている ⇒「膨張が終わる」と表示 ・値が10%以上の割合で減っている ⇒・「噴火している」と表示、次の値を求める この3つをif文を使って分類すればいいのでしょうか?そして全体にwhile文を使って繰り返し値を読んでいけばいいのでしょうか? しかし、噴火してから再び値が上がった時に「噴火終わり」と表示するするにはどのようにすればいいのでしょうか? よろしくお願いします。
- a-saitoh
- ベストアンサー率30% (524/1722)
課題とのことなのでヒントの追加だけ. どのような条件でどのような出力をするのかまとまったら(表にするのがよいでしょう),その判断に必要なデータを保持するようにプログラミングする必要があります. たとえば,ある入力行を読み込むときに,1つ前の行のデータを上書きして消して(捨てて)しまっては駄目だ,とか.
お礼
回答ありがとうございます。 条件ですが、私がNo1の方に返信した条件で合っているのでしょうか? 膨張しているときと、噴火して再び膨張する時の違いをどうすればいいか、が分かりません。 もう少し、具体的にヒントを頂きたいのですが・・・ よろしくお願いします。
- Trick--o--
- ベストアンサー率20% (413/2034)
考えられる状況は4つ ・膨張する ・膨張が終わる ・噴火が起きている ・噴火が終わる ですね? それぞれの条件を書き出してください。
お礼
回答ありがとうございます。 まず、 膨張する⇒値が、前の値よりも上がっている。 膨張が終わる⇒値が、前の値よりも下がっているが、割合は10%未満。 噴火が起きている⇒値が、前の値よりも下がっていて、割合は10%以上。 噴火が終わる⇒噴火が起きた後、値が再び上がった時。 になると思います。この条件をどのように、どこでif文、while文を使ってプログラムすればいいかを考えていると混乱してしまいます。 よろしくお願いします。
お礼
ありがとうございます。 何とかプログラムできました。