Resistor Color Trio in Abap: Complete Solution & Deep Dive Guide

Tabs labeled

Mastering ABAP Logic: A Deep Dive into the Resistor Color Trio Problem

Learn to solve the ABAP Resistor Color Trio challenge by mapping color names to numerical values. This guide covers creating a robust solution using modern ABAP syntax, including data structures, string manipulation, and mathematical calculations to determine a resistor's final ohm value from three color bands.


Ever stared at a tiny electronic component with colorful stripes and wondered how it translates into a precise technical specification? This is a common scenario in electronics, where resistors use a color-coding system to denote their resistance value. For a developer, this presents a fascinating challenge: how do you teach a machine, specifically an SAP system using ABAP, to read and interpret these colors?

You might be thinking this is a niche problem, far removed from the world of business processes and enterprise software. However, the core principles involved—mapping, data transformation, and logical calculation—are the bedrock of countless tasks you'll perform as an ABAP developer. This exercise from the exclusive kodikra.com curriculum is designed to sharpen these exact skills.

In this ultimate guide, we will deconstruct the Resistor Color Trio problem from the ground up. We'll build a clean, modern, and efficient ABAP solution, transforming you from a novice to a confident problem-solver ready to tackle complex data manipulation tasks within the SAP ecosystem.


What is the Resistor Color Trio Problem?

The Resistor Color Trio problem is a classic programming exercise that simulates the process of reading the resistance value from a standard three-band resistor. In electronics, the first two bands represent the first two significant digits of the resistance value, and the third band represents a multiplier (a power of 10).

The challenge is to write a program that takes three color names as input (e.g., "Orange", "Orange", "Black") and outputs a human-readable string with the final resistance value and its unit (e.g., "33 ohms").

Here's the standard color-to-value mapping:

  • Black: 0
  • Brown: 1
  • Red: 2
  • Orange: 3
  • Yellow: 4
  • Green: 5
  • Blue: 6
  • Violet: 7
  • Grey: 8
  • White: 9

The calculation follows a specific formula: the value is (10 * first_color_value + second_color_value) * (10 ^ third_color_value). The final result in ohms must then be formatted. If the value is 1000 ohms or greater, it should be converted to kiloohms.


Why is This a Foundational Module for ABAP Developers?

While seemingly simple, this problem is a perfect vehicle for learning and reinforcing fundamental ABAP concepts that are critical in real-world SAP development. It's not just about resistors; it's about mastering data transformation logic.

Here’s what makes it so valuable:

  • Data Mapping and Lookups: You must create a mapping between string values (colors) and integer values. This is analogous to mapping status codes to descriptions, country codes to country names, or plant codes to plant details in SAP.
  • Object-Oriented ABAP: The problem is an excellent candidate for encapsulation within a class (ZCL_...), promoting clean, reusable, and testable code—a cornerstone of modern ABAP development.
  • String and Data Type Manipulation: You'll work with strings, convert them to numbers, perform calculations, and format the final result back into a descriptive string. This includes using modern string templates.
  • Mathematical Operations: The use of exponents (10 ** value) is a direct application of ABAP's mathematical capabilities.
  • Conditional Logic: The final step of deciding whether to display the result in "ohms" or "kiloohms" requires clear conditional logic (IF/ELSE), a universal programming construct.
  • Error Handling: What happens if an invalid color is provided? A robust solution must anticipate and handle such exceptions gracefully, a non-negotiable requirement in enterprise software.

By solving this, you build a mental model for processing and transforming coded data, a skill you will use daily when working with BAPIs, APIs, and complex business logic in an SAP S/4HANA environment.


How to Design and Implement the ABAP Solution

A structured approach is key to building a maintainable and efficient solution. We will use an object-oriented approach by creating a global class. This makes the logic self-contained and easily testable with ABAP Unit.

Step 1: Define the Data Structure for Color Mapping

First, we need a reliable way to store the color-to-value mapping. While a long CASE statement could work, a more scalable and readable approach is to use an internal table defined as a constant within our class. This makes it easy to add more colors or change values later without altering the core logic.


