• ベストアンサー

アルゴリズムだけでも教えてください。

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文など基本的な構造でできるそうですが、混乱してわかりません。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.8

3-1.結果が< 現在の値 > 前回の値 >の時さらに分岐します としてみてください。

lemonfish
質問者

お礼

ありがとうございます。 何とかプログラムできました。

その他の回答 (9)

回答No.10

プログラムは書けたということですが。 このような問題では、 ・今の状況はどうか? ・その状況下でどのような条件が起こったらどうするか という2段階で考えておくと混乱が少なくなります。「ステート遷移」という考え方です。 たとえば 【現在の状態:静止状態】  この条件下で、  1)今の値が前の値より大きい→現在の状態を「膨張」に変更  2)今の値は前の値より小さいが、減少率は 10%未満→なにもしない  3)今の値は前の値より小さく、減少率は 10%以上 → 現在の状態を「噴火が起きている」に変更 【現在の状態:膨張】  1)今の値が前の値より大きい→なにもしない(膨張のまま)  2) 2)今の値は前の値より小さいが、減少率は 10%未満→現在の状態を「膨張が終わる(=静止状態)」に変更  3)今の値は前の値より小さく、減少率は 10%以上 → 現在の状態を「噴火が起きている」に変更 【現在の状態:噴火が起きている】  1)今の値が前の値より大きい→現在の状態を「噴火が終わる(=静止状態)」に変更  2) 2)今の値は前の値より小さいが、減少率は 10%未満→なにもしない  3)今の値は前の値より小さく、減少率は 10%以上 → なにもしない あと、それぞれ状態が遷移したときに適切な表示をします。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.9

とりあえず、アルゴリズムを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

lemonfish
質問者

お礼

回答ありがとうございます。 「膨張」には特に制約はありません。 ただ、まだド初心者なのでbluepixyさんのアルゴリズムは難しくて分かりませんでした。わざわざありがとうございます。

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.7

今の段階で私が言えることは全て言いました。 どのように表示するかはあなたの好みです。 とりあえず、#4の?に適切と思われる言葉を入れてください。 おかしいところがあれば指摘します。 出来たのなら、それをそのままコーディングすればよいのです。

lemonfish
質問者

お礼

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)
回答No.6

#1補>膨張する⇒値が、前の値よりも上がっている だと 山は1において膨張している 山は2において膨張している 山は3において膨張している となりませんか? それとも、膨張というにはもう少し制約となる条件があるのでしょうか?

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.5

あぁ、ちょっと2は書き方が悪くて分かりにくかったですね 2.<現在の値>と<前回の値>を比べます です。

lemonfish
質問者

お礼

回答ありがとうございます。 今プログラムしているのですが、噴火が終わった後に「噴火終わり」と表示するためにはどのように分岐すればよいのでしょうか? また、「噴火始まり」の条件になったときに、 「山は(1つ前の値で)膨張している」 「噴火が(現在の値で)起きている」 と表示するようにプログラムすればいいのでしょうか? よろしくお願いします。

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.4

基本的な流れを確認しましょう 1.現在の値を調べます 2.<?????>と<?????>を比べます 3.比べた結果によって分岐します 3-1.結果が<???>の時さらに分岐します 3-1-1.<???>の時「???」と出力します 3-1-2.<???>の時「???」と出力します 3-2.結果が<???>の時「???」と出力します 3-3.結果が<???>の時「???」と出力します 4.最初に戻ります 「???」に状況、<???>に条件、<?????>にデータが入ります。

lemonfish
質問者

お礼

回答ありがとうございます。少しずつ流れが分かってきました。 まず、最初に2つの値を読み込み、その2つを比べる、ということですか? 1の現在の値と、2の?????は別のものなのですか? よろしくお願いします。

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.3

では、考えられる「条件」をまとめましょう ・値が増えている ・値が10%未満減っている ・値が10%以上増えている この3つですね 4つの状況に対応させるために、条件を細かく分けます。 ・値が増えている  ・噴火中に 値が増えている  ・噴火していないときに 値が増えている これで状況と条件が一対一になりましたね。 最後に必要なデータを考えましょう。 上の「条件」を調べるために必要なデータを洗い出してください。 それが出来れば後一歩です。

lemonfish
質問者

お礼

回答ありがとうございます。 ・値が増えている  ⇒次の値を求める   ・値が10%未満の割合で減っている  ⇒「膨張が終わる」と表示 ・値が10%以上の割合で減っている  ⇒・「噴火している」と表示、次の値を求める この3つをif文を使って分類すればいいのでしょうか?そして全体にwhile文を使って繰り返し値を読んでいけばいいのでしょうか? しかし、噴火してから再び値が上がった時に「噴火終わり」と表示するするにはどのようにすればいいのでしょうか? よろしくお願いします。   

  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.2

課題とのことなのでヒントの追加だけ. どのような条件でどのような出力をするのかまとまったら(表にするのがよいでしょう),その判断に必要なデータを保持するようにプログラミングする必要があります. たとえば,ある入力行を読み込むときに,1つ前の行のデータを上書きして消して(捨てて)しまっては駄目だ,とか.

lemonfish
質問者

お礼

回答ありがとうございます。 条件ですが、私がNo1の方に返信した条件で合っているのでしょうか? 膨張しているときと、噴火して再び膨張する時の違いをどうすればいいか、が分かりません。 もう少し、具体的にヒントを頂きたいのですが・・・ よろしくお願いします。

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.1

考えられる状況は4つ ・膨張する ・膨張が終わる ・噴火が起きている ・噴火が終わる ですね? それぞれの条件を書き出してください。

lemonfish
質問者

お礼

回答ありがとうございます。 まず、 膨張する⇒値が、前の値よりも上がっている。 膨張が終わる⇒値が、前の値よりも下がっているが、割合は10%未満。 噴火が起きている⇒値が、前の値よりも下がっていて、割合は10%以上。 噴火が終わる⇒噴火が起きた後、値が再び上がった時。 になると思います。この条件をどのように、どこでif文、while文を使ってプログラムすればいいかを考えていると混乱してしまいます。 よろしくお願いします。

