0

I was doing some practice tasks from NiO for an upcoming coding competition. The competition is held online and forces me to use stdin.readline so they can test my code. The usage of stdin got me really stuck. The script is running flawlessly with raw_input but throws "ValueError: substring not found" whenever I switch to sys.stdin.readline. Am I doing something stupidly wrong?

import string
import sys

n = int(sys.stdin.readline())
txt = sys.stdin.readline()
ab = string.ascii_uppercase
result = ""

for letter in txt:
    result += ab[((ab.index(letter) + n) % 26)]

print result
4
  • How are you calling it and what are you typing on the command line after for input? Where is the error exactly? Please post a textual screen dump in your question. Commented Dec 21, 2016 at 20:59
  • readline() includes the newline at the end of the string. There's no newline in ab, so ab.index(letter) fails when you get to the last character. Commented Dec 21, 2016 at 21:00
  • Your code will get that error if any of the input isn't an uppercase letter. Commented Dec 21, 2016 at 21:01
  • It is customary to select the answer that you found most helpful by clicking on the check mark next to it. Commented Dec 22, 2016 at 7:35

2 Answers 2

2

readline() will return the entire line, including the newline character at the end. Since \n isn't present in ascii_uppercase, you're getting the error.

Use txt = sys.stdin.readline().strip() and the error should go away.

Sign up to request clarification or add additional context in comments.

3 Comments

More generally: txt = [x.upper() for x in sys.stdin.readline() if x.isalpha()] might be a better approach. Alternatively, you could put the isalpha and upper calls in the loop.
I think I'm gonna make that an answer.
Yep, it did. Thank you so much!
1

The fundamental flaw with your code is that you do not sanitize your input and you are getting an illegal character (\n) at the end. The operation ab.index(...) assumes that all inputs are uppercase letters, so it fails when they are not.

You can fix this in a couple of ways. One is to convert everything that can be converted to uppercase to uppercase and leave the rest in as-is:

import string, sys

ab = string.ascii_uppercase
n = int(sys.stdin.readline())
txt = sys.stdin.readline()
result = [ab[(ab.index(letter.upper()) % n) % 26] for letter in txt if letter.isalpha() else letter]

Alternatively, you can just throw away all the non-uppercase inputs:

import string, sys

ab = string.ascii_uppercase
n = int(sys.stdin.readline())
txt = sys.stdin.readline()
result = [ab[(ab.index(letter) % n) % 26] for letter in txt if letter.isupper()]

There are any number of combinations of these methods you could use.

By the way, if you are interested in having a prompt for your input, use print with end='':

print('How far to shift? ', end='')
n = int(sys.stdin.readline())
print('Text to encode? ', end='')
txt = sys.stdin.readline()
...

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.