TYPES:
  BEGIN OF ty_color_map,
    color TYPE string,
    value TYPE i,
  END OF ty_color_map,
  ty_color_map_tab TYPE STANDARD TABLE OF ty_color_map WITH EMPTY KEY.

CONSTANTS:
  gc_color_map TYPE ty_color_map_tab VALUE `(
    ( color = 'black'  value = 0 )
    ( color = 'brown'  value = 1 )
    ( color = 'red'    value = 2 )
    ( color = 'orange' value = 3 )
    ( color = 'yellow' value = 4 )
    ( color = 'green'  value = 5 )
    ( color = 'blue'   value = 6 )
    ( color = 'violet' value = 7 )
    ( color = 'grey'   value = 8 )
    ( color = 'white'  value = 9 )
  )`.

This CONSTANTS block uses a modern constructor expression to initialize the internal table, which is clean and highly readable.

Step 2: The Logic Flow Diagram

Before writing the full code, let's visualize the process from input to output. This helps clarify the steps and dependencies.

    ● Start (Input: Table of 3 Color Strings)
    │
    ▼
  ┌─────────────────────────────────┐
  │ Loop through input colors       │
  │ & Map each to an integer value  │
  │ using the color map constant.   │
  └───────────────┬─────────────────┘
                  │
                  ▼
  ┌─────────────────────────────────┐
  │ Concatenate first two values    │
  │ numerically (e.g., 3, 3 -> 33). │
  └───────────────┬─────────────────┘
                  │
                  ▼
  ┌─────────────────────────────────┐
  │ Calculate multiplier: 10 ** val3│
  └───────────────┬─────────────────┘
                  │
                  ▼
  ┌─────────────────────────────────┐
  │ Compute total Ohms:             │
  │ (base_value * multiplier)       │
  └───────────────┬─────────────────┘
                  │
                  ▼
             ◆ Ohms >= 1000?
            ╱               ╲
           Yes               No
           ╱                   ╲
          ▼                     ▼
┌──────────────────┐   ┌──────────────────┐
│ Divide by 1000   │   │ Use Ohms value   │
│ Format as        │   │ Format as "ohms" │
│ "kiloohms"       │   └──────────────────┘
└─────────┬────────┘
          │
          └────────┬──────────┘
                   ▼
    ● End (Output: Formatted String)

Step 3: Building the ABAP Class

We will create a class named ZCL_RESISTOR_COLOR_TRIO. It will have one public method, CALCULATE_VALUE, which takes the colors and returns the final string. A private helper method, GET_VALUE_FOR_COLOR, will handle the lookup logic for better code separation.

Full Class Definition and Implementation (ZCL_RESISTOR_COLOR_TRIO.abap)


CLASS zcl_resistor_color_trio DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    TYPES:
      ty_colors TYPE STANDARD TABLE OF string WITH EMPTY KEY.

    METHODS calculate_value
      IMPORTING
        it_colors         TYPE ty_colors
      RETURNING
        VALUE(rv_result)  TYPE string
      RAISING
        cx_sy_conversion_error.

  PRIVATE SECTION.
    TYPES:
      BEGIN OF ty_color_map,
        color TYPE string,
        value TYPE i,
      END OF ty_color_map,
      ty_color_map_tab TYPE STANDARD TABLE OF ty_color_map WITH EMPTY KEY.

    CONSTANTS:
      gc_color_map TYPE ty_color_map_tab VALUE `(
        ( color = 'black'  value = 0 )
        ( color = 'brown'  value = 1 )
        ( color = 'red'    value = 2 )
        ( color = 'orange' value = 3 )
        ( color = 'yellow' value = 4 )
        ( color = 'green'  value = 5 )
        ( color = 'blue'   value = 6 )
        ( color = 'violet' value = 7 )
        ( color = 'grey'   value = 8 )
        ( color = 'white'  value = 9 )
      )`.

    METHODS get_value_for_color
      IMPORTING
        iv_color          TYPE string
      RETURNING
        VALUE(rv_value)   TYPE i
      RAISING
        cx_sy_conversion_error.

ENDCLASS.

CLASS zcl_resistor_color_trio IMPLEMENTATION.

  METHOD calculate_value.
    " Ensure we have exactly three colors provided
    IF lines( it_colors ) <> 3.
      RAISE EXCEPTION TYPE cx_sy_conversion_error
        EXPORTING
          text = 'Exactly three colors are required.'.
    ENDIF.

    " Step 1: Get the integer value for each of the three colors
    DATA(lv_val1) = get_value_for_color( it_colors[ 1 ] ).
    DATA(lv_val2) = get_value_for_color( it_colors[ 2 ] ).
    DATA(lv_val3) = get_value_for_color( it_colors[ 3 ] ).

    " Step 2: Combine the first two values to form a two-digit number
    " For example, if colors are Orange (3) and Orange (3), base value is 33.
    DATA(lv_base_value) = lv_val1 * 10 + lv_val2.

    " Step 3: Calculate the total resistance in ohms
    " The third color value is the exponent for the multiplier (10^N)
    DATA(lv_total_ohms) = lv_base_value * ( 10 ** lv_val3 ).

    " Step 4: Format the output string, converting to kiloohms if necessary
    IF lv_total_ohms >= 1000.
      DATA(lv_kiloohms) = lv_total_ohms / 1000.
      rv_result = |{ lv_kiloohms } kiloohms|.
    ELSE.
      rv_result = |{ lv_total_ohms } ohms|.
    ENDIF.

  ENDMETHOD.

  METHOD get_value_for_color.
    " Helper method to look up a color's value from our constant table
    TRY.
        " Use modern table expression with line_exists to find the color
        IF line_exists( gc_color_map[ color = to_lower( iv_color ) ] ).
          rv_value = gc_color_map[ color = to_lower( iv_color ) ]-value.
        ELSE.
          " Raise an exception if the color is not found in our map
          RAISE EXCEPTION TYPE cx_sy_conversion_error
            EXPORTING
              text = |Invalid color provided: { iv_color }|.
        ENDIF.
      CATCH cx_sy_itab_line_not_found.
        " This catch block is a fallback, the line_exists should prevent it.
        RAISE EXCEPTION TYPE cx_sy_conversion_error
          EXPORTING
            text = |Invalid color provided: { iv_color }|.
    ENDTRY.
  ENDMETHOD.

ENDCLASS.

Step 4: Creating a Test Program

To see our class in action, we need a simple executable program (a report) that instantiates the class, calls the method, and displays the result. This simulates how another part of an application would consume our logic.

Executable Program (Z_TEST_RESISTOR_TRIO.abap)


REPORT z_test_resistor_trio.

" Define the input data
DATA lt_colors TYPE zcl_resistor_color_trio=>ty_colors.
lt_colors = VALUE #( ( 'Orange' ) ( 'Orange' ) ( 'Black' ) ). " Expected: 33 ohms

" Entry point of the program
START-OF-SELECTION.
  " Use a TRY-CATCH block to handle potential errors gracefully
  TRY.
      " Instantiate our class and call the calculation method
      DATA(lo_resistor_calc) = NEW zcl_resistor_color_trio( ).
      DATA(lv_result) = lo_resistor_calc->calculate_value( lt_colors ).

      " Display the successful result
      cl_demo_output=>display( lv_result ).

    CATCH cx_sy_conversion_error INTO DATA(lx_error).
      " Display the error message if something went wrong (e.g., invalid color)
      cl_demo_output=>display( lx_error->get_text( ) ).
  ENDTRY.

  " --- Another test case ---
  lt_colors = VALUE #( ( 'Blue' ) ( 'Green' ) ( 'Yellow' ) ). " Expected: 650 kiloohms
  TRY.
      DATA(lo_resistor_calc2) = NEW zcl_resistor_color_trio( ).
      DATA(lv_result2) = lo_resistor_calc2->calculate_value( lt_colors ).
      cl_demo_output=>display( lv_result2 ).
    CATCH cx_sy_conversion_error INTO DATA(lx_error2).
      cl_demo_output=>display( lx_error2->get_text( ) ).
  ENDTRY.

  " --- Error test case ---
  lt_colors = VALUE #( ( 'Blue' ) ( 'Pink' ) ( 'Yellow' ) ). " Expected: Error
  TRY.
      DATA(lo_resistor_calc3) = NEW zcl_resistor_color_trio( ).
      DATA(lv_result3) = lo_resistor_calc3->calculate_value( lt_colors ).
      cl_demo_output=>display( lv_result3 ).
    CATCH cx_sy_conversion_error INTO DATA(lx_error3).
      cl_demo_output=>display( lx_error3->get_text( ) ).
  ENDTRY.

