user
Goal

Convert UPC bar codes to decimal.

Specifically:

The UPC standard is actually a collection of standards -- physical standards, data format standards, product reference standards...

Here,   in this task,   we will focus on some of the data format standards,   with an imaginary physical+electrical implementation which converts physical UPC bar codes to ASCII   (with spaces and   **#**   characters representing the presence or absence of ink).

Sample input

Below, we have a representation of ten different UPC-A bar codes read by our imaginary bar code reader:

```
         # #   # ##  #  ## #   ## ### ## ### ## #### # # # ## ##  #   #  ##  ## ###  # ##  ## ### #  # #       
        # # #   ##   ## # #### #   # ## #   ## #   ## # # # ###  # ###  ##  ## ###  # #  ### ###  # # #         
         # #    # # #  ###  #   #    # #  #   #    # # # # ## #   ## #   ## #   ##   # # #### ### ## # #         
       # # ##  ## ##  ##   #  #   #  # ###  # ##  ## # # #   ## ##  #  ### ## ## #   # #### ## #   # #        
         # # ### ## #   ## ## ###  ##  # ##   #   # ## # # ### #  ## ##  #    # ### #  ## ##  #      # #          
          # #  #   # ##  ##  #   #   #  # ##  ##  #   # # # # #### #  ##  # #### #### # #  ##  # #### # #         
         # #  #  ##  ##  # #   ## ##   # ### ## ##   # # # #  #   #   #  #  ### # #    ###  # #  #   # #        
        # # #    # ##  ##   #  # ##  ##  ### #   #  # # # ### ## ## ### ## ### ### ## #  ##  ### ## # #         
         # # ### ##   ## # # #### #   ## # #### # #### # # #   #  # ###  #    # ###  # #    # ###  # # #       
        # # # #### ##   # #### # #   ## ## ### #### # # # #  ### # ###  ###  # # ###  #    # #  ### # #         

```

Some of these were entered upside down,   and one entry has a timing error.

Task

Implement code to find the corresponding decimal representation of each, rejecting the error.

Extra credit for handling the rows entered upside down   (the other option is to reject them).

Notes

Each digit is represented by 7 bits:

```
    0:  0 0 0 1 1 0 1
    1:  0 0 1 1 0 0 1
    2:  0 0 1 0 0 1 1
    3:  0 1 1 1 1 0 1
    4:  0 1 0 0 0 1 1
    5:  0 1 1 0 0 0 1
    6:  0 1 0 1 1 1 1
    7:  0 1 1 1 0 1 1
    8:  0 1 1 0 1 1 1
    9:  0 0 0 1 0 1 1

```

On the left hand side of the bar code a space represents a **0** and a **#** represents a **1**.
  
On the right hand side of the bar code, a **#** represents a **0** and a space represents a **1**
  
Alternatively (for the above):   spaces always represent zeros and **#** characters always represent ones, but the representation is logically negated -- **1**s and **0**s are flipped -- on the right hand side of the bar code.

The UPC-A bar code structure
:   :   * It begins with at least 9 spaces   (which our imaginary bar code reader unfortunately doesn't always reproduce properly),
        * then has a      **# #**      sequence marking the start of the sequence,
        * then has the six "left hand" digits,
        * then has a    **# #**    sequence in the middle,
        * then has the six "right hand digits",
        * then has another    **# #**    (end sequence),   and finally,
        * then ends with nine trailing spaces   (which might be eaten by wiki edits, and in any event, were not quite captured correctly by our imaginary bar code reader).

Finally, the last digit is a checksum digit which may be used to help detect errors.

Verification

Multiply each digit in the represented 12 digit sequence by the corresponding number in   (3,1,3,1,3,1,3,1,3,1,3,1)   and add the products.

The sum (mod 10) must be **0**   (must have a zero as its last digit)   if the UPC number has been read correctly.
assistant
(formerly Perl 6)

```
sub decode_UPC ( Str $line ) {
    constant @patterns1 = '   ## #', '  ##  #', '  #  ##', ' #### #', ' #   ##',
                          ' ##   #', ' # ####', ' ### ##', ' ## ###', '   # ##';
    constant @patterns2 = @patterns1».trans( '#' => ' ', ' ' => '#' );

    constant %pattern_to_digit_1 = @patterns1.antipairs;
    constant %pattern_to_digit_2 = @patterns2.antipairs;

    constant $re = / ^  '# #'  (@patterns1) ** 6
                       ' # # ' (@patterns2) ** 6
                        '# #'                     $ /;

    $line.trim ~~ $re
        orelse return;

    my @digits = flat %pattern_to_digit_1{ $0».Str },
                      %pattern_to_digit_2{ $1».Str };

    return unless ( @digits Z* ( |(3,1) xx * ) ).sum %% 10;

    return @digits.join;
}

my @lines =
    '         # #   # ##  #  ## #   ## ### ## ### ## #### # # # ## ##  #   #  ##  ## ###  # ##  ## ### #  # #       ',
     '        # # #   ##   ## # #### #   # ## #   ## #   ## # # # ###  # ###  ##  ## ###  # #  ### ###  # # #      ',
    '         # #    # # #  ###  #   #    # #  #   #    # # # # ## #   ## #   ## #   ##   # # #### ### ## # #       ',
      '       # # ##  ## ##  ##   #  #   #  # ###  # ##  ## # # #   ## ##  #  ### ## ## #   # #### ## #   # #        ',
    '         # # ### ## #   ## ## ###  ##  # ##   #   # ## # # ### #  ## ##  #    # ### #  ## ##  #      # #       ',
   '          # #  #   # ##  ##  #   #   #  # ##  ##  #   # # # # #### #  ##  # #### #### # #  ##  # #### # #    ',
    '         # #  #  ##  ##  # #   ## ##   # ### ## ##   # # # #  #   #   #  #  ### # #    ###  # #  #   # #     ',
     '        # # #    # ##  ##   #  # ##  ##  ### #   #  # # # ### ## ## ### ## ### ### ## #  ##  ### ## # #      ',
    '         # # ### ##   ## # # #### #   ## # #### # #### # # #   #  # ###  #    # ###  # #    # ###  # # #       ',
     '        # # # #### ##   # #### # #   ## ## ### #### # # # #  ### # ###  ###  # # ###  #    # #  ### # #      ',
;
for @lines -> $line {
    say decode_UPC($line)
     // decode_UPC($line.flip)
     // 'Invalid';
}

```

Output:

```
924773271019
403944441050
834999676706
939825158811
Invalid
316313718717
214575875608
818778841813
706466743030
653483540435
```