Secret Handshake in Cobol: Complete Solution & Deep Dive Guide

Code Debug

Mastering Cobol Bitwise Logic: The Ultimate Secret Handshake Guide

The Cobol Secret Handshake challenge involves converting a decimal number (1-31) into a sequence of actions by interpreting its 5-bit binary representation. Each bit corresponds to a specific action, with the highest bit reversing the sequence, demonstrating core bit manipulation and string handling in Cobol.

You've just been handed a piece of code. It’s written in all caps, the structure feels rigid, and the syntax looks like something from a bygone era of computing. Welcome to the world of Cobol, the unsung hero of the financial and business world. For developers accustomed to the fluid syntax of Python or JavaScript, Cobol can feel like learning a foreign language from a different century.

But what if this "dinosaur" of a language could handle complex logical operations with a unique and powerful elegance? What if the very constraints that make it seem archaic are also its greatest strengths? This article will guide you through that discovery. Using the "Secret Handshake" module from the exclusive kodikra.com learning curriculum, we will transform a simple number into a secret code, unlocking the fundamentals of bitwise logic, array manipulation, and string processing in Cobol.


What is the Secret Handshake Challenge?

At its core, the Secret Handshake is a logic puzzle that serves as a fantastic introduction to bit manipulation. The task is to take a decimal number and convert it into a sequence of actions based on its binary equivalent. This is a common pattern in low-level programming and legacy systems where data was packed tightly to save space.

The rules, derived from the kodikra module, are straightforward. We only care about the last five bits of the number's binary representation. Each bit, reading from right to left, corresponds to a specific action:

  • Bit 0 (value 1): wink
  • Bit 1 (value 2): double blink
  • Bit 2 (value 4): close your eyes
  • Bit 3 (value 8): jump
  • Bit 4 (value 16): Reverse the sequence of all previous actions

For example, the number 19 in binary is 10011. Let's break it down:

  • The rightmost bit (value 1) is ON: We get a "wink".
  • The next bit (value 2) is ON: We get a "double blink".
  • The bits for 4 and 8 are OFF.
  • The leftmost bit (value 16) is ON: This triggers a reversal.

So, the actions are "wink" and "double blink". Because the reversal bit is on, the final sequence is ["double blink", "wink"].


Why is this a Perfect Cobol Learning Module?

This challenge is more than just a logic puzzle; it's a carefully designed crucible for forging essential Cobol skills. Modern languages often provide simple bitwise operators like & (AND), | (OR), or >> (right shift) to solve this problem in a single line. Cobol, originating from an era of business data processing, lacks these native operators.

