2nd Assignment - Bugging Out (Sorry for repeat)

Hey all. First off: not looking for answers as this is for a Uni assignment. I’m wondering if somebody can point me in the right direction. The following program is supposed to:

  1. accept a user input
  2. determine if that user input is a valid basic code, positional code, or upc code, based on:

Basic Code :

  • Add all digits (except the last one) together
  • compute sum % 10 (between 0-9)
  • add that digit (from step 2) to the end of the digit. If that last digit is correct ,the number is a valid Basic Code.

ie. for 434135:
4 + 3 + 4 + 1 + 3 = 15
15 % 5 = 5

Last digit of the number is a “5”, so the number is a valid Basic Code.

Positional Code :

  • Compute the sum by multiplying each digit (except the last one) by it’s position in the string
  • Compute the result % 10
  • Add that number to the end of the digit

ie. 434135:
(4 * 1) + (3 * 2) + (4 * 3) + (1 * 4) + (3 * 5) = 41
41 % 10 = 1

Last digit of the number is not 1, so this code is not a valid positional code

UPC :

  • multiply each odd digit by 3 and each even digit by 1 and add together
  • compute the result % 10
  • If resulting number is a 0, add it to the end. If the resulting number is 1-9, subtract that number from 10 to get the final digit.

ie. 434135:

(4 * 1) + (3 * 3) + (4 * 1) + (1 * 3) + (3 * 3) = 29
29 % 10 = 9
10 - 9 = 1

Last digit is not a 1, therefore this is not a valid UPC code.

We have to create two separate programs. The first one houses our functions and the second one is the main program that calls the functions. I’m not sure what I’m doing wrong, but every number I enter (regardless of whether or not it should be a valid Basic Number, Positional Number, or UPC Number) is ending up in the “invalid” list and printing out with “None:” instead. Any advice?

first file (contains functions):

''' This program contains the functions needed for assign2.py. These functions
check to see if an inputted code is a valid basic code, positional code, or UPC
code. '''

# basicCode function takes input, converts to integer, and adds all digits together
# before determining if the check digit is valid.

def basicCode(code) :
  inputList = list(map(int, code.strip()))
  total = sum(inputList) 
  checkDigit = total % 10
  finalDigit = code[-1]
  if checkDigit == finalDigit :
   return True

# positionalCode function takes input, converts to integer, and multiplies
# each digit by its position and adds the result to the total sum before
# determining if the check digit is valid.

def positionalCode(code) :
    inputList = list(map(int, code.strip()))
    for i in range (0, len(inputList)) :
      total = 0
      total +=(i + 1) * inputList[i]
      checkDigit = total % 10
      finalDigit = code[-1]
    if checkDigit == finalDigit :
        return True

# UPC function takes input, converts to integer, and multiplies each odd digit by
# 3 and leaves each even digit alone (multiplies by 1). It then subtracts any
# numbers between 1-9 from 10 to determine the checkDigit or (if the number is 0)
# determines that the checkDigit is 0. The function then verifies the code.
                    
def UPC(code) :
    total = 0
    inputList = list(map(int, code.strip()))
    for i in range (0, len(inputList)) :
      if i % 2 == 0 :
        total = total + (3 * inputList[i])
      else :
        total += inputList[i]
      checkDigit = total % 10
      if checkDigit == 0 :
        checkDigit = 10 - checkDigit
        finalDigit = code[-1]
        if checkDigit == finalDigit :
          return True

Second code (main program):

from check_code import *

inputList =[]
basic = []
positional = []
upc = []
invalid = []

while True :
    code = input("Please enter a code. To exit, enter 0. ")
    if code == "0" :
        break
    inputList.append(code)
    for c in inputList :
        if basicCode(c) == True :
            print("--code: " + c + "valid Basic code.")
            basic.append(c)
        if positionalCode(c) == True :
            print("--code: " + c + "valid Position code.")
            positional.append(c)
        if UPC(c) == True :
            print("--code: " + c + "valid UPC code.")
            upc.append(c)
        if not basicCode == True and not positionalCode == True and not UPC == True :
            print("--code: " + c + "not Basic, Position or UPC code.")
            invalid.append(c)

