0

This code is a preview from an upcoming competition at picoctf.com. I modified the original code provided so it allows for user input, but I can't get Test #2 to work. When a string of 10 characters is entered with at least one letter, I want it to print that only numbers may be used. Currently it tries to convert the user input to an integer value to compare it to the actual serial, but if there is a letter present the test fails since a letter can't be converted to a integer value:

123456789a yields "invalid literal for int() with base 10..."

How can I fix this piece of code so that it tests correctly?

**

if int(serial) != serial:
            print ("only numbers allowed")
            print ('Failed Test 2')

**

#!/usr/bin/env python
# Your goal is to find the input that will verify your robot's serial number
#solution to keep it handy = 0933427186

serial = input ("Please enter a valid serial number from your RoboCorpIntergalactic purchase")

def check_serial(serial):
    if len(serial) != 10:
        print ('Failed Test 1')
        return False
    if int(serial) != serial:
        print ("only numbers allowed")
        print ('Failed Test 2')
        return False
    if int(serial[0])+int(serial[1]) != 9:
        print ('Failed Test 3')
        return False
    if int(serial[2])*int(serial[3]) != 9:
        print ('Failed Test 4')
        return False
    if int(serial[4])-int(serial[5]) != 2:
        print ('Failed Test 5')
        return False
    if int(serial[5])%int(serial[4]) != 2:
        print ('Failed Test 6')
        return False
    if int(serial[6])/int(serial[7]) != 7:
        print ('Failed Test 7')
        return False
    if int(serial[8])-int(serial[9]) != 2:
        print ('Failed Test 8')
        return False
    if int(serial[7])*int(serial[1]) != 9:
        print ('Failed Test 9')
        return False
    if int(serial[2]) + int(serial[3]) != int(serial[9]):
        print ('Failed Test 10')
        return False
    return True

if check_serial(serial):
    print ("Thank you! Your product has been verified!")
else:
    print ("I'm sorry that is incorrect. Please use a valid RoboCorpIntergalactic serial number")
2
  • Note that int(somestring) == somestring will always be false, even if it is all digits. Commented Mar 21, 2013 at 12:58
  • Ahh. That makes sense and explains why I was having problems with ten digit solutions! Thanks! Commented Mar 21, 2013 at 13:59

3 Answers 3

5

Use str.isdigit() to test if all characters are digits:

>>> 'a1'.isdigit()
False
>>> '11'.isdigit()
True
>>> '1a'.isdigit()
False

You may want to turn your serial string into a sequence of integers to make all your tests easier:

s_int = [int(d) for d in serial]

then

if s_int[0] + s_int[1] != 9:

etc.

You could easily build a sequence of tests with indices, an operator and the expected outcome:

import operator

tests = (
    (0, 1, operator.add, 9),
    (2, 3, operator.mul, 9),
    (4, 5, operator.sub, 2),
    (5, 4, operator.mod, 2),
    (6, 7, operator.truediv, 7),
    (8, 9, operator.sub, 2),
    (7, 1, operator.mul, 9),
)

for i, (a, b, op, res) in enumerate(tests, 3):
    if op(s_int[a], s_int[b]) != res:
        print("Failed test {}".format(i))
        return False
Sign up to request clarification or add additional context in comments.

4 Comments

The part with operator is so beautiful! :)
Thanks everyone for your ideas. For now I just went with: if str.isdigit(serial) == False: print ('only numbers allowed') print ('Failed Test 2') return False I will investigate your ideas further. I am a total n00b to both Python and programming in general! Thanks again!
I am guessing that serial.isdigit() is preferred over str.isdigit(serial) though both seem to work okay for me? Or does it not matter?
@jkibbe: I meant for you to use serial.isdigit(). str.isdigit(serial) happens to work because it is an unbound method of the str class. :-)
1
try:
    int(serial)
except ValueError:
    print ("only numbers allowed")
    print ('Failed Test 2')

or following Martijn's suggestion

try:
    s_int = [int(d) for d in serial]
except ValueError:
    s_int = None
    print ("only numbers allowed")
    print ('Failed Test 2')

2 Comments

This'll succeed if serial contains leading or trailing whitespace. int() is quite tolerant.
@MartijnPieters, would also allow negative numbers :) My second suggestion wouldn't though
1

Use str.isdigit()

Return true if all characters in the string are digits and there is at least one character, false otherwise.

You could use a regular expression as well:

import re;
if(re.match('\D', serial)):
    print ('Failed Test 2')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.