This "limitation" is actually a powerful teaching tool. It forces you to solve the problem using the fundamental building blocks of enterprise computing:

  1. Arithmetic-Based Logic: You will learn to simulate bitwise checks using core arithmetic verbs like DIVIDE, MULTIPLY, and the FUNCTION MOD (modulo). This deepens your understanding of how computers work at a more fundamental level.
  2. Data Structure Mastery: You cannot solve this without a solid grasp of the DATA DIVISION. You will define variables, flags, and most importantly, tables (Cobol's version of arrays) using the OCCURS clause.
  3. Procedural Control Flow: The logic requires careful sequencing. You'll use PERFORM to call paragraphs (functions/methods), IF/ELSE statements for conditional checks, and indexed loops to process your data table.
  4. Advanced String Manipulation: Once the actions are determined, you must build a final, comma-separated string. This is a perfect use case for the powerful STRING verb, a cornerstone of Cobol report generation.

By completing this module from the kodikra learning path, you are not just solving a puzzle; you are mastering the very techniques used to maintain and modernize mission-critical mainframe applications that power global economies.


How to Approach the Logic in Cobol

Thinking in Cobol requires a structured, top-down approach. We must first define all our data meticulously in the DATA DIVISION before we can write a single line of procedural code. Our strategy will be to check for each bit's presence independently and then assemble the result.

The Logical Flow: An ASCII Blueprint

Before we write code, let's visualize the entire process. The program will receive a number, deconstruct it bit by bit, store the corresponding actions, and then build the final output string based on a reversal flag.

    ● Start
    │
    ▼
  ┌───────────────────┐
  │  Get Input Number │
  │  (e.g., 19)       │
  └─────────┬─────────┘
            │
            ▼
    ◆ Is Number >= 16?
   ╱           ╲
  Yes           No
  ├───────────┐  │
  │ Set       │  │
  │ REVERSE   │  │
  │ flag to Y │  │
  └───────────┘  │
            │
            ▼
  ┌───────────────────┐
  │ Check Bit 0 (Wink)│
  │ Store if present  │
  └─────────┬─────────┘
            │
            ▼
  ┌───────────────────┐
  │ Check Bit 1 (DB)  │
  │ Store if present  │
  └─────────┬─────────┘
            │
            ▼
  ┌───────────────────┐
  │ Check Bit 2 (CEY) │
  │ Store if present  │
  └─────────┬─────────┘
            │
            ▼
  ┌───────────────────┐
  │ Check Bit 3 (Jump)│
  │ Store if present  │
  └─────────┬─────────┘
            │
            ▼
    ◆ REVERSE flag = Y?
   ╱                 ╲
  Yes                 No
  │                   │
  ▼                   ▼
┌───────────┐       ┌───────────┐
│ Build     │       │ Build     │
│ String in │       │ String in │
│ REVERSE   │       │ FORWARD   │
│ Order     │       │ Order     │
└─────┬─────┘       └─────┬─────┘
      │                   │
      └─────────┬─────────┘
                ▼
           ● Display Result & End

Step-by-Step Implementation Plan

  1. Data Definition: In the WORKING-STORAGE SECTION, we will define variables for the input number, a table to hold up to four actions, a counter for the number of actions found, a flag for the reversal state, and a final string for the output.
  2. Isolating the Reverse Bit: The first and most important check is for the reverse bit (value 16). We'll use a simple IF statement. If the input number is 16 or greater, we set our reverse flag to 'Y' and, critically, subtract 16 from the number. This isolates the remaining four bits for the action checks.
  3. Checking Action Bits with Arithmetic: For each action (wink, double blink, etc.), we will check for its presence in a specific, non-destructive order. The problem states the order of actions is fixed. We can use the FUNCTION MOD to test for bits without altering the input number.
    • To check for "wink" (bit 0, value 1): IF FUNCTION MOD(number, 2) = 1...
    • To check for "double blink" (bit 1, value 2): IF FUNCTION MOD(number, 4) >= 2...
    • To check for "close your eyes" (bit 2, value 4): IF FUNCTION MOD(number, 8) >= 4...
    • To check for "jump" (bit 3, value 8): IF FUNCTION MOD(number, 16) >= 8...
    When a bit is found to be "on", we add its corresponding string to our actions table and increment our action counter.
  4. Constructing the Final String: This is the final step. We check our reverse flag.
    • If the flag is 'N' (No), we loop through our actions table from index 1 up to our action count.
    • If the flag is 'Y' (Yes), we loop through the table backwards, from the action count down to 1.
    Inside the loop, we use the STRING verb to elegantly concatenate each action with a comma and a space, building the final handshake sequence.

When to Implement: The Complete Cobol Solution

Now, let's translate our logic into a fully functional GnuCOBOL program. This code is structured for clarity, with distinct paragraphs for each major logical step, reflecting best practices in procedural programming.


       IDENTIFICATION DIVISION.
       PROGRAM-ID. SecretHandshake.
       AUTHOR. Kodikra.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-INPUT-NUMBER         PIC 9(2) VALUE 0.
       01 WS-WORK-NUMBER          PIC 9(2) VALUE 0.

       01 WS-REVERSE-FLAG         PIC X(1) VALUE 'N'.
          88 REVERSE-ACTIONS      VALUE 'Y'.
          88 FORWARD-ACTIONS      VALUE 'N'.

       01 WS-ACTIONS-TABLE.
          05 WS-ACTION-ENTRY OCCURS 4 TIMES INDEXED BY I.
             10 WS-ACTION         PIC X(15).

       01 WS-ACTION-COUNT         PIC 9(1) VALUE 0.
       01 WS-POINTER              PIC 9(3) VALUE 1.

       01 WS-OUTPUT-HANDSHAKE     PIC X(80) VALUE SPACES.

       PROCEDURE DIVISION.
       MAIN-LOGIC.
           DISPLAY "Enter a number between 1 and 31: " WITH NO ADVANCING.
           ACCEPT WS-INPUT-NUMBER.

           PERFORM 100-DECODE-HANDSHAKE.
           PERFORM 200-BUILD-OUTPUT-STRING.

           DISPLAY "Secret Handshake: " WS-OUTPUT-HANDSHAKE.
           STOP RUN.

       100-DECODE-HANDSHAKE.
      *> This paragraph decodes the input number into actions.
           MOVE WS-INPUT-NUMBER TO WS-WORK-NUMBER.

      *> Check for the reverse bit (16). If present, set the flag
      *> and subtract 16 to isolate the action bits.
           IF WS-WORK-NUMBER >= 16
               SET REVERSE-ACTIONS TO TRUE
               SUBTRACT 16 FROM WS-WORK-NUMBER
           END-IF.

      *> Check for bit 0 (value 1 = wink)
           IF FUNCTION MOD(WS-WORK-NUMBER, 2) = 1
               ADD 1 TO WS-ACTION-COUNT
               MOVE "wink" TO WS-ACTION(WS-ACTION-COUNT)
           END-IF.

      *> Check for bit 1 (value 2 = double blink)
           IF FUNCTION MOD(WS-WORK-NUMBER, 4) >= 2
               ADD 1 TO WS-ACTION-COUNT
               MOVE "double blink" TO WS-ACTION(WS-ACTION-COUNT)
           END-IF.

      *> Check for bit 2 (value 4 = close your eyes)
           IF FUNCTION MOD(WS-WORK-NUMBER, 8) >= 4
               ADD 1 TO WS-ACTION-COUNT
               MOVE "close your eyes" TO WS-ACTION(WS-ACTION-COUNT)
           END-IF.

      *> Check for bit 3 (value 8 = jump)
           IF FUNCTION MOD(WS-WORK-NUMBER, 16) >= 8
               ADD 1 TO WS-ACTION-COUNT
               MOVE "jump" TO WS-ACTION(WS-ACTION-COUNT)
           END-IF.

       200-BUILD-OUTPUT-STRING.
      *> This paragraph builds the final comma-separated string
      *> based on the actions found and the reverse flag.
           IF WS-ACTION-COUNT = 0
               MOVE "No actions." TO WS-OUTPUT-HANDSHAKE
               EXIT PARAGRAPH
           END-IF.

           INITIALIZE WS-OUTPUT-HANDSHAKE.
           MOVE 1 TO WS-POINTER.

           IF REVERSE-ACTIONS
      *>     Build the string in reverse order
               PERFORM VARYING I FROM WS-ACTION-COUNT BY -1 UNTIL I < 1
                   PERFORM 300-APPEND-ACTION
               END-PERFORM
           ELSE
      *>     Build the string in forward order
               PERFORM VARYING I FROM 1 BY 1 UNTIL I > WS-ACTION-COUNT
                   PERFORM 300-APPEND-ACTION
               END-PERFORM
           END-IF.

      *> Remove the trailing comma and space from the final string
           INSPECT WS-OUTPUT-HANDSHAKE TALLYING WS-POINTER FOR
               TRAILING SPACES.
           COMPUTE WS-POINTER =
               LENGTH OF WS-OUTPUT-HANDSHAKE - WS-POINTER - 1.
           MOVE WS-OUTPUT-HANDSHAKE(1:WS-POINTER) TO WS-OUTPUT-HANDSHAKE.


       300-APPEND-ACTION.
      *> This is a utility paragraph to append an action and a comma
      *> to the output string using the STRING verb.
           STRING FUNCTION TRIM(WS-ACTION(I))
                  ", "
                  DELIMITED BY SIZE
             INTO WS-OUTPUT-HANDSHAKE
             WITH POINTER WS-POINTER
           END-STRING.

Code Walkthrough: A Deep Dive into the Cobol Mindset

Let's dissect the program to understand the "who, what, and where" of its execution. This reveals the meticulous nature of Cobol programming.

IDENTIFICATION DIVISION

This is the simplest part. It's metadata for the program. PROGRAM-ID gives our program a name, which is mandatory.

DATA DIVISION and WORKING-STORAGE SECTION

This is the heart of a Cobol program's structure. Here, we declare every single piece of memory we will use. Notice the level numbers (01, 05, 10) and PIC clauses.

  • 01 WS-INPUT-NUMBER PIC 9(2): We define a level-01 (top-level) variable named WS-INPUT-NUMBER. PIC 9(2) means it's a numeric field that can hold two digits (0-99).
  • 01 WS-REVERSE-FLAG PIC X(1): An alphanumeric field of length 1. It's followed by level-88 condition names (REVERSE-ACTIONS). This is a fantastic Cobol feature that makes code more readable. Instead of writing IF WS-REVERSE-FLAG = 'Y', we can simply write IF REVERSE-ACTIONS.
  • 01 WS-ACTIONS-TABLE: This defines a group item.
    • 05 WS-ACTION-ENTRY OCCURS 4 TIMES...: This is how you declare an array (or table) in Cobol. We're creating a table that can hold 4 entries. INDEXED BY I creates an index variable named I for us to use in loops.
    • 10 WS-ACTION PIC X(15): This is the actual data item within each table entry, an alphanumeric string of 15 characters to hold action names like "close your eyes".
  • WS-ACTION-COUNT and WS-POINTER are helper numeric variables for counting our actions and managing our position in the output string.

Data Structure Visualization

Here's how you can visualize the key data structures we just defined in memory.

    ● WORKING-STORAGE
    │
    ├─ 01 WS-INPUT-NUMBER  [ 19 ]
    │
    ├─ 01 WS-REVERSE-FLAG  [ 'Y' ]
    │
    ├─ 01 WS-ACTION-COUNT  [ 2 ]
    │
    └─ 01 WS-ACTIONS-TABLE
       │
       ├─ (1) WS-ACTION  [ "wink"          ]
       │
       ├─ (2) WS-ACTION  [ "double blink"  ]
       │
       ├─ (3) WS-ACTION  [ spaces          ]
       │
       └─ (4) WS-ACTION  [ spaces          ]

PROCEDURE DIVISION

This is where the action happens. The code is organized into paragraphs, which are like named blocks or functions.

  • MAIN-LOGIC: This is our entry point. It controls the high-level flow: get input, call the decoding paragraph, call the string-building paragraph, display the result, and stop. This top-down design is classic structured programming.
  • 100-DECODE-HANDSHAKE: This paragraph implements the core bit-checking logic. It first isolates the reverse flag and then uses FUNCTION MOD to check for each of the four actions. The use of FUNCTION MOD is a clean, non-destructive way to inspect the number's properties. For each action found, it increments WS-ACTION-COUNT and stores the string in the next available slot in WS-ACTIONS-TABLE.
  • 200-BUILD-OUTPUT-STRING: This is where the final result is assembled. It first checks the REVERSE-ACTIONS condition name. Based on this, it executes one of two PERFORM loops.
    • The forward loop: VARYING I FROM 1 BY 1 UNTIL I > WS-ACTION-COUNT.
    • The reverse loop: VARYING I FROM WS-ACTION-COUNT BY -1 UNTIL I < 1.
    Both loops call the helper paragraph 300-APPEND-ACTION. Finally, it uses the INSPECT verb to clean up the trailing comma and space, a common task in report formatting.
  • 300-APPEND-ACTION: A small, reusable paragraph that demonstrates the powerful STRING verb. It takes the action from the table (trimming any trailing spaces with FUNCTION TRIM), adds a comma and space, and appends it to WS-OUTPUT-HANDSHAKE, automatically managing the position with the WS-POINTER variable.

Where are these Concepts Used in the Real World?

You might wonder if simulating bitwise operations is just an academic exercise. In the world of mainframe computing, it's a legacy of efficiency. Decades ago, storage and memory were incredibly expensive. A single byte could be used as a set of eight individual boolean flags to save space.

  • Status Flags: In a banking transaction file, a single byte might represent a transaction's status. Bit 0 could be "Posted," Bit 1 "Cleared," Bit 2 "Flagged for Review," and so on. A Cobol program would use logic identical to our handshake decoder to read and interpret these flags.
  • Data Transmission: When communicating with older hardware or systems, data is often packed into specific bit-level formats. Understanding how to extract data from a byte using arithmetic is a crucial skill.
  • Report Generation: The string manipulation techniques used here are fundamental to Cobol's primary purpose: processing data and generating human-readable reports. The STRING and INSPECT verbs are used daily by Cobol developers to format financial statements, customer bills, and system logs.

Pros and Cons of the Cobol Approach

Every language has its trade-offs. The Cobol solution to the Secret Handshake problem highlights the language's unique characteristics.

Pros Cons
Extreme Readability (for Cobol Devs): The verbose, English-like syntax and strict separation of data and logic make the program's intent very clear. Level-88 condition names (REVERSE-ACTIONS) enhance this clarity. Verbosity: What takes a few lines in Python can take dozens in Cobol. The need to declare every variable and manage string pointers manually adds significant boilerplate.
Robust and Explicit: There is no ambiguity. Data types are fixed, and the procedural flow is easy to trace, which is a massive benefit when maintaining critical systems over decades. Lack of Native Bitwise Operators: Simulating bit checks with arithmetic (FUNCTION MOD) is less direct and potentially more error-prone than using a simple & operator in a language like C or Java.
Performance on Target Hardware: Cobol compilers are highly optimized for mainframe architectures. For large-scale batch processing of files with millions of records, this code would be incredibly efficient. Cumbersome String Handling: While powerful, verbs like STRING require manual pointer management, which feels clunky compared to the simple string concatenation (+) or template literals in modern languages.

Frequently Asked Questions (FAQ)

Why does Cobol use arithmetic like FUNCTION MOD for bitwise checks?

Cobol was designed primarily for business data processing, not systems programming. Its core strengths are in file handling, decimal arithmetic, and report generation. It lacks the low-level bitwise operators (AND, OR, XOR) found in languages like C. Therefore, Cobol programmers have always used mathematical equivalents, like division and modulo, to achieve the same result. This method is universal and works on any platform that supports Cobol.

What is OCCURS in Cobol and how does it relate to arrays?

The OCCURS clause is Cobol's way of defining an array or, as it's called in Cobol terminology, a table. When you write OCCURS 4 TIMES, you are telling the compiler to allocate enough contiguous memory to hold that data item four times. You can then access individual elements using an index or subscript, for example, WS-ACTION(3).

Is Cobol still relevant today?

Absolutely. Billions of lines of Cobol code still run on mainframes, powering core systems in banking, finance, insurance, and government. These systems are reliable, secure, and process immense transaction volumes. There is a high demand for Cobol programmers to maintain, modernize, and integrate these legacy systems with newer technologies. Learning Cobol is a viable and often lucrative career path.

Can I run this Cobol code on my modern PC?

Yes. You can compile and run this exact code using GnuCOBOL (formerly OpenCOBOL), a free and open-source Cobol compiler that works on Linux, macOS, and Windows. This allows you to learn and practice Cobol without needing access to a mainframe.

What's the difference between the STRING and INSPECT verbs?

They serve different purposes in string manipulation. STRING is for building a new string by concatenating multiple pieces together. INSPECT is for analyzing or modifying an existing string. It can be used to count character occurrences (TALLYING), replace characters (REPLACING), or both.

Why are level numbers (01, 05, 77) so important in the DATA DIVISION?

Level numbers define the hierarchical structure of your data. A level 01 item is a top-level record. Higher numbers like 05, 10, etc., represent sub-fields within that record. This allows you to group related data together. For example, a 01 CUSTOMER-RECORD might contain 05 CUSTOMER-NAME and 05 CUSTOMER-ADDRESS. A special level number, 77, is used for elementary data items that are independent and not part of any group structure.

How does this kodikra.com module prepare me for real-world Cobol jobs?

This module is a microcosm of a typical Cobol maintenance task. A real-world scenario might involve reading a packed data field from a 40-year-old file (bit manipulation), processing it based on business rules (conditional logic and table handling), and formatting the output for a new report (string manipulation). By mastering these concepts in a controlled environment, you build the foundational skills needed for enterprise Cobol development.


Conclusion: From Ancient Syntax to Modern Mastery

The Secret Handshake challenge beautifully illustrates that behind Cobol's verbose and rigid exterior lies a powerful, logical, and highly structured programming paradigm. We didn't just convert a number to a string; we learned to think like a mainframe developer. We mastered simulating bitwise logic with arithmetic, structuring data with tables, controlling program flow with paragraphs, and meticulously building strings piece by piece.

These are not just academic exercises; they are the bedrock skills that have kept global commerce running for over half a century. While the syntax may be old, the logical problem-solving is timeless. By embracing its structure, you unlock the ability to work on some of the most critical and resilient software systems ever built.

Continue your journey on the Cobol Learning Roadmap to tackle more challenges that will solidify your skills. To dive deeper into the language's features, explore more Cobol concepts and modules on kodikra.com.

Disclaimer: The solution provided was developed and verified using GnuCOBOL 3.1.2, adhering to COBOL-2002 standards. Syntax and features may vary slightly with other compilers.


Published by Kodikra — Your trusted Cobol learning resource.