【COBOL 書き1-12-10】 中央値算出最終コードを作る!〜超新星爆発コード

🧩今日の学び
・奇数版と偶数版を統合するには、まず件数を2で割った余りから偶数・奇数を判定する考え方が使える。
DIVIDEREMAINDERを使えば商だけでなく余りも取得でき、偶奇判定の材料として利用できる。
・動く処理をそのまま2本並べるのではなく、共通化できる部分を探して分岐そのものを減らすこともプログラム設計では重要になる。

なるお)おはーす。

係長)お前ほんとにギリギリに来るやつだな⋯

な)時間には厳格なんで!

係)出勤時間だけ厳格なやつがいるかよ!

な)鳥貴族良かったすねー。係長のお金だと思うと数倍美味かったっす!あざんした!

係)人の金だと思ってたんまり食いやがって⋯

まぁいい、早速いくぞ。

な)え、まだやるんすか!?

係)当たり前だろ!

あんな中途半端なところで終われるか!いいだけ食ったんだ文句言わずにやれ!

な)なんてこと!

奇数版と偶数版を一つにまとめる

係)前回までで、カウントが偶数の時と奇数の時での処理の違いをそれぞれやってきた。

それを統合して、自動で割り振って、処理をする流れにしろ。

な)えー!

自動化自動化って、世の中なんでもかんでも自動化しようとするから、おかしくなってるんすよ!

自動運転、自動食事、自動睡眠、エトセトラ。

自動化なんてナンセンス!手動が一番。手書きが一番。明治維新が悪いんですよ!鎖国ですよ!ついにペリーを打ち負かすときが来たんですよ!

係)だったら、お前の集計も全部手でやれよ。

な)ぎゃふん

係)では、流れ考えたら報告しろ。以上だ。

な)え…、「以上だ」じゃないっての!それ以下にどれだけのものが埋まっていると思ってんの!氷山で見えてるのは氷山の一角だから!文字通りの一角獣だから!ユニコーンだから!

そういや、ユニコーンの鳴き声ってどんなんだろ?

バヒュルルヒン!みたいな?

さておき

まとめんのね。あれを。

うっとりをまとめたらゔっとり(ヴィクトリーうっとりの略)になっちゃうじゃないよねぇ。

大変なことになっちゃうっての。

まずはこれまで作った2つのコードを見比べる

まんず、奇数版うっとり、と

📝 COBOL 奇数版完成
  1IDENTIFICATION DIVISION.
  2PROGRAM-ID. NARUO.
  3
  4ENVIRONMENT DIVISION.
  5INPUT-OUTPUT SECTION.
  6FILE-CONTROL.
  7    SELECT NARUO-FILE
  8        ASSIGN TO "naruo2.txt" ORGANIZATION IS LINE SEQUENTIAL.
  9
 10
 11DATA DIVISION.
 12FILE SECTION.
 13
 14FD NARUO-FILE.
 1501 NARUO-RECORD.
 16    05 SALE-DATE    PIC X(10).
 17    05 ITEM-NAME    PIC X(20).
 18    05 AMOUNT       PIC 9(5).
 19
 20WORKING-STORAGE SECTION.
 2101 EOF-FLAG  PIC X VALUE "N".
 2201 EOF-FLAG2 PIC 9(1) VALUE 0.
 2301 TOTAL-AMOUNT PIC 9(7) VALUE 0.
 24
 2501 COUNT-LOOPING PIC 9(2) VALUE 0.
 2601 COUNT-LOOPING2 PIC 9(2)V9 VALUE 0.
 27
 28
 29PROCEDURE DIVISION.
 30OPEN INPUT NARUO-FILE.
 31
 32PERFORM UNTIL EOF-FLAG = "Y"
 33    READ NARUO-FILE
 34        AT END
 35            MOVE "Y" TO EOF-FLAG
 36        NOT AT END
 37            ADD 1 TO COUNT-LOOPING
 38    END-READ
 39END-PERFORM.
 40
 41CLOSE NARUO-FILE.
 42OPEN INPUT NARUO-FILE.
 43
 44ADD 1 TO COUNT-LOOPING.
 45DIVIDE 2 INTO COUNT-LOOPING.
 46
 47PERFORM UNTIL COUNT-LOOPING = COUNT-LOOPING2
 48    READ NARUO-FILE
 49        AT END
 50            DISPLAY "SEKAI NO OWARI"
 51        NOT AT END
 52            ADD 1 TO COUNT-LOOPING2
 53    END-READ
 54END-PERFORM.
 55
 56DISPLAY "MEDIAN IS" AMOUNT.
 57
 58CLOSE NARUO-FILE.
 59STOP RUN.

