Joined: 07 Jan 2003 Posts: 1056 Topics: 91 Location: The Blue Planet
Posted: Thu Nov 25, 2004 5:06 am Post subject: Sort Challenge !!!
Hi,
Here is a small SORT challenge for all of you. Actually my friend asked this question to me. I already completed this. I will post my solution later.The challenge is open. You can give solution in any Sort Product (DFSORT/Syncsort /CA-sort).
I have a input file as shown below.
Code:
250
1000
657
9800
12
567
700
The input file layout is: (LRECL=80, RECFM=FB)
FIELD1 PIC X(04)
FILLER PIC X(76)
The Output should look like this: You should group 3 records at a time and the 3 FIELD1 should come in one line.
Code:
250 1000 657
9800 12 567
700
This should be accomplished in MINIMUM no. of Steps & Passes.
Joined: 07 Jan 2003 Posts: 1056 Topics: 91 Location: The Blue Planet
Posted: Tue Nov 30, 2004 1:09 am Post subject:
Hi All,
Its really surprising to see that there are no responses to this thread yet.
The challenge is still open. You can give solutions in syncsort/Dfsort. I will post my solution tomorrow.
Joined: 26 Nov 2002 Posts: 12375 Topics: 75 Location: San Jose
Posted: Tue Nov 30, 2004 8:24 am Post subject:
LRDevulapalli,
You don't need 4 passes to achieve the data. I don't have DFSORT at my shop,so cannot test it. But here is the untested version of DFSORT using SAMPLE & SPLICE parms. You also need KEEPNODUPS parm on the Splice parm to keep records which do not have matching record to splice.
Joined: 07 Jan 2003 Posts: 1056 Topics: 91 Location: The Blue Planet
Posted: Wed Dec 01, 2004 1:35 am Post subject:
Okay.....I have got 6 solutions from 5 people. And surprisingly all 6 are different. Two of these are already posted (one by LRDevulapalli and Kolusu's reply to that post).
Here are the remaining 4. Please feel free to give your Suggestions/Comments.
Solution 1: From the requestor of this Challenge - my Colleague
This solution took 2 Steps and 5 passes over the input file. It also required 6 temporary files to get to the result. The developer used the OUTFIL SPLIT option to a good extent to split the records easily across three temp files, but he took 5 passes of the input.
This solution took 3 Steps, 3 passes & 4 Temporary files to get to the result. The First 2 steps could have been easily merged into 1 using OUTFIL SPLIT parameters in the same step.
The first two solutions was written to handle only numeric data, since the developers used ZD summation to merge the records. Kolusu's solution is more generic. It supports Numeric as well as non-numeric data in the input file. Solution 2 is a bit similar to this but Kolusu's one is more efficient since the no. of passes required is just 2.
The solution takes 1 step, 2 passes and just 1 Temp. file to achieve the desired result.
Pass # 1:
---------
a. Use INREC to Insert a 8 digit sequence number (starting at 00000000) at the end of the record layout.
b. In OUTREC, use arithmetic operators over the Sequence no. field and generate two different types of sequence nos in the record.
5,8,ZD,SUB,(5,8,ZD,DIV,+3),MUL,+3,EDIT=(TTTT) - This will generate a set of numbers in the sequence 0000, 0001, 0002, 0000, 0001, 0002, 0000 and so on. (Basically this is similar to using MOD operator).
5,8,ZD,DIV,+3,EDIT=(TTTTTTTT) - This will produce a set of numbers in the sequence 00000000, 00000000, 00000000, 00000001, 00000001, 00000001, 00000002 & so on. This is used to group 3 records together in the next pass.
Output of OUTREC will be as shown below:
----+----1----+----2
0001000000000000
0002000100000000
0003000200000000
0004000000000001
0005000100000001
0006000200000001
0007000000000002
0008000100000002
0009000200000002
0010000000000003
0011000100000003
0012000200000003
0013000000000004
0014000100000004
0015000200000004
0016000000000005
0017000100000005
0018000200000005
0019000000000006
0020000100000006
c. The final OUTFIL OUTREC statement uses CHANGE operator to reformat the input record depending on the seqnum at position 5 to 8.
If 5 to 8 contains 0000, then convert the record as <4 char data> <space> <4 low-value> <space> <4 low-value> <space> <seqnum 2>
If 5 to 8 contains 0001, then convert the record as <4 low-value> <space> <4 char data> <space> <4 low-value> <space> <seqnum 2>
If 5 to 8 contains 0002, then convert the record as <4 low-value> <space> <4 low-value> <space> <4 char data> <space> <seqnum 2>
Pass # 2:
---------
a. Sort the records on the seqnum order (at Pos 16 to 23) so that 3 records are grouped at a time.
b. Sum the data portion (1,4, 6,4 and 11,4) using BI summation so that the records are merged together.
c. Strip off the seqnum before writing to output.
This solution is slightly different from your solution. We directly use the character values in the change parm as the merging of the records is done by SPLICE parm.
Although the I/P file has a record length of 80, I am enforcing a length of 240 in I/P parameters so that it picks up 3 records at a time and then sort takes the 1st 4 characters and next 4 from 81st byte (i.e. first 4 characters of 2nd record) and then from 240th byte keeping the rest 68 bytes in O/P as spaces.
Joined: 07 Jan 2003 Posts: 1056 Topics: 91 Location: The Blue Planet
Posted: Sun Dec 12, 2004 2:36 am Post subject:
Danav,
Excellent!!!. Though your solution has a limitation on the input file record count, it is good for everyone to the different possible alternatives. Probably your solution could turn very handy in some special cases. Its always good to think in 'n' different ways !!!.
Joined: 02 Dec 2002 Posts: 1618 Topics: 31 Location: San Jose
Posted: Sat Dec 25, 2004 2:02 pm Post subject:
Below is a DFSORT solution with only one sort pass and no temporary files that can handle numerics and non-numerics. It uses the new IFTHEN and OVERLAY features available with z/OS DFSORT V1R5 PTF UQ95214 and DFSORT R14 PTF UQ95213.
Note that both IFTHEN and OVERLAY can be used to do multiple operations on each record, and earlier changes affect later changes. For example:
INREC statement:
In the OVERLAY for WHEN=INIT, we set up the seqnum and then use MOD on the seqnum to get 0, 1 or 2. We then use the 0, 1 or 2 in subsequent IFTHEN clauses all within the same INREC statement before we start sorting.
OUTREC statement:
In the first IFTHEN we use HIT=NEXT to continue with the second OUTREC IFTHEN for all records so we can handle binary zeros in 6-9 AND in 11-14.
It's pretty amazing what you can do in one pass using IFTHEN.
Code:
//S1 EXEC PGM=ICEMAN
//SYSOUT DD SYSOUT=*
//SORTIN DD *
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
AAAA
BBBB
/*
//SORTOUT DD SYSOUT=*
//SYSIN DD *
OPTION EQUALS
* Init. records to:
INREC IFTHEN=(WHEN=INIT,
* aaaa zzzz zzzz ... 00000001
* bbbb zzzz zzzz ... 00000002
* cccc zzzz zzzz ... 00000003
* dddd zzzz zzzz ... 00000004
* eeee zzzz zzzz ... 00000005
* ffff zzzz zzzz ... 00000006
* ...
* where zzzz is 4 binary zeros.
OVERLAY=(6:4Z,11:4Z,81:SEQNUM,8,ZD,START=0,
* Use MOD to convert seqnum to 0, 1 or 2 to get:
* aaaa zzzz zzzz ... 0
* bbbb zzzz zzzz ... 1
* cccc zzzz zzzz ... 2
* dddd zzzz zzzz ... 0
* eeee zzzz zzzz ... 1
* ffff zzzz zzzz ... 2
* ...
81:81,8,ZD,MOD,+3,TO=ZD,LENGTH=1)),
* Set seqnum for 0 records to get:
* aaaa zzzz zzzz ... 00000001
* dddd zzzz zzzz ... 00000002
* ...
IFTHEN=(WHEN=(81,1,CH,EQ,C'0'),
OVERLAY=(81:SEQNUM,8,ZD)),
* Set seqnum for 1 records and reformat to get:
* zzzz bbbb zzzz ... 00000001
* zzzz eeee zzzz ... 00000002
* ...
IFTHEN=(WHEN=(81,1,CH,EQ,C'1'),
OVERLAY=(6:1,4,1:4Z,81:SEQNUM,8,ZD)),
* Set seqnum for 2 records and reformat to get:
* zzzz zzzz cccc ... 00000001
* zzzz zzzz ffff ... 00000002
* ...
IFTHEN=(WHEN=(81,1,CH,EQ,C'2'),
OVERLAY=(11:1,4,1:4Z,81:SEQNUM,8,ZD))
* Sort on seqnum to get:
* aaaa zzzz zzzz ... 00000001
* zzzz bbbb zzzz ... 00000001
* zzzz zzzz cccc ... 00000001
* dddd zzzz zzzz ... 00000002
* zzzz eeee zzzz ... 00000002
* zzzz zzzz ffff ... 00000002
* ...
SORT FIELDS=(81,8,ZD,A)
* SUM with binary zeros to get:
* aaaa bbbb cccc ... 00000001
* dddd eeee ffff ... 00000002
* ...
SUM FORMAT=BI,FIELDS=(1,4,6,4,11,4)
* Replace binary zeros in 6-9 or 11-14 with blanks (takes care of
* record count that is not a multiple of 3).
OUTREC IFTHEN=(WHEN=(6,4,BI,EQ,+0),OVERLAY=(6:4X),HIT=NEXT),
IFTHEN=(WHEN=(11,4,BI,EQ,+0),OVERLAY=(11:4X)),
* Remove seqnum.
IFOUTLEN=80
/*
Of course, you could use the same technique with COPY and SPLICE operators instead of doing the binary SUM trick, if you like.
For complete information on the new functions available with these DFSORT PTFs, see:
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum