#include <array>
#include <iostream>
#include <iomanip>
#include <map>
#include <string>

std::string to_bar_code(unsigned int zip_code)
{
    const std::array<std::string, 10> digit {{
        "11000", "00011", "00101", "00110", "01001",
        "01010", "01100", "10001", "10010", "10100"
    }};
    return "1"
        + digit[(zip_code / 10000) % 10]
        + digit[(zip_code / 1000) % 10]
        + digit[(zip_code / 100) % 10]
        + digit[(zip_code / 10) % 10]
        + digit[zip_code % 10]
        + "1";
}

int to_zip_code(const std::string& bar_code)
{
    const std::map<std::string, int> digits = {
        {"11000", 0}, // special case
        {"00011", 1},
        {"00101", 2},
        {"00110", 3},
        {"01001", 4},
        {"01010", 5},
        {"01100", 6},
        {"10001", 7},
        {"10010", 8},
        {"10100", 9}
    };
    const std::string bar_digits[5]{ {bar_code, 1, 5}, {bar_code, 6, 5}, {bar_code, 11, 5}, {bar_code, 16, 5}, {bar_code, 21, 5} };
    unsigned int res = 0;
    for (const auto& d : bar_digits)
    {
        res *= 10;
        res += digits.at(d);
    }
    return res;
}


int main()
{
    std::cout << "Digits" << "       " << "Bar Code" << std::endl;
    for (const auto zip : {99504, 12345, 67890}) {
        std::cout << zip << std::setw(35) << to_bar_code(zip) << std::endl;
    }
    std::cout << "Digits" << "       " << "Bar Code" << std::endl;
    for (const auto bar : {"110100101000101011000010011", "100101010011100001100110001", "110100001011100001100010011", "100011000110101000011100101"}) {
        std::cout << to_zip_code(bar) << std::setw(35) << bar << std::endl;
    }    
}
