#はじめに
COBOLを少しかじってみたので
AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~(Qiita)
をCOBOLで解きました。
COBOLがまだよくわかってない汚いコードをとりあえず置いておきます。
初めての記事で書き方が変ですがよろしくお願いします。
#謝罪
最初に書かないといけないことがあります。
タイトルに10問と書いていますが、9問しか解けていません。後述します。すいません。
#0問目 practice contest A - はじめてのあっとこーだー(Welcome to AtCoder)
文字列を出力するときに文字数に気をつけないといけないことに気づかずにいっぱいWA出しました。一番苦しみました。
入力は1行まるまるみたいなので複数の変数に分割するのに汚い書き方してます。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(10).
01 A PIC 9999.
01 B PIC 9999.
01 C PIC X(101).
01 REN PIC 9999.
01 RE1 PIC 9.
01 RE2 PIC Z9.
01 RE3 PIC ZZ9.
01 RE4 PIC ZZZ9.
01 temp1 PIC 9999.
01 temp2 PIC 9999.
01 N PIC 9999.
PROCEDURE DIVISION.
MAIN.
ACCEPT REN.
ACCEPT INP.
PERFORM VARYING temp1 FROM 1 BY 1 UNTIL INP(temp1:1)=SPACE
END-PERFORM.
SUBTRACT 1 FROM temp1.
MOVE INP(1:temp1) TO A.
ADD 2 TO temp1.
PERFORM VARYING temp2 FROM temp1 BY 1 UNTIL INP(temp2:1)=SPACE
END-PERFORM.
COMPUTE N=temp2 - temp1.
MOVE INP(temp1:N) TO B.
ACCEPT C.
PERFORM VARYING temp2 FROM 1 BY 1 UNTIL C(temp2:1)=SPACE
END-PERFORM.
SUBTRACT 1 FROM temp2.
COMPUTE REN = REN + A.
COMPUTE REN = REN + B.
IF REN < 10 THEN
MOVE REN TO RE1
DISPLAY RE1 " " C(1:temp2)
ELSE IF REN < 100 THEN
MOVE REN TO RE2
DISPLAY RE2 " " C(1:temp2)
ELSE IF REN < 1000 THEN
MOVE REN TO RE3
DISPLAY RE3 " " C(1:temp2)
ELSE
MOVE REN TO RE4
DISPLAY RE4 " " C(1:temp2)
END-IF
STOP RUN.
#1問目 ABC086A - Product
COBOLで剰余を出す方法がわからなかったので商から求めました。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(100).
01 A PIC 99999.
01 B PIC 99999.
01 temp1 PIC 9999.
01 temp2 PIC 9999.
01 N PIC 9999.
PROCEDURE DIVISION.
MAIN.
ACCEPT INP.
PERFORM VARYING temp1 FROM 1 BY 1 UNTIL INP(temp1:1)=SPACE
END-PERFORM.
SUBTRACT 1 FROM temp1.
MOVE INP(1:temp1) TO A.
ADD 2 TO temp1.
PERFORM VARYING temp2 FROM temp1 BY 1 UNTIL INP(temp2:1)=SPACE
END-PERFORM.
COMPUTE N=temp2 - temp1.
MOVE INP(temp1:N) TO B.
COMPUTE A = A * B.
COMPUTE B = A / 2.
COMPUTE A = A - B * 2.
IF A = 0 THEN
DISPLAY "Even"
ELSE
DISPLAY "Odd"
END-IF.
STOP RUN.
#2問目 ABC081A - Placing Marbles
3文字のなのでPERFORM
使わなくてもいいのですが、練習代わりに使いました。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(100).
01 A PIC 99999.
01 B PIC 99999.
01 temp1 PIC 9999.
01 temp2 PIC 9999.
01 N PIC 9999.
01 RE PIC 9.
PROCEDURE DIVISION.
MAIN.
MOVE 0 TO RE.
ACCEPT INP.
PERFORM VARYING N FROM 1 BY 1 UNTIL N = 4
MOVE INP(N:1) TO A
IF A = 1 THEN
ADD 1 TO RE
END-IF
END-PERFORM.
DISPLAY RE.
STOP RUN.
#3問目 ABC081B - Shift only
配列の作り方を学びました。
1行の入力から変数に切り出すのを綺麗にかけてると個人的には思います。
2で割れるかの判定が変です。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(2000).
01 A-REC.
02 A-DATA OCCURS 200 .
03 A PIC 999999999 .
01 temp1 PIC 9999.
01 temp2 PIC 9999.
01 temp3 PIC 99999.
01 N PIC 999.
01 REN PIC ZZZZ9.
01 RE PIC 99999.
01 MOD PIC 9.
01 R PIC 999999999.
01 S PIC 999.
01 NOW PIC 9999.
PROCEDURE DIVISION.
MAIN.
MOVE 10000 TO RE.
ACCEPT N.
MOVE 1 TO NOW.
ADD 1 TO N.
ACCEPT INP.
PERFORM VARYING S FROM 1 BY 1 UNTIL S = N
PERFORM VARYING temp1 FROM NOW BY 1
UNTIL INP(temp1:1)=SPACE
END-PERFORM
COMPUTE temp2 = temp1 - NOW
MOVE INP(NOW:temp2) TO A(S)
COMPUTE NOW = temp1 + 1
END-PERFORM.
PERFORM VARYING S FROM 1 BY 1 UNTIL S = N
COMPUTE R = A(S) / 2
COMPUTE MOD = A(S) - R*2
PERFORM VARYING temp3 FROM 0 BY 1 UNTIL MOD = 1
COMPUTE R = A(S) / 2
COMPUTE MOD = A(S) - R*2
COMPUTE A(S) = R
END-PERFORM
IF temp3 > 0 THEN
SUBTRACT 1 FROM temp3
END-IF
IF temp3 < RE THEN
MOVE temp3 TO RE
END-IF
END-PERFORM.
MOVE RE TO REN.
DISPLAY REN.
STOP RUN.
#4問目 ABC087B - Coins
PERFORM
を3周回すコードです。
COMPUTE temp1 = S * 500 + T * 100 + U * 50
と書いたらInvalid Expression
とエラーが出ました。厳しい…
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 A PIC 99.
01 B PIC 99.
01 C PIC 99.
01 X PIC 99999.
01 RE PIC 99999.
01 REN PIC ZZZZ9.
01 temp1 PIC 99999.
01 S PIC 99.
01 T PIC 99.
01 U PIC 99.
PROCEDURE DIVISION.
MAIN.
ACCEPT A.
ACCEPT B.
ACCEPT C.
ACCEPT X.
ADD 1 TO A.
ADD 1 TO B.
ADD 1 TO C.
MOVE 0 TO RE.
PERFORM VARYING S FROM 0 BY 1 UNTIL S = A
PERFORM VARYING T FROM 0 BY 1 UNTIL T = B
PERFORM VARYING U FROM 0 BY 1 UNTIL U = C
COMPUTE temp1 = S * 500
COMPUTE temp1 = temp1 + T * 100
COMPUTE temp1 = temp1 + U * 50
IF temp1 = X THEN
ADD 1 TO RE
END-IF
END-PERFORM
END-PERFORM
END-PERFORM.
MOVE RE TO REN.
DISPLAY REN.
STOP RUN.
#5問目 ABC083B - Some Sums
各桁の和を求めるのにMOD SECTION.
を使ったら便利でした。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(100).
01 A PIC 99999999.
01 B PIC 99999999.
01 C PIC 9999999999.
01 REN PIC 9999999999.
01 RE PIC ZZZZZZZZZZ9.
01 temp1 PIC 9999999.
01 temp2 PIC 9999999.
01 temp3 PIC 9999999.
01 N PIC 9999999.
PROCEDURE DIVISION.
MAIN.
ACCEPT INP.
PERFORM VARYING temp1 FROM 1 BY 1 UNTIL INP(temp1:1)=SPACE
END-PERFORM.
SUBTRACT 1 FROM temp1.
MOVE INP(1:temp1) TO A.
ADD 2 TO temp1.
PERFORM VARYING temp2 FROM temp1 BY 1 UNTIL INP(temp2:1)=SPACE
END-PERFORM.
COMPUTE N=temp2 - temp1.
MOVE INP(temp1:N) TO B.
ADD 1 TO temp2.
PERFORM VARYING temp1 FROM temp2 BY 1 UNTIL INP(temp1:1)=SPACE
END-PERFORM.
COMPUTE N=temp1 - temp2.
MOVE INP(temp2:N) TO C.
ADD 1 TO A.
MOVE 0 TO REN.
PERFORM VARYING N FROM 1 BY 1 UNTIL N = A
MOVE 0 TO temp1
MOVE N TO temp2
PERFORM MOD
IF temp1 >= B AND temp1 <= C THEN
ADD N TO REN
END-IF
END-PERFORM.
MOVE REN TO RE.
DISPLAY RE.
STOP RUN.
MOD SECTION.
PERFORM 5 TIMES
COMPUTE temp3 = temp2 / 10
COMPUTE temp1 = temp1 + temp2 - temp3 * 10
COMPUTE temp2 = temp3
END-PERFORM.
EXIT.
#6問目 ABC088B - Card Game for Two
速いソートを書く自信がなかったので選択ソートです。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(11000).
01 A-REC.
02 A-DATA OCCURS 100.
03 A PIC 999.
01 B PIC 999.
01 C PIC 999.
01 D PIC 999.
01 ALICE PIC 999999.
01 BOB PIC 999999.
01 REN PIC 9999999999.
01 RE PIC ZZZZZZZZZZ9.
01 temp1 PIC 9999999.
01 temp2 PIC 9999999.
01 temp3 PIC 9999999.
01 NOW PIC 9999999.
01 N PIC 999.
01 MAX PIC 999.
PROCEDURE DIVISION.
MAIN.
ACCEPT B.
ACCEPT INP.
ADD 1 TO B.
MOVE 1 TO NOW.
PERFORM VARYING C FROM 1 BY 1 UNTIL C = B
PERFORM VARYING temp1 FROM NOW BY 1
UNTIL INP(temp1:1) = SPACE
END-PERFORM
COMPUTE N = temp1 - NOW
MOVE INP(NOW:N) TO A(C)
COMPUTE NOW = NOW + N + 1
END-PERFORM.
PERFORM VARYING C FROM 1 BY 1 UNTIL C = B
MOVE C TO MAX
PERFORM VARYING D FROM C BY 1 UNTIL D = B
IF A(D) > A(MAX) THEN
MOVE D TO MAX
END-IF
END-PERFORM
COMPUTE temp1 = A(C)
COMPUTE A(C) = A(MAX)
COMPUTE A(MAX) = temp1
END-PERFORM.
MOVE 0 TO ALICE.
MOVE 0 TO BOB.
PERFORM VARYING C FROM 1 BY 1 UNTIL C >= B
COMPUTE ALICE = ALICE + A(C)
ADD 1 TO C
IF C < B THEN
COMPUTE BOB = BOB + A(C)
END-IF
END-PERFORM.
COMPUTE REN = ALICE - BOB.
MOVE REN TO RE.
DISPLAY RE.
STOP RUN.
#7問目 ABC085B - Kagami Mochi
制約として1<=A(S)<=100
があったので値をインデックスにした配列に入れました。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(11000).
01 A-REC.
02 A-DATA OCCURS 100.
03 A PIC 999.
01 B PIC 999.
01 C PIC 999.
01 D PIC 999.
01 ALICE PIC 999999.
01 BOB PIC 999999.
01 REN PIC 9999999999.
01 RE PIC ZZZZZZZZZZ9.
01 temp1 PIC 9999999.
01 temp2 PIC 9999999.
01 temp3 PIC 9999999.
01 NOW PIC 9999999.
01 N PIC 999.
01 MAX PIC 999.
PROCEDURE DIVISION.
MAIN.
PERFORM VARYING N FROM 1 BY 1 UNTIL N = 101
MOVE 0 TO A(N)
END-PERFORM.
ACCEPT B.
ADD 1 TO B.
PERFORM VARYING N FROM 1 BY 1 UNTIL N = B
ACCEPT C
ADD 1 TO A(C)
END-PERFORM.
MOVE 0 TO D.
PERFORM VARYING N FROM 1 BY 1 UNTIL N = 101
IF A(N) > 000 THEN
ADD 1 TO D
END-IF
END-PERFORM.
MOVE D TO RE.
DISPLAY RE.
STOP RUN.
#8問目 ABC085C - Otoshidama
PERFORM
2周回せば大丈夫なやつですね。多めに桁数とった変数からゼロサプレスの変数に転記し忘れるとWA。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(20).
01 N PIC 9999999.
01 Y PIC 99999999.
01 temp1 PIC 999999999.
01 S PIC 99999999.
01 T PIC 99999999.
01 temp2 PIC 99999999.
01 temp3 PIC 99999999.
01 RE1 PIC ZZZZZZZ9.
01 RE2 PIC ZZZZZZZ9.
01 RE3 PIC ZZZZZZZ9.
PROCEDURE DIVISION.
MAIN.
ACCEPT INP.
PERFORM VARYING S FROM 1 BY 1 UNTIL INP(S:1)=SPACE
END-PERFORM.
SUBTRACT 1 FROM S.
MOVE INP(1:S) TO N.
ADD 2 TO S.
PERFORM VARYING temp1 FROM S BY 1 UNTIL INP(temp1:1)=SPACE
END-PERFORM.
COMPUTE temp1 = temp1 - S.
MOVE INP(S:temp1) TO Y.
COMPUTE Y = Y / 1000 .
PERFORM VARYING S FROM 0 BY 1 UNTIL S > N
COMPUTE temp1 = N - S
PERFORM VARYING T FROM 0 BY 1 UNTIL T > temp1
COMPUTE temp2 = temp1 - T
COMPUTE temp3 = S * 10 + T * 5
COMPUTE temp3 = temp3 + temp2
IF temp3 = Y THEN
MOVE S TO RE1
MOVE T TO RE2
MOVE temp2 TO RE3
DISPLAY RE1 " " RE2 " " RE3
STOP RUN
END-IF
END-PERFORM
END-PERFORM.
DISPLAY "-1 -1 -1".
STOP RUN.
#9問目 ABC049C - 白昼夢 / Daydream
これが謝罪のところに書いた解けなかった問題です。
というのも調べ切れてないので断言はできないのですが、COBOLに与えられる入力の最大文字数が8191文字みたいで、10000文字くらいを超えるテストケースに通りませんでした。
一応コードだけ上げます。何かしたら通せるのかな…?
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(110000).
01 INV PIC X(110000).
01 NOW PIC 999999.
01 temp PIC 999999.
PROCEDURE DIVISION.
MAIN.
ACCEPT INP.
PERFORM VARYING NOW FROM 1 BY 1 UNTIL INP(NOW:1) = SPACE
END-PERFORM.
ADD -1 TO NOW.
MOVE NOW TO temp.
PERFORM VARYING NOW FROM temp BY -1 UNTIL NOW = 0
* DISPLAY NOW
IF INP(NOW:1) = 'm' THEN
IF NOW <= 4 THEN
DISPLAY "NO"
STOP RUN
END-IF
SUBTRACT 4 FROM NOW
IF INP(NOW:5) NOT = "dream" THEN
DISPLAY "NO"
STOP RUN
END-IF
ELSE IF INP(NOW:1) = 'e' THEN
IF NOW <= 4 THEN
DISPLAY "NO"
STOP RUN
END-IF
SUBTRACT 4 FROM NOW
IF INP(NOW:5) NOT = "erase" THEN
DISPLAY "NO"
STOP RUN
END-IF
ELSE IF INP(NOW:1) = 'r' THEN
IF NOW <= 1 THEN
DISPLAY "NO"
STOP RUN
END-IF
SUBTRACT 1 FROM NOW
IF INP(NOW:1) = 'e' THEN
IF NOW <= 1 THEN
DISPLAY "NO"
STOP RUN
END-IF
SUBTRACT 1 FROM NOW
IF INP(NOW:1) = 'm' THEN
IF NOW <= 4 THEN
DISPLAY "NO"
STOP RUN
END-IF
SUBTRACT 4 FROM NOW
IF INP(NOW:7) NOT = "dreamer" THEN
DISPLAY "NO"
STOP RUN
END-IF
ELSE IF INP(NOW:1) = 's'
IF NOW <= 3 THEN
DISPLAY "NO"
STOP RUN
END-IF
SUBTRACT 3 FROM NOW
IF INP(NOW:6) NOT = "eraser" THEN
DISPLAY "NO"
STOP RUN
END-IF
END-IF
ELSE
DISPLAY "NO"
STOP RUN
END-IF
ELSE
DISPLAY "NO"
STOP RUN
END-IF
END-PERFORM.
DISPLAY "YES"
STOP RUN.
#10問目 ABC086C - Traveling
偶奇を調べるのに変な書き方をしました。
IDENTIFICATION DIVISION.
PROGRAM-ID. test1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INP PIC X(100).
01 A PIC 99999999.
01 B PIC 99999999.
01 C PIC 99999999.
01 temp1 PIC 999999.
01 temp2 PIC 999999.
01 temp3 PIC 999999.
01 temp4 PIC 999999.
01 N PIC 999999.
01 S PIC 999999.
01 T PIC 999999.
01 NOW1 PIC 999999.
01 NOW2 PIC 999999.
01 NOW3 PIC 999999.
PROCEDURE DIVISION.
MAIN.
ACCEPT S.
PERFORM VARYING T FROM 1 BY 1 UNTIL T > S
ACCEPT INP
PERFORM VARYING temp1 FROM 1
BY 1 UNTIL INP(temp1:1)=SPACE
END-PERFORM
SUBTRACT 1 FROM temp1
MOVE INP(1:temp1) TO A
ADD 2 TO temp1
PERFORM VARYING temp2 FROM temp1
BY 1 UNTIL INP(temp2:1)=SPACE
END-PERFORM
COMPUTE N=temp2 - temp1
MOVE INP(temp1:N) TO B
ADD 1 TO temp2
PERFORM VARYING temp1 FROM temp2
BY 1 UNTIL INP(temp1:1)=SPACE
END-PERFORM
COMPUTE N=temp1 - temp2
MOVE INP(temp2:N) TO C
COMPUTE temp1 = A - NOW1
COMPUTE temp2 = B - NOW2
COMPUTE temp3 = C - NOW3
COMPUTE temp2 = temp2 + temp3
IF temp1 < temp2 THEN
DISPLAY "No"
STOP RUN
END-IF
COMPUTE temp2 = temp1 / 2
COMPUTE temp1 = temp1 - temp2 * 2
COMPUTE temp2 = B - NOW2
COMPUTE temp3 = temp2 / 2
COMPUTE temp2 = temp2 - temp3 * 2
COMPUTE temp3 = C - NOW3
COMPUTE temp4 = temp3 / 2
COMPUTE temp3 = temp3 - temp4 * 2
COMPUTE temp2 = temp2 + temp3
COMPUTE temp2 = temp2 - 2
IF temp2 = 2 THEN
MOVE 0 TO temp2
END-if
IF temp1 NOT = temp2 THEN
DISPLAY "No"
STOP RUN
END-IF
MOVE A TO NOW1
MOVE B TO NOW2
MOVE C TO NOW3
END-PERFORM.
DISPLAY "Yes"
STOP RUN.
#終わりに
COBOLだと変数の宣言や処理が難しくて苦労しました。
9問目を通せるようになりたいです。