Friday, December 13, 2019

Another Lab Assignment - PC/370 and WinBatch

My daughter showed me another of her computer lab assignments. Just a random number transformation. She drew a sketch of the GUI along with some samples. We discussed the exercise requirements & I added some notes to the scrap paper. The design also needs to include an <EXIT> button.

ABOVE: My daughter's sketch of her computer lab project with some of my notes (& red markings).

Requirements: A primary input field that will contain a base integer string and a secondary input that represents the number of positions (starting from the end) within the input string - the digit at that location I'll refer to as the "Magic Number". In the GUI sample sketch the primary value is "1235" and the secondary input is "2". Therefore the "Magic Number" is 2 positions from the end which is "3". It's the 3rd position from the beginning of the file. The transformation logic will add the "Magic Number" to each position to the left of the "Magic Number" and will subtract the "Magic Number" from all digits to the right. The Magic Number itself remains the same. Furthermore, the items to the left must be a single digit (only the ones place is retained) and the items on the right are absolute values.

Another example is with the Base Number of 5 3 7 6 2 7 1 3 4 and the reverse offset position of 5.

The Magic Number is the fifth position from the end - the digit 2. It's also absolute position 5 in the string. Add 2 to each digit to the left of position 5 and subtract 2 from each to the right.

The Output Number is: 7 5 9 8 2 5 1 1 2

Position 7 clearly displays the Absolute Value: ABS(1 - 2) = 1

Here's another example that displays the formula context:

Input: 9 5 1 Offset Position: 2    The "Magic Number" is in the middle with a value of 5.

Output: 4 5 4  

LEFT: 9 + 5 = 14  To isolate the 4 simply take the modulus when dividing by 10.
CENTER: 5 remains unchanged (Magic Number).
RIGHT: 1 - 5 = -4 Just wrap in the ABS function to convert to 4.

It's not a very difficult assignment but it highlights some important functions & concepts to the class - Substrings, Indexing, Length, Loops, Math Functions, Concatenation, etc.

Also a good exercise to show in action - so here's a quick PC/370 & WinBatch version.

PC/370 Solution:

I leveraged the Screen Template I created for the previous AGRAM Card Game. With just a few simple modifications it was ready to go...



 ABOVE: The PC/370 Input Screen using Numeric Validation/Formating.

The Assembler Version is much more streamlined - due to the nature of Packed Data-Types I don't need to perform any explicit MOD() or ABS() function for either portion of the formula. In either case I'm OR'ing the sign bits to X'0F' and I'm only unpacking the last digit (No need to divide by 10 to extract the remainder).

The Input Fields are named AC1 & AC2 respectively. I'm using numeric format [@E#NUM] I developed for my TDACC.CPY data entry copybook. It ensures all characters are numeric, right justifies the data & zero pads on the left. The position has a max value of 13.

The comments within the code provide step-by-step explanation. Notice the zero-padded integers are not included in the calculation & are left blank in the output. The exception to that would be if the zero-padding was also the "Magic Number" based on the offset - in which case it would only be blank up to that point.

***********************************************************************
*        CALCULATE                                                    *
***********************************************************************
         DC    F'0'                          RETURN ADDRESS SAVE AREA
CALC     EQU   *
         ST    6,*-4                         SAVE RETURN ADDRESS
*
         MVC   XBASE,AC1                     MOVE INPUT BASE
         PACK  DUBB,AC2                      PACK INPUT POSITION
         CVB   3,DUBB                        CONVERT TO BINARY
*
         LA    4,XBASE+L'XBASE               POSITION ADDRESS POINTER
         SR    4,3                           SUBTRACT POSITION
         PACK  XMAGIC,0(1,4)                 PACK MAGIC NUMBER
         ST    4,ADDR                        STORE ADDRESS POINTER
*
         NI    CALCLO+1,X'0F'                INIT LEADING ZERO TEST
*
         LA    3,OBASE                       LOAD RESULT ADDRESS
         LA    4,XBASE                       LOAD STRING ADDRESS
CALC1    EQU   *
         CLI   0(4),X'FF'                    END OF STRING???
         BE    CALCX                         YES - EXIT ROUTINE
*
         PACK  XPACK,0(1,4)                  INITIALIZE FIELD
         C     4,ADDR                        COMPARE ADDRESS
         BE    CALCGO                        EQUAL - FORMAT OUTPUT
         BH    CALCHI                        HIGH  - SUBTRACT
