Nickolas's blog

By Nickolas, 7 years ago, translation, In English,

Here goes a review of the problems. I tried to set them so that each of them shows a certain aspect of the language — a commonly used verb or a specific feature. Once it was recognized and found, the solution should become evident.

153A - A + B

Let me note right away that the sample code provided in the blog post does work both in Custom test and in ideone (as well as locally), as long as the numbers are written one per line and (attention!) each of them, including the last one, is followed by the end-of-line character. The last '\n' is not shown in the tests, but it is there, and COBOL minds it. All test cases at Codeforces are generated with this in mind, so there should be no problems like this when the code is submitted.

The most evident COBOL feature is storing numbers in decimal notation, with width set by the programmer. In this case we focused on the fact that by default the number is printed in a fixed-width way, padded with leading zeros if needed. These zeros where what you needed to get rid of. The reference solution transformed the sum of numbers into a string with leading zeros and removed the zeros. To do this, the zeros had to be counted — most likely using the verb INSPECT ... TALLYING which calculates the characters of the string which correspond to the given condition and adds their number to the given variable. The sample A+B code needed only a couple more lines:

       01 ZEROSCOUNT  PIC 99.
       01 SUMSTRING   PIC X(10).

       MOVE SUM TO SUMSTRING
       MOVE 1 TO ZEROSCOUNT
       INSPECT SUMSTRING TALLYING ZEROSCOUNT FOR LEADING "0"
       DISPLAY SUMSTRING(ZEROSCOUNT:11 - ZEROSCOUNT)

In COBOL string characters and array elements are indexed starting with 1, so the initial value of ZEROSCOUNT must be set to 1.

This problem could be done much easier: declare a variable C of type z(10)9, move the sum into it and just DISPLAY it — this format pads the number to the required width with spaces instead of zeros, and Codeforces checker ignored spaces.

153B - Binary notation

The next problem combines two important elements of the language — the verb PERFORM UNTIL, used for loops organization, and string concatenation verb STRING. The condition of loop end is simply N EQUAL 0. STRING arguments are complemented by DELIMITED BY clause which defines the part of the string used in concatenation. Two main modes are DELIMITED BY SIZE (all variable regardless of how much it is filled) and DELIMITED BY SPACE (part of the variable until the first space or the end of the filled part). The current binary digit can be stored in a variable of size 1 and use it as DELIMITED BY SIZE, while the current binary notation should better be DELIMITED BY SPACE (though this would be more important if the digit was appended to the end of the notation, not the other way round).

The main loop of the program is (yes, you could write the code not in uppercase :-)):

         perform until n equal 0
           divide n by 2 giving n remainder digit
           move digit to binary_digit
           string binary_digit  delimited by size
                  binary_number delimited by space
                  into str
           move str to binary_number
         end-perform.

153C - Caesar Cipher

This problem allowed two main approaches. The first one is more typical for programming contests — iterate through the string and process each character separately. The reference solution used the second one, based on yet another COBOL verb INSPECT ... CONVERTING. It allows to iterate through the string replacing the characters which belong to the first argument with corresponding characters from the second one. Encoding with a fixed key would become a one-liner, for example, for ROT-13

inspect cipher
    converting 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
            to 'NOPQRSTUVWXYZABCDEFGHIJKLM'

but this would be boring, wouldn't it? So you had to construct the second argument beforehand — either char-by-char or by cutting the alphabet string in one place and swapping the parts.

153D - Date Change

Of course this problem can be solved by hand — split the date into day, month and year and add/subtract one day per iteration for the required number of times. But COBOL has its special functions for this very case — INTEGER-OF-DATE (convert date from YYYYMMDD format to the number of days elapsed since December 31st, 1600) and its inverse DATE-OF-INTEGER. All you have to do is to convert the input data to YYYYMMDD format, convert it to integer, add shift to it and repeat the process in the opposite direction.

153E - Euclidean Distance

The last problem of the round required working with arrays, called tables in COBOL. The hardest thing about them is figuring out the declaration format. My data structure looked like this:

         01 n pic 99.
         01 points.
            02 occurs 2 to 50 times depending on n.
               03 x pic S999.
               03 y pic S999.

S character in integer declaration means that is can take negative values — otherwise the minus sign is just dropped. DEPENDING ON N means that the array is automatically resized to contain exactly N elements. Referencing array elements is very simple — x(i) и y(i).

The double loop can be organized in several ways, the easiest of them is using an inner loop:

         perform varying i from 1 by 1 until i > n
           perform varying j from i by 1 until j > n
             compute dx = x(i) - x(j)
             compute dy = y(i) - y(j)
             compute d = dx * dx + dy * dy
             if d > maxd
               move d to maxd
           end-perform
         end-perform.

Finally, the last language element used is the call of the library function SQRT:

         display function sqrt(maxd)
 
 
 
 
  • Vote: I like it
  • +34
  • Vote: I do not like it

»
7 years ago, # |
  Vote: I like it +12 Vote: I do not like it

Thanks Nickolas, it was very fun