で、これが偶数版うっとり

📝 COBOL 偶数版完成
  1       IDENTIFICATION DIVISION.
  2       PROGRAM-ID. NARUO.
  3
  4       ENVIRONMENT DIVISION.
  5       INPUT-OUTPUT SECTION.
  6       FILE-CONTROL.
  7           SELECT INPUT-FILE
  8               ASSIGN TO "naruo2.txt"
  9               ORGANIZATION IS LINE SEQUENTIAL.
 10           SELECT SORT-FILE
 11               ASSIGN TO "sortwork.tmp".
 12           SELECT OUTPUT-FILE
 13               ASSIGN TO "naruo2_sorted.txt"
 14               ORGANIZATION IS LINE SEQUENTIAL.
 15
 16       DATA DIVISION.
 17       FILE SECTION.
 18       FD INPUT-FILE.
 19       01 INPUT-RECORD.
 20           05 INPUT-SALE-DATE PIC X(10).
 21           05 INPUT-ITEM-NAME PIC X(20).
 22           05 INPUT-AMOUNT    PIC 9(5).
 23
 24       SD SORT-FILE.
 25       01 SORT-RECORD.
 26           05 SORT-SALE-DATE PIC X(10).
 27           05 SORT-ITEM-NAME PIC X(20).
 28           05 SORT-AMOUNT    PIC 9(5).
 29
 30       FD OUTPUT-FILE.
 31       01 OUTPUT-RECORD.
 32           05 OUTPUT-SALE-DATE PIC X(10).
 33           05 OUTPUT-ITEM-NAME PIC X(20).
 34           05 OUTPUT-AMOUNT    PIC 9(5).
 35
 36       WORKING-STORAGE SECTION.
 37       01 EOF-FLAG      PIC X VALUE "N".
 38       01 COUNT-LOOPING PIC 9(2) VALUE 0.
 39       01 READ-COUNT    PIC 9(2) VALUE 0.
 40       01 LOW-POS       PIC 9(2) VALUE 0.
 41       01 HIGH-POS      PIC 9(2) VALUE 0.
 42       01 LOW-VAL       PIC 9(5) VALUE 0.
 43       01 HIGH-VAL      PIC 9(5) VALUE 0.
 44       01 MEDIAN-VAL    PIC 9(5)V9 VALUE 0.
 45
 46       PROCEDURE DIVISION.
 47           SORT SORT-FILE
 48               ON ASCENDING KEY SORT-AMOUNT
 49               USING INPUT-FILE
 50               GIVING OUTPUT-FILE.
 51
 52           OPEN INPUT OUTPUT-FILE.
 53           PERFORM UNTIL EOF-FLAG = "Y"
 54               READ OUTPUT-FILE
 55                   AT END
 56                       MOVE "Y" TO EOF-FLAG
 57                   NOT AT END
 58                       IF OUTPUT-AMOUNT IS NUMERIC
 59                           AND OUTPUT-AMOUNT > 0
 60                           ADD 1 TO COUNT-LOOPING
 61                       END-IF
 62               END-READ
 63           END-PERFORM.
 64           CLOSE OUTPUT-FILE.
 65
 66           COMPUTE LOW-POS  = COUNT-LOOPING / 2.
 67           COMPUTE HIGH-POS = LOW-POS + 1.
 68
 69           OPEN INPUT OUTPUT-FILE.
 70           MOVE "N" TO EOF-FLAG.
 71           PERFORM UNTIL EOF-FLAG = "Y"
 72               READ OUTPUT-FILE
 73                   AT END
 74                       MOVE "Y" TO EOF-FLAG
 75                   NOT AT END
 76                       IF OUTPUT-AMOUNT IS NUMERIC
 77                           AND OUTPUT-AMOUNT > 0
 78                           ADD 1 TO READ-COUNT
 79                           IF READ-COUNT = LOW-POS
 80                               MOVE OUTPUT-AMOUNT TO LOW-VAL
 81                           END-IF
 82                           IF READ-COUNT = HIGH-POS
 83                               MOVE OUTPUT-AMOUNT TO HIGH-VAL
 84                           END-IF
 85                       END-IF
 86               END-READ
 87           END-PERFORM.
 88           CLOSE OUTPUT-FILE.
 89
 90           COMPUTE MEDIAN-VAL = (LOW-VAL + HIGH-VAL) / 2.
 91           DISPLAY "COUNT=" COUNT-LOOPING
 92                   " LOW-POS=" LOW-POS " HIGH-POS=" HIGH-POS.
 93           DISPLAY "LOW-VAL=" LOW-VAL " HIGH-VAL=" HIGH-VAL.
 94           DISPLAY "MEDIAN IS " MEDIAN-VAL.
 95           STOP RUN.