CALCLO   EQU   *
         BC    0,CALCLO2                     LEADING ZERO BRANCH
         CLI   0(4),C'0'                     LEADING ZERO?
         BNE   CALCLO2                       NO  - CONTINUE PLEASE
         MVI   0(3),C' '                     YES - MOVE BLANK
         B     CALC2                         CONTINUE FORWARD
CALCLO2  EQU   *
         OI    CALCLO+1,X'F0'                RESET LEADING ZERO TEST
         AP    XPACK,XMAGIC                  ADD MAGIC NUMBER
         B     CALCGO                        FORMAT TRANSFORMATION
CALCHI   EQU   *
         SP    XPACK,XMAGIC                  SUB MAGIC NUMBER
CALCGO   EQU   *
         OI    XPACK+1,X'0F'                 SET ABSOLUTE VALUE
         UNPK  0(1,3),XPACK+1(1)             UNPACK OUTPUT DIGIT
CALC2    EQU   *
         LA    4,1(,4)                       BUMP STRING POINTER
         LA    3,1(,3)                       BUMP RESULT POINTER
         B     CALC1                         TEST NEXT DIGIT
CALCX    EQU   *
         L     6,CALC-4                      RESTORE LINK REGISTER
         BR    6                             BRANCH ON LINK REGISTER
***********************************************************************
         EJECT
***********************************************************************
*        WORKING STORAGE                                              *
***********************************************************************
XBASE    DC    CL13' ',X'FF'                 INPUT BASE STRING
XPACK    DC    PL2'0'                        PACKED NUMBER FIELD
XMAGIC   DC    PL2'0'                        MAGIC NUMBER
DUBB     DC    D'0'                          INPUT BASE POSITION
ADDR     DC    A(XBASE)                      INITIALIZE ADDRESS
OBASE    DC    CL13' ',C'$'                  OUTPUT BASE STRING
***********************************************************************

<SNIP>
***********************************************************************
AC1      DC    CL13' ',C'$'                  ACCEPT - INPUT
AC2      DC    CL2' ',C'$'                   ACCEPT - POSITION
***********************************************************************


NOTE - When data fields are followed by an individual C'$' that means they are used in @WTO operations. In PC/370 the Write-To-Operator messages are terminated with a $ sign.

WinBatch:

The WinBatch version is much easier - especially the GUI Dialog to enter the input values.

ABOVE: WinBatch Data Entry created using Dialog Editor.

The GUI Dialog doesn't have real-time Numeric Validation like I built into the PC/370 screen. Therefore the first part of the routine below does some basic validation & exits if there's something wrong (highlighted in yellow). Non-integer values and an offset position not within the range of 1 up to the string length are violations - the output displays the message "***Invalid Data Entry***".

;**********************************************************************
;*      Process Main                                                  *
;**********************************************************************

:Process_Main

O_base                              = "***Invalid Data Entry***"

if  IsInt(I_base)                  == @FALSE
    goto Process_Main_Exit
endif

if  IsInt(I_pos)                   == @FALSE
    goto Process_Main_Exit
endif

if  I_pos                           < 1
    goto Process_Main_Exit
endif

if  I_pos                           > StrLen(I_base)
    goto Process_Main_Exit
endif


W_len                               = StrLen(I_base)

W_pos                               = (W_len - I_pos) + 1

W_magic                             = StrSub(I_base, W_pos, 1)

O_base                              = ''

for x                               = 1 to W_len

   W_num                            = StrSub(I_base, x, 1)
   W_new                            = W_magic

   if x                             < W_pos
      W_new                         = (W_num + W_magic) mod 10
   else
      if x                          > W_pos
         W_new                      = Abs(W_num - W_magic)
      endif
   endif

   O_base                           = StrCat(O_base, W_new)

next

:Process_Main_Exit

Return

;**********************************************************************


Another fun little puzzle...


Previous 370 Assembler Posts:
https://tdxbits.blogspot.com/2019/03/pc370-assembler-object-code-translator.html
https://tdxbits.blogspot.com/2019/03/mvs370-assembler-like-building-with.html
https://tdxbits.blogspot.com/2019/03/pc370-assembler-creation-stars-stripes.html
https://tdxbits.blogspot.com/2019/04/resourceful-solution-using-ibm-dfsort.html
https://tdxbits.blogspot.com/2019/04/caroscoe-libi-interface-read-member.html
https://tdxbits.blogspot.com/2019/11/acsl-agram-card-game-pc370-version.html
https://tdxbits.blogspot.com/2019/11/acsl-agram-pc370-keyboard-input.html
https://tdxbits.blogspot.com/2019/12/pc370-assembler-object-code-translator.html
https://tdxbits.blogspot.com/2019/12/interesting-grid-algorithm-pc370-sqr.html