関連するQ&A

  • 組み合わせ問題のアルゴリズム

    あらかじめ用意された整数を足して、その合計がある指定された整数と等しくなる組み合わせの数を調べるプログラムを書こうとしているのですが、苦労しています。 具体例がないと伝わりにくいかもしれないので例をあげると、 例えばあらかじめ用意された整数というのが 1・1・2・2・5・8 の4つで、 指定された整数が10である場合は、 8と2 8と1と1 5と2と2と1 という3通りの組み合わせがあるので、3を出力したいというわけです。 今まではもっと単純なアルゴリズムしか考えてこなかったので、こういった組み合わせのような問題が難しく感じられます。 こういう場合、アルゴリズムはどのようなものが考えられるでしょうか。 よろしくお願いします。

  • うるう年判定のアルゴリズム

    javaでうるう年判定のプログラムを作成しています。 プログラム自体はサーバにアップするときに実行結果が正しいかどうかテストされます。 仕様としては、 1.時間に関するAPIなどは一切使わずに完全に自作 2.入力される値はLong型の"秒"数(APIで提供されているのはミリ秒ですが) 3.60537895631062456L などの入力値に対して、年/月/日 (曜日) 時:分:秒 yday=元旦からの経過日数 を出力 最初は以下の関数を使用してループをかけていたのですが、仕様3の入力値に対して50秒近くかかってしまい、上手くいきませんでした。 public static int isLeap(int year){ if(year%4==0 && (year%100!=0 || year%400==0)) return 1; return 0; } 問題点はループ回数が多いことで、作る時点で分かってはいたのですが、ここまで遅くなるとは思っても見ませんでした。 これを使わない方法としては、一回だけうるう年(=n)を見つけ、その後は「(n+4)との比較+100で割り切れず400で割り切れる場合は別」という処理を行うことによって、処理時間を30秒付近にまで短縮することができたのですが、どうも10~15秒以内で終わらせなければテストにパスすることができないようです。 なんとか色々考えてはみたものの、上手いアルゴリズムは思いつきませんでした。 うるう年を処理するための"高速な"アルゴリズムはないのでしょうか。 お知恵を貸してください。よろしくお願いします。

    • ベストアンサー
    • Java
  • うるう年判定のアルゴリズム

    javaでうるう年判定のプログラムを作成しています。 プログラム自体はサーバにアップするときに実行結果が正しいかどうかテストされます。 仕様としては、 1.時間に関するAPIなどは一切使わずに完全に自作 2.入力される値はLong型の"秒"数(APIで提供されているのはミリ秒ですが) 3.60537895631062456(Long値) などの入力値に対して、年/月/日 (曜日) 時:分:秒 yday=元旦からの経過日数 を出力 最初は以下の関数を使用してループをかけていたのですが、仕様3の入力値に対して50秒近くかかってしまい、上手くいきませんでした。 public static int isLeap(int year){ if(year%4==0 && (year%100!=0 || year%400==0)) return 1; return 0; } 問題点はループ回数が多いことで、作る時点で分かってはいたのですが、ここまで遅くなるとは思っても見ませんでした。 これを使わない方法としては、一回だけうるう年(=n)を見つけ、その後は「(n+4)との比較+100で割り切れず400で割り切れる場合は別」という処理を行うことによって、処理時間を30秒付近にまで短縮することができたのですが、どうも10~15秒以内で終わらせなければテストにパスすることができないようです。 なんとか色々考えてはみたものの、上手いアルゴリズムは思いつきませんでした。 うるう年を処理するための"高速な"アルゴリズムはないのでしょうか。 お知恵を貸してください。よろしくお願いします。

  • 二分探索アルゴリズムの問題の解法

    二分探索アルゴリズムを用いて、N件のレコードを持つ表の中からキーの値がkに一致するレコードを探し出す探索を考える。この探索について以下の問いに答えよ。 1)このアルゴリズムにおいて最も計算時間が短くなるのは、どのような場合か? 2)このアルゴリズムにおいて最も計算時間が長くなる場合の時間計算量をNのオーダーで表せ。 全くわからないので教えていただいたら、ありがたいです。 一応二分探索なのでO(logN)だけはわかります。 宜しくお願いします。

  • 普賢岳

    や御獄山の噴火は唐突な自然破壊の恐ろしさに今更に驚くばかりですが日本列島には100以上の24時間監視体制が必要な活火山が有るそうですが次に危ない地域は何処でしょうか? 世界遺産になったばかりの富士山も富士5湖の水位異常低下などは やはり、 地底からの警告を発信し続けていると言う事デスヨネ? 箱根山なども噴火可能性が高いのでしょうか? いざ 噴火となればどんな事に成りますか?

  • 大阪 生駒山は火山か

    大阪の生駒山が火山なのかという質問です。 (社会とか歴史のカテゴリだったでしょうか・・・?) Wikipediaで「火山の一覧(日本)」と調べると、生駒山は 含まれていません。 ただ、注意書きに 「噴火によって直接できた地形が残っていないものは火山の定義に合致しないので、このリストに追加しないでください。特に、第三紀の火山岩からなり、侵食による削れ残りが山の形をしているものは間違えやすいので注意してください。 例:二上山、耳成山、畝傍山…など。 」 との記述がありました。 例に挙げられている「二上山」とは生駒山地の近くに位置しています。 「火山岩からなり、侵食による削れ残りが山の形をしているもの」 というのは・・・火山活動でできた山でも火山に数えないものがある ということなんでしょうか・・・?火山の定義があるんですね・・・。 また、 http://www2.mus-nh.city.osaka.jp/learning/geoguid/kakougan.html http://kosmochlor3.at.webry.info/200904/article_2.html 以上のHPなどには、 「死火山。 しかし、中央構造線と直交する西の県境、生駒山地⇒ 金剛山地の断層線の直下には今なお重力異常が認められる。」 などの記述もありました・・・。 対して「褶曲(しゅうきょく)山地説が有力となっている。」との記述 があるのが以下のHPです。 http://100.yahoo.co.jp/detail/%E7%94%9F%E9%A7%92%E5%B1%B1%E5%9C%B0/ まだ判明していないということなのでしょうか? 詳しい方よろしくお願いします。

  • アルゴリズムでわからない問題があります。(C言語)

    問題1:探索アルゴリズムであるハッシュ法について正しいものを選べ。 (1)ハッシュ関数の出力によりデータを格納した配列の先頭から順番に調べる. (2) 入力データを,ハッシュ関数の出力により求めた格納場所に基づいて,あらかじめ木構造に格納しておく. (4) 入力データを格納した配列を繰り返し2つに分割し,それぞれを順番に調べていく. (3) 入力データから格納場所の位置に変換する関数(ハッシュ関数)の出力により,データの探索場所を決定する。 (5) 入力データを,ハッシュ関数の出力により求めた格納場所に基づいて,あらかじめヒープに格納しておく 問題2:探索アルゴリズムであるハッシュ法について正しくないものを選べ。 (1)入力データはハッシュ値で決められる場所に格納される. (2) ハッシュ関数には,異なる入力の値に対し異なる値を出力することが求められる. (3) ハッシュ関数の時間計算量は,入力データのサイズに比例する. (4) データの格納場所が大きい方が効率がよい. (5) 一般に2分探索法より高速に動作する. どなたかアルゴリズムに詳しい方回答お願いします

  • 浅間山の噴火

    最近急に火山活動が活発化してきた浅間山のことが気になっています。地元の群馬出身なので余計に気になります。浅間山は江戸時代に大噴火をしたそうですし、最近では雲仙の普賢岳の例もあります。大火砕流とか起きる可能性はありますか?

  • ガウシアンフィッティングのアルゴリズム

    c言語等を用いて実験データの解析を行おうと思っています。 データの形式は(x・・・時間軸、y・・・値)の列になっていて、 これをグラフにすると、パルス状の波形が連続する形になっています。 求めたい情報は、各パルス波形の山に対応する時刻の羅列 なのですが、現在ではガウス曲線近似機能のついたグラフソフトで、 一個一個手作業で求めています。 これを、解析プログラムを作って自動化しようと思っているのですが、 ガウス曲線(鋭い立ち上がりの)に近い部分を自動的に検出する方法、 また、フィッティングを数値計算的に行う方法がわかりません。 このようなアルゴリズムを考える上で参考になるようなHPや文献を ご存知の方がいらっしゃれば、教えていただきたいと思っています。

  • Perlのアルゴリズムについて教えてください!

    データファイルAとデータファイルBからデータを受け取って、データファイルB中の第i番目の文Siの重要度を式1に基づいて計算して、重要度と順位(重要度の高い順に1位、2位、、)を各文Siに付与するアルゴリズムを考える場合、式1のWi,jは文Siに出現するj番目の単語で、niはSiに出現する単語の数となる。Wi,jの出現頻度はファイルAから得られるものとする。 /*データファイルA*/ はじめ:␣12 改行 こる:␣1 改行 いく:␣23 改行 みせ:␣4 改行 ... というように前に文字列(基本形)が入り後ろに数字が記載されているデータ /*データファイルB*/ はじめ␣はじめ␣形容詞 改行 こる␣こる␣形容詞 改行 ... EOS 改行 ... ␣は空文字 1.ファイルAにまだ読み込んでいない行がある限り繰り返す    1-1.ファイルから一行読み込む    1-2.その行の基本形用のカウンタを用意して、そのカウンタにその基本形の出現頻度を代入する。 2.文番号カウンタと文重要度変数を用意して、初期値をそれぞれ1と0にする。 3.データファイルBにまだ読み込んでいない行がある限り繰り返す 3-1.ファイルから1行読み込む 3-2.もしその行がEOSであれば、文番号カウンタと文重要度変数の値を出力する。その後、文重要度変数を0にして、文番号カウンタを1増やす。 3-3.これ以降のアルゴリズムが解けないので教えてください。