という並びになりますな。

な)んで、偶数版の方でDATA DIVISIONをカバーできているはずなので、それを流用しますか。

そこまでは良しとして、次のPROCEDURE DIVISIONよねぇ。

はっ!PROCEDUREとか普通に言っちゃってる!?もうプロだわこれ!

と、自画自賛しておいてと、ここからが問題だと。

まず件数が偶数か奇数かを判定する

んーと、まず偶数か奇数か判定するわけよね。

なので、ルーピングでカウント回して偶数か奇数かを判定。

あとは簡単圧縮鍋調理ってなもんで、偶数だったら偶数の処理、奇数だったら奇数の処理で、骨まで食えるってなわけで、カルシウムは満タンだと。

奇数と偶数の判定…うーん、でも偶数のときにやったやつがあったから、それを考えると、

割り切れたら偶数

割り切れなかったら奇数

わかった!

2で割って余りが出なかったら偶数(余り= 0

2で割って余りが出たら奇数(余り>0

その答えによって、偶数処理と奇数処理に分岐して流れに身を任せる!

係長! 美空ひばりっす!

係)あん?

な)美空ひばり記念館ですよ!

係)どこからどうなったら美空ひばりになるんだよ…

な)オレもびっくりっす!ビックにびっくりっす!

係)うるさいわ!

な)いやー最高の答えが出せて、疲れましたねー

係)そう簡単に終わると思ったか?

な)え…

係)今日も残業覚悟しとけ。

な)まだお昼前なんですけどー!

係)まずIDENTIFICATION DIVISIONは後から考えるぞ。

必要なことを考えていき、結果として必要なことを追加していけばいい。

だからDATA DIVISIONも後からにするぞ。

な)あーなんか前にも言ってたような…

係)で、お前が言ってたことは、そこそこ正しいぞ。

な)おー!やはり!

REMAINDERで割り算の余りを求める

係)それで、余りを出すとかいうのはどうやるんだ?

な)余りわからないですね

係)ふざけようとすんな!

な)いやん

係)2で割るとか言ってたが、割り算はどうやるんだった?

な)えーとDIVIDEなんとかギブミーチョコレート!進駐軍憎し!タケヤリトツゲキ!

係)戦中戦後かよ!

DIVIDE (割られる数) BY (割る数) GIVING (商) REMAINDER (余り)

だっただろ!

な)もうアメリカかぶれなんすね…

係)覚えてなかったな?

な)(ギクっ!)

そ、そんなもん天文学的な速さで覚えてますって!超新星爆発が地球から確認できるぐらいの速さで記憶してますよ!

係)どんだけ遅いんだよ!

な)光速だから速いんすよ!

偶数と奇数を分岐させずにもっと簡略化できる?

係)それでこのあとの処理で、IF分岐を考えると言ってたが、偶数と奇数の処理の両方を乗せる気だったのか?

な)へ?そうですけど?

係)そうか

な)うっとり設計でしょ?有用なものは後生の学びのために残さないといけないし

係)わかった。

な)やはり!

係)偶数と奇数に分岐させずに簡略化しろ。

な)へ!?

係)次の課題だ。さぁやれ。

な)んが!

その「やれ!」までの間がないんすよ…

行間を読むという文化が日本にはあるんすよ?

だから、超新星爆発を見ながら待っててくださいよー

係)何百年待たせる気だよ!

な)じゃ、コース料理を食べ終わるぐらいで、もういいですよ!

係長が代金払ってくださいよ!

係)コース料理をたかるなよ!

そもそも速い遅いの話をしてないだろ…

(また続く)

係長のワンポイント

偶数・奇数の判定は「処理を二つ作るため」のものじゃない。
本当は、両者の違いを見つけて処理を共通化するための判断材料だ。
よくある誤解は、REMAINDERで判定したあとに偶数用・奇数用のコードを丸ごと分けることだ。
それでも動くが、同じ処理が増えればコードは長くなり、修正する場所も増えていく。
だから違う部分だけを条件として残し、共通する流れは一つにまとめられないかを考える。
COBOLは分岐を増やす言語ではなく、違いを見極めて処理を整理する言語だ。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

CAPTCHA