Saturday, December 29, 2018

TCS Hiring Challenge 2018 - Mainframe - Part 1

Hello,

TCS has come up with hiring challenge for Mainframe professionals who are interested in pursuing an employment opportunity with them. I attempted the TCS Hiring Challenge on Dec 15th, 2018. It reminded me of those days I spent in Cognizant Academy, undergoing the training on Mainframes. To successfully pass the training, we had given tests which were very much similar to this challenge.

A day before the challenge, I received 2 emails from TCS. One with a sample question and the other one with instructions to join the challenge on Hackerrank. I used the latter email to join the challenge, the next day. Before starting the challenge, I was asked to agree to the consent that I'll not consult/copy code from any sources though I can refer manuals/use an IDE.



There were 2 questions which had to be finished within an hour. 1 for COBOL and the other one for SQL. I started the challenge with COBOL program.

The task was to write a COBOL program to display the even and odd numbers between two given numbers.

The program has to get 2 numbers from the user as input. Let's label the first input as LOWER and the 2nd input as UPPER. The code has to print the list of even and odd numbers between LOWER and UPPER.

For example, if LOWER and UPPER values are 01 and 19 respectively, the COBOL program should print the output in the following way:

Even numbers are:
02
04
06
08
10
12
14
16
18
Odd numbers are:
01
03
05
07
09
11
13
15
17
19

One constraint is that LOWER and UPPER should have values between 1 and 99.

I wrote the following code:
  • The code accept two inputs from user. The input values are assigned to WS-LOWER and WS-UPPER data-items respectively. 
  • I preferred using 88 Conditional names for WS-LOWER and WS-UPPER data-items to validate the constraint. This helps me avoid coding lengthy IF condtions.
  • Iterate between WS-LOWER and WS-UPPER using PERFORM loop.  
  • FUNCTION MOD, an intrinsic function in COBOL is being used to find whether a number is Even or odd. FUNCTION MOD outputs remainder which can be evaluated further. 
  • I've used tables with OCCURS DEPENDING ON to load the even and odd numbers and to display them as per the requirement. 

Output: The below output was displayed for WS-LOWER and WS-UPPER values as 01 and 28 respectively.

Even numbers are:
02
04
06
08
10
12
14
16
18
20
22
24
26
28
Odd numbers are:
01
03
05
07
09
11
13
15
17
19
21
23
25
27


I preferred coding in COBOL Coding Ground by Tutorialspoint rather than coding in the IDE supported by Hackerrank. You just need to write a working piece of code in COBOL Coding Ground. Once done with code, you can copy and paste it in Hackerranks's COBOL IDE and compile it.

You can try my code in COBOL Coding Ground here.

Things to note when you're compiling the COBOL program in Hackerrank:
Be cautious about AREA A and AREA B and code accordingly.
Use period and END-PERFORM or END-IF, for that matter, to end the scope of a loop or conditional statement. For example, it is better to end PERFORM loop by coding END-PERFORM.

I took 50 minutes to get the COBOL code running and passing the test cases. With 10 minutes left for the contest to end, I moved on with the next question. Unfortunately, the SQL query was a lengthy one requiring INNER JOIN on 4 tables. The contest ended while I was typing the query. Ufff!

I received an email within a week from TCS saying I was not selected. Hmm, That's alright!
Hope you found this article useful. Share your thoughts in the comments section.


Sunday, December 16, 2018

How to extract last byte of each record in VB and FB file using DFSORT


Hello,

In this post, I'll be showing how to extract last byte of each record, from a VB and FB file (in zOS).  I prefer using IBM's DFSORT utility to complete this task.

The last byte in a record might be anywhere within the record. 

Let's switch to apply our thinking process on real world example. Let's assume that we have a word document with following sentences.

My favourite number is 7
My favourite destination is Bhutan
I love Mainframes
I love IBM DFSORT
I love COBOL
You have this task of extracting the last letter of each sentence. As you see, the last letter is occurring in different positon for each sentence. With rich set of formatting tools in Word, we can align the sentences to look something like the below.



My favourite number is 7
My favourite destination is Bhutan
I love Mainframes
I love IBM DFSORT
I love COBOL


Right! Now that all the sentence are aligned to the right side, it's pretty much easy to read out the last letters in each sentence. You can even write a code to scan the word document and read last position of each sentence in the word document.

Let's switch back to Mainframes. Let's start with FB file. I'll be using JUSTIFY option in DFSORT. JUSTIFY option will align the data to make it look more presentable.

