Ryu_1936
@Ryu_1936

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

薬が無くなるまでの予定作成アルゴリズム

解決したいこと

Android Studio (Java)で服薬管理アプリケーションの開発をしています。
取得情報をもとに薬が無くなるまでの予定を作成するアルゴリズムが思い浮かばないので質問させていただきます。

現在取得している情報
・服用回数(int)
・服用するタイミング(int)
・頻度(int)
・開始日(int)

服用回数:
(処方された数)/(一回に服用する数)

服用するタイミング:
「朝」:1
「昼」:2
「夜」:3
「朝夜」:4
「朝昼夜」:5
「必要に応じて」:6

頻度:
別ページからの遷移で持ってきているため毎日以外はすべて乗算して持ってきています。
毎週月水土曜日の場合は「130」で持ってきています。
「毎日」:1
「月」:2
「火」:3
「水」:5
「木」:7
「金」:11
「土」:13
「日」:17

開始日:
2022年10月28日の場合は
「20221028」として扱っています

前提条件として
開始日が必ずしも開始日の条件に合っているかを判定しないといけない。
//例
毎週火金曜日になっているのに、開始日が月曜日になっている可能性がある。

最終的にアルゴリズムの結果としてほしい数値

開始日からの服用回数が0になるまでの日付(int)とタイミング(int)
「日付」20221028
「服用するタイミング」1(朝)

補足情報

服用するタイミングが「必要に応じて」の場合は結果を出さずに処理を終わらせたい。

ご質問にはなるべく答えさせていただきます。
稚拙な文章で分かりづらいと思いますが、どなたかご教示お願いいたします。

0

2Answer

中々ユニークな処理をされていますね、真面目に作るのであれば値の受け渡し用にクラスを作ったりZonedDateTimeの利用などを検討しますが、仕組みとして成り立っていますので取り敢えずそのまま進めましょう。
(例えばプログラミングでは数値で組み合わせを作るとき、掛け算よりも2進数を好んで使います)

日付について、30日までの日か31日までの日かだったり、20221028が何曜かなんて自分で判断してられないので、LocalDateやZonedDateTimeを使いましょう。(CalendarやDateなどもありますが、Javaの長い歴史で生まれた、今使うべき型ではないので情報に気をつけてください)

20221028を年月日にそれぞれ分解したりする部分はご自身で把握できていますでしょうか?
その後はやることは簡単です、最初に各値を利用可能な形に変換し、「必要に応じて」の例外ケースを確かめたあと、whileの中で薬が無くなるまで一個づつ減らして無くなるときを確かめるだけです。
(受け渡された情報の形からして個人アプリですよね?一億錠処方されたり、一億人の服薬スケジュールを考えるのでなければループで十分です)
特に日付型の存在を知らないから文字列で期待しているのだとおもいますが、文字列が良ければ最後に元の形に戻す処理もつけてください。

要所は省きますが、メインロジックはこんな感じです(携帯からですので誤字や型違いがあったらすみません)

String main(){
    if(timing == 6){
       return "頓服薬です";
    }

    int[] sholdTakeWeeks = {1, 2, 3, 4, 5}; // 例は平日1-5です
    boolean shoudTakeMorning = ArrayUtils.contains({1, 4, 5}, timing); // 朝か朝夜か朝昼夜
    boolean shoudTakeNoon = // 
    boolean shoudTakeNight = // 

    LocalDate ld = LocalDate.now(); // 正しくは開始日をパースして渡してください
    int currentCycle = 1; // 現在時間、1朝2昼3夜、朝開始
    int currentWeek = ld.getDayOfWeek().get(ChronoField.DAY_OF_WEEK); // 現在曜日
    int medicineNum = 10; // 所持数、本来は入力から

    while(medicineNum > 0){
        boolean shouldTakeWeek = ArrayUtils.contains(sholdTakeWeeks, currentWeek);
        boolean shouldTakeCycle = (currentCycle == 1 && shoudTakeMorning) || (currentCycle == 2 && shoudTakeNoon) || (currentCycle == 3 && shoudTakeNight);
        if( shouldTakeWeek  && shouldTakeCycle ){
            medicineNum--;// 飲むタイミングだったら薬を減らす
        }(

        // 時間を進める
        if(++currentCycle > 3){ // 時間を進めて夜より先なら
            currentCycle = 1; // 朝に戻す
            ld = ld.plusDays(1); // 日付も進める
            currentWeek = ld.getDayOfWeek().get(ChronoField.DAY_OF_WEEK);
        }
    }
    return "薬切れ"; // currentCycleとldに答えが入ってます
}

頑張ってください。

2Like

Comments

  1. なお、雑なループなので、アプリのコードでは必ず朝昼夜・月火水木金土日のどれかに服用することを確かめて無限ループにならないことを確かめてください
  2. 型保管使えない環境で書いてたのでさぼって配列型を使ってますが、ArrayやSetを使うほうが正しいと思ってます。もし把握しておられましたら適当に読み替えてください。
  3. @Ryu_1936

    Questioner

    丁寧な回答ありがとうございました。
    すごく勉強になります。
    もし、このコードの実装中に分からないことが出来たらまた質問してもよろしいでしょうか?
  4. Androidの実装ではわからない箇所もあるかもしれませんが、単純な設計やJavaのことなら回答できると思いますよ。
    もちろん必要があればどうぞ私だけでなく新たに質問を作成して聞いてください。

 最近、ある国会議員が(批判文に対して)いいねを押して、10万フォロワーの影響力がある国会議員として、誹謗中傷と見なされ、損害賠償の判決が下されましたが、対話無しに一方的に判定を下す社会は無知な人間に優しい社会なのでしょうか?子供から老人まで、楽しく技術の話ができる社会、コミュニティーでありたいものです。

 さて、アルゴリズムとは言えない思いつきですみません。
「服用するタイミング」1(朝)は度外視させてください。

薬は1種類として、A薬:朝昼夜 = [1,1,1,0]、1日の服用数のプロパティを作成します。0は必要に応じて、 朝夜:4、朝昼夜:5 は除外

A処方:平日 = [0,1,1,1,1,1,0] 服用サイクルのプロパティを作成します。0は日土
 注意: 複数の薬の処方は想定してません。

set obj = New 患者(Aさん)
obj.set(A薬,A処方)
  ※ 複数の薬の処方? できる?
obj.日数=null 
obj.個数=40  日数か個数どちらか要
日数=obj.count()
最終日=obj.last(開始日) 

さて、ロジックですが、for文でブン回して引き算しましょう! 
 残念ロジック! by暇人x  in 居酒屋

0Like

Your answer might help someone💌