Detailed Code Walkthrough

Let's break down the key parts of our zcl_resistor_color_trio implementation to understand the "why" behind the code.

The get_value_for_color Method

This private helper method is the heart of our data mapping. Its sole responsibility is to take a color string and return its corresponding integer value.

  1. Input Conversion: to_lower( iv_color ) is used to make the lookup case-insensitive. This is a crucial step for robustness, as the input could be "Orange", "orange", or "ORANGE".
  2. Safe Lookup: IF line_exists(...) is a modern and safe way to check if an entry exists in an internal table before trying to access it. This prevents the program from crashing with a `CX_SY_ITAB_LINE_NOT_FOUND` runtime error if an invalid color is passed.
  3. Value Retrieval: If the line exists, rv_value = gc_color_map[ ... ]-value uses a table expression to read the value directly. This syntax is concise and highly readable compared to the older READ TABLE ... INTO ... statements.
  4. Error Handling: If the color is not found, we proactively RAISE EXCEPTION TYPE cx_sy_conversion_error. This immediately stops the execution of this method and passes control to the calling method's CATCH block, providing a clear error message.

The calculate_value Method

This public method orchestrates the entire calculation process.

  1. Input Validation: The first check, IF lines( it_colors ) <> 3, is a guard clause. It ensures the input is valid before any processing begins, preventing unexpected errors later on.
  2. Value Extraction: It calls our private helper method three times to get the numerical values for the bands. This keeps the main method clean and focused on calculation rather than lookup.
  3. Base Value Calculation: DATA(lv_base_value) = lv_val1 * 10 + lv_val2 is a simple but effective mathematical trick to combine two digits. For example, if `lv_val1` is 3 and `lv_val2` is 3, this becomes `3 * 10 + 3 = 33`.
  4. Total Ohms Calculation: 10 ** lv_val3 uses the ABAP exponentiation operator (**) to calculate the multiplier. This is equivalent to `10` to the power of `lv_val3`. The result is then multiplied by the base value to get the final resistance in ohms.
  5. Output Formatting: This is where the final business logic is applied. An IF statement checks if the resistance is 1000 or more.

The Ohm-to-Kiloohm Formatting Logic

The final formatting step is critical for user-friendliness. A value like "650000 ohms" is harder to read than "650 kiloohms".

    ● Start (Input: lv_total_ohms)
    │
    ▼
  ┌────────────────────────┐
  │ IF lv_total_ohms >= 1000 │
  └────────────┬───────────┘
               │
    Yes ╱      ╲ No
       ╱        ╲
      ▼          ▼
┌────────────┐  ┌───────────────────┐
│ Calculate: │  │ rv_result =       │
│ lv_kiloohms =│  │ "{lv_total_ohms}" │
│ lv_total_ohms│  │ & " ohms"         │
│ / 1000     │  └─────────┬─────────┘
└─────┬──────┘            │
      │                   │
      ▼                   │
┌────────────┐            │
│ rv_result =│            │
│ "{lv_kiloohms}"│        │
│ & " kiloohms"│          │
└─────┬──────┘            │
      │                   │
      └─────────┬─────────┘
                ▼
    ● End (Output: rv_result)

The code uses modern string templates with the pipe character (|). The expression |{ lv_kiloohms } kiloohms| is a cleaner, more powerful alternative to the older CONCATENATE statement. It automatically handles type conversions and creates the final string in a single, readable line.


Alternative Approaches and Considerations

While our chosen solution is robust and modern, it's useful to understand alternative ways the problem could have been solved and why we avoided them.

Pros and Cons of Different Mapping Techniques

