2

I need to create a function that takes a 13 digit sequence and uses the last number as a check using modulo 10. ie BAF189D234EA2 entry check = 2.

Using the values of A-F (see weight dict below) instead of ord(char). So as my loop iterates I need char to pull the corresponding weight dict if it is a string value. I simply cannot figure out how to make it call from that dictionary based on the value of char.

Thanks in advance for any help.

weight={
'A' : '10',
'B' : '11',
'C' : '12',
'D' : '13',
'E' : '14',
'F' : '15',
}

def validater(value):
    global userEntry
    valSum = 0
    i = 0
    for char in userEntry:
        if i == 12:
            break
        try:
            if char >=0 and char <= 9:
                valSum += char * i
                i +=1
        except TypeError:  
            valSum += weight[char] * i
            i += 1

Error:

Traceback (most recent call last):
    line 93, in <module>
    if validater(userEntry) ==True:
    line 74, in validater
    valSum += weight[char] * i
TypeError: unsupported operand type(s) for +=: 'int' and 'str'

Edit: Thanks, I changed the dictionary by dropping the quotes around my ints. Now I get a Key Error 1

  • What exactly does your code do wrong? If you're getting an exception, edit the full traceback into the question. If it's providing incorrect results, provide sample input, actual output, and expected output. – glibdud Oct 05 '18 at 19:27
  • Sorry about that. I edited the post to include the traceback I get. – Joseph Nolan Oct 05 '18 at 19:31
  • 1
    Your dictionary values are string. If you want an int it would be `'A' : 10,` – BigGerman Oct 05 '18 at 19:32
  • I don't understand your question, but you could just change your entire dictionary into parsing in base 16 - `int(char, 16)` would return 10 for A etc. – Sayse Oct 05 '18 at 19:35
  • As suggested earlier either change values in dict or while performing the mathematical operation – mad_ Oct 05 '18 at 19:35
  • Thanks I changed my dictionary to your suggestion BigGerman. Now I get KeyError: '1' – Joseph Nolan Oct 05 '18 at 19:39
  • That's because '1' is not a key in the dictionary. You will need to except the KeyError. – BigGerman Oct 05 '18 at 19:47

3 Answers3

2

Short version:

>>> is_ok = lambda x: sum(i * int(c, 16) for i, c in enumerate(x[:-1])) % 10 == int(x[-1], 16)
>>> is_ok('BAF189D234EA2')
True
>>> is_ok('BAF189D234EA3')
False

When using the build-in int() you can specify a base. Looking at this answer, you can convert you chars directly.

>>> int('a', 16)
10
>>> int('1a', 16)
26

So try this code:

def validate(value):
    assert len(value) == 13

    value_sum = sum(
        int(c, 16) * i
        for i, c in enumerate(value[:-1]))

    last_digit = int(value[-1], 16)

    assert value_sum % 10 == last_digit

I get the correct result when testing with your example:

>>> validate('BAF189D234EA2')

And it fails with an assertion error when I change a char:

>>> validate('BAF189D234EA3')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 10, in validate
AssertionError

Also raises error when input is not 13 chars long

>>> validate('BAF189D234EA23')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 2, in validate
AssertionError
Ralf
  • 16,086
  • 4
  • 44
  • 68
  • Thank you for your answer. The int(char, 16) worked. I appreciate your help – Joseph Nolan Oct 05 '18 at 19:51
  • @JosephNolan I improved my answer; it should cover your use case now, but with less code than you have. – Ralf Oct 05 '18 at 20:01
  • Thanks for your response. This is a nice piece of code here. I'm a PhD student (geology) taking entry-level coding classes to make software for something I research (since nothing exists). As this is a freshman level class it might send up a red flag if I use something that advanced. – Joseph Nolan Oct 06 '18 at 16:36
2

Your error is due to your dictionary values all being strings instead of integers, so changing them to integers would solve your issues, but since all you're mapping is hexadecimal numbers to base 10, you may as well just do the conversion yourself

valSum += int(char, 16) * i
Sayse
  • 42,633
  • 14
  • 77
  • 146
1

1) remove quotation from weights

2) cast char as int, right after try

3) the remainder from division (modulo) is % btw

Serge
  • 3,387
  • 3
  • 16
  • 34