print("Summary")
print("Basic :" + ", ".join(basic))
print("Position :" + ", ".join(positional))
print("UPC :" + ", ".join(upc))
print("None :" + ", ".join(invalid))

in basicCode, it looks like you are summing all the digits, not all the digits prior to the last one.

Also, your finalDigit is pulled from code (which is a string) instead of inputList (which is a list of ints). Therefore when you compare checkDigit to finalDigit, you are comparing an int to a str, which will never be true.

I think you may have repeated that in other functions.

Thanks Bowl. I started off with the input being a string but changed it later to an int, so had a few pieces of unnecessary code in the functions. I’ve changed the basicCode function to:

def basicCode(code) :
  inputList = list(code)
  total = sum(inputList) 
  checkDigit = total % 10
  finalDigit = inputList[-1]
  if checkDigit == finalDigit :
   return True

Now I’m working on figuring out how to add all the digits without the final one. Any other suggestions about the new code. I think I have an error in inputList = list(code) now.

If they’re in a list, then sum the slice of the list that excludes the final element.
sum(inputList[:-1])

Is code still a string? If so, there was nothing wrong with the previous conversion. You said something might be wrong with the current statement, but not what you wanted to accomplish. If code is a string, then inputList will be a list of the characters of that string. Is that what you want?

You should also take a look at the last if in your program. It’s not doing what you think it’s doing.

Hey everyone! Thanks so much for the input. I ended up figuring it out and have submitted it. With that said, one thing just … kind of worked. Without me knowing why, so hoping somebody can clarify for me. In this function:

def UPC(code):
    digit = 0
    
    finalDigit = 10 - (code % 10) # Determine last digit
    
    code = code // 10 # Remove last digit

    isOdd = True # Variable set to determine if digit is Even or Odd
    while code != 0 :
      if isEven :
          digit += ((code % 10) * 3)
      else :          
          digit += (code % 10)
          
      code = code // 10
      isOdd  = not(isOdd)
    
    if (digit % 10) == finalDigit :
        return True
    else :
        return False

I’m kind of confused as to how the isOdd = True bit works. Again: it works, so I’m not complaining, but I thought I’d have to use a more elaborate if isOdd % 2 == 0 : ... statement, but it wasn’t necessary.

Can anybody explain to me how it worked without me having to put an if statement in?

Thanks,
Ryan

The code that you’ve posted isn’t valid. isEven isn’t assigned, so when it is examined in the first line of the while loop, you’ll get a NameError.

NameError: name 'isEven' is not defined

As you mention, isOdd isn’t being used. Do you have some examples of valid UPC codes that should pass? The function above will not run though.

My apologies, the correct code is:

# Create function to determine if input meets UPC Code criteria
def UPC(code):
    digit = 0
    
    finalDigit = 10 - (code % 10) # Determine last digit
    
    code = code // 10 # Remove last digit

    isOdd = True # Variable set to determine if digit is Even or Odd
    while code != 0 :
      if isOdd :
          digit += ((code % 10) * 3)
      else :          
          digit += (code % 10)
          
      code = code // 10
      isOdd  = not(isOdd)
    
    if (digit % 10) == finalDigit :
        return True
    else :
        return False

I had originally had isEven = True and changed it to isOdd. Forgot to change the code within the While loop.

isOdd is set to True initially, so the if isOdd: follows the branch.

Later you have isOdd = not(isOdd). That sets it to False. Next time through the else branch is followed.

This flips back and forth each time. Since odd/even flip back with each loop, this matches the state of isOdd.

Two comments:
If you find yourself doing an “if” to just return True or False, you can probably simplify it. Just return the statement itself. In your case you can replace

    if (digit % 10) == finalDigit :
        return True
    else :
        return False

with

    return digit % 10 == finalDigit

The other issue is that by changing the code to operate on integers instead of strings, you may have an issue of not being able to handle leading zeros. 036000291452 is a valid UPC code, but your function cannot decode it. That may or may not be a problem for your purposes.