Access Left-justifying and right-justifying data to learn more about JUSTIFY.

I have created a FB file with LRECL of 80 and with some records as shown in the Picture 5.1  below.
Picture 5.1

I have prepared a JCL with some DFSORT statements as shown in Picture 5.2. I have preferred to format the records before sorting by using INREC FIELDS. Basically, with JUSTIFY, I am aligning each record to the right side, so that, the last byte, wherever it may be in the record, will be FORCED to occupy the 80th position, as the LRECL is 80.
Picture 5.2

Now, I can use OUTREC FIELDS to write the 80th byte to output. See Picture 5.3 for output.
Picture 5.3

We can do the same stuff with VB files, but we have to take care of two things. RDW and SHORT records.
  • RDW (Record Descriptor Word) is a 4 byte field describing the record. The first 2 bytes contain the length of the logical record. 
  • SHORT records: A variable-length input record may be too short to contain all specified control fields. A short record causes DFSORT to issue message ICE218A and terminate. 
Here's a VB file with LRECL 84 and with a record as shown in Picture 5.4 below. The record is 28 byte long (4bytes RDW + 24 bytes of record).
Picture 5.4

I have prepared a JCL as shown in Picture 5.5. 
Picture 5.5

I've used INREC IFTHEN to,
  1. align the record to the right side
  2. check if the logical record length (access first 2 bytes of RDW for the length) is less than the LRECL of the file and overlay the 84th byte with a blank. This will ensure short records are being padded with blanks and will prevent DFSORT from terminating.  Note that this will change the actual length in RDW (0028) to 84.
The output after submitting the JCL is shown in Picture 5.6.
  
Picture 5.6

Hope this helps. Use the Comments section below, to share your thoughts on this article. 


Screenshot courtesy: Mainframe access obtained via Master the Mainframe contest run by IBM.


Wednesday, December 5, 2018

How to reverse a string in COBOL without using FUNCTION REVERSE

Hello,

In this post I'll be showing how to reverse a string in COBOL without using an instrinsic (read instrinsic as in-built) function in COBOL, called FUNCTION REVERSE. This is also a common question asked in COBOL language interviews.

Pseudocode goes like this:
  1. Have the string you want to reverse, in a data-item.
  2. Define a data item (or) a table to store the reversed string.
  3. PERFORM a loop, with a data-item whose value is the length of the string, decremented by 1 in each iteration, until the data-item's value reached zero.
  4. Inside the loop, for each iteration, MOVE, starting from the last character of the string, either to the destination table (or) data-item.
  5. After loop, DISPLAY the reversed string.
In the following code, I've used a table to store the characters of the reversed string.

 IDENTIFICATION DIVISION.  
 PROGRAM-ID. REVERS.  
 DATA DIVISION.  
 WORKING-STORAGE SECTION.  
 01 WS-A   PIC X(50) VALUE 'SRINIVASAN'.  
 01 WS-TABLE.  
   05 WS-O OCCURS 0 TO 50 TIMES DEPENDING ON WS-LEN PIC X.   
 01 WS-I   PIC   9(3) VALUE 0.  
 01 WS-J   PIC   9(2) VALUE 1.   
 01 WS-LEN PIC 9(3) VALUE 0.   
 PROCEDURE DIVISION.  
     MOVE FUNCTION LENGTH(WS-A) TO WS-LEN.  
     PERFORM VARYING WS-I FROM WS-LEN BY -1 UNTIL WS-I = 0  
     MOVE WS-A(WS-I:1) TO WS-O(WS-J)  
     ADD 1 TO WS-J  
     END-PERFORM  
     DISPLAY WS-TABLE.   
     STOP RUN.  

Running the above COBOL program will give the following output. 


                                        NASAVINIRS

If you wish to use a data-item to store the reversed string, you can very well make use of reference modification to write the characters one by one to the destination data item as shown in the following code snippet.
 WORKING-STORAGE SECTION.  
 01 WS-A PIC X(50) VALUE 'SRINIVASAN'.  
 01 WS-OUT PIC X(50).   
 ...  
 ...  
 ...  
 PROCEDURE DIVISION.  
 MOVE FUNCTION LENGTH(WS-A) TO WS-LEN.  
 PERFORM VARYING WS-I FROM WS-LEN BY -1 UNTIL WS-I = 0  
 MOVE WS-A(WS-I:1) TO WS-OUT(WS-J:1)  
 ...  
 ...  
 ...  
 DISPLAY WS-OUT.   
 STOP RUN.  

Hope this helps!