Technique Pros Cons
Internal Table Constant (Our Approach) - Highly readable and maintainable.
- Data is separate from logic.
- Easily extensible with new colors.
- Slightly more setup code than a CASE statement.
CASE Statement - Simple for a small, fixed set of values.
- No need for separate data type definitions.
- Becomes unwieldy and hard to read as the number of conditions grows.
- Mixes data (the color values) directly with procedural logic.
Customizing Table (Z-Table) - Fully dynamic; values can be changed in production without a code change.
- The "enterprise" way to handle configurable mappings.
- Overkill for this simple problem.
- Introduces a database dependency and performance overhead (DB select).

For this self-contained problem from the kodikra learning path, the internal table constant strikes the perfect balance between readability, maintainability, and simplicity.

Looking ahead, as you progress towards building applications with the ABAP RESTful Application Programming Model (RAP), the logic from our class could be easily integrated into a custom entity or a determination within a business object, demonstrating the real-world applicability of these foundational skills. You can explore our comprehensive ABAP language hub for more advanced topics.


Frequently Asked Questions (FAQ)

Why use an ABAP Objects Class instead of a simple Function Module?

Using a class (ABAP Objects) is the modern standard for new development. It offers better encapsulation (hiding implementation details with private methods), reusability, and testability using ABAP Unit. While a Function Module could solve this, classes provide a superior structure for building complex, maintainable applications.

How does the code handle invalid color inputs like "Purple"?

The get_value_for_color method is designed to be robust. It first checks if a color exists using line_exists(). If the color is not found in our predefined map, it raises a cx_sy_conversion_error exception with a descriptive message, like "Invalid color provided: Purple". The calling program can then catch this exception and handle the error gracefully.

What does the 10 ** lv_val3 syntax mean in ABAP?

The double asterisk (**) is the exponentiation operator in modern ABAP. The expression 10 ** lv_val3 calculates 10 raised to the power of the value stored in the lv_val3 variable. It is a direct and readable way to perform power calculations, which was more complex in older ABAP versions.

What are string templates and why are they used here?

String templates, denoted by pipe characters (|...|), are a modern feature for string creation. They allow you to embed variables and expressions directly within a string, like |{ lv_kiloohms } kiloohms|. The system automatically converts the variable's value to a string. This is far cleaner and more efficient than the old CONCATENATE ... INTO ... SEPARATED BY ... syntax.

Can this logic be integrated into an SAP Fiori application?

Absolutely. This class provides the backend logic. You could expose this logic as a remote-enabled Function Module (RFC) or, more modernly, as part of an OData service using SAP Gateway or the ABAP RESTful Application Programming Model (RAP). A Fiori app could then call this service to perform the calculation based on user input from a dropdown list of colors.

What is the difference between ohms and kiloohms?

"Ohm" is the standard unit of electrical resistance. "Kiloohm" is a multiple of this unit. Just like a kilometer is 1000 meters, a kiloohm is 1000 ohms. Our program automatically makes this conversion for values of 1000 ohms or greater to improve readability.

Where can I learn more ABAP fundamentals like this?

This module is part of a structured learning curriculum at kodikra.com. To build on these skills and tackle more complex challenges, you can continue your journey on the ABAP 1 learning path and explore a wide range of hands-on exercises.


Conclusion: From Colors to Clean Code

We have successfully journeyed from a real-world problem—decoding resistor colors—to a complete, modern, and robust ABAP solution. By doing so, we've touched upon a host of indispensable programming concepts: object-oriented design, data mapping, type conversion, mathematical operations, conditional logic, and robust error handling.

The Resistor Color Trio problem beautifully illustrates that the core of enterprise development isn't always about massive, complex frameworks; it's about mastering the fundamentals of data transformation. The ability to take raw input, apply business rules, and produce clean, formatted output is a skill that will serve you throughout your entire ABAP career.

The solution presented here, with its use of internal table constants, helper methods, and modern syntax, is a template for writing clean and maintainable code. As you continue your learning, remember these principles. They are the foundation upon which powerful and reliable SAP applications are built.

Disclaimer: The code and concepts in this article are based on modern ABAP syntax (ABAP 7.40 and higher), which is standard in SAP S/4HANA and recent SAP NetWeaver systems. Syntax may differ in older systems.


Published by Kodikra — Your trusted Abap learning resource.