IndexError: string index out of range python problem - python

I'm working on a game that called 'i will guess the name ur thinking of ' or 'guess my name'.
The user will enter a letter and the program will try to guess what position of it by using a "for loop" in python:
list_of_names = [ ]
userinput_letter = input('QUESTION : write a letter the name has: ')
new_list_of_names = [ ]
for names in list_of_names :
if userinput_letter in list_of_names :
new_list_of_names.append(names)
randomname = random.choice(new_list_of_names]
position_of_userletter = randomname.find(userinput_letter)
yn = input('QUESTION : does this letter "'+ userinput_letter +'" in the position "'+ str(position_of_userletter ) +'" (yes/no): ' )
if (yn == 'yes') :
newlist_ofnames = [ ]
for namesyes in new_list_of_names:
if ( namesyes in userinput_letter [position_of_userletter] ) :
newlist_ofnames.append(namesyes)
print(newlist_ofnames)
IndexError: string index out of range

As far as I understand userinput_letter is just one letter and you are trying to get some index in it. That's why you are getting error.
You should do smth like
if (len(namesyes) => position_of_userletter and namesyes[position_of_userletter] == userinput_letter):

First of all on line 5 you should have placed names instead of list_of_names.
Secondly you should place a loop that would re-run random choice if yn is equal to 'no'.
Then instead of this line:
if ( namesyes in userinput_letter [position_of_userletter] ) :
place this line:
if (namesyes[postition_of_userletter]== userinput_letter):
Hope it works :)

Related

Python How to scan for a certain letter in a input

So, I'm making some code that I want it to do a if statement that looks through the input and if it sees a certain character will then go print a message.
password = input("password: ")
if(password == "scan for a certain letter or something"):
print("Please use don't use these smybols: / \ ; : , . > < ? ! # # $ % ^ & * ( ) [ ] { } | ")
it dosen't have to be a if statement if that is what it turns out to be, I just want to know how to do it.
You can use the in operator with the any() function:
prohibited = set("/ \ ; : , . > < ? ! # # $ % ^ & * ( ) [ ] { } | ]".split())
password = input("password: ")
if any(char in prohibited for char in password):
print(f"Please use don't use these symbols: {prohibited}")
I think it will be more convenient for the user to get an exhaustive list of invalid characters used by him so that he can correct the input:
unacceptable_symbols = r"/\;:,.><?!##$%^&*()[]{}| "
password = r"f;kjad%9203)29e2" # test string
lst = [x for x in password if x in unacceptable_symbols] # makes list of all used unacceptable symbols
if len(lst) > 0:
print("You have used the following unacceptable characters: " + ' '.join(lst))
print("Please don't use these symbols: " + ' '.join(list(unacceptable_symbols)))
# Output:
# You have used the following unacceptable characters: ; % )
# Please don't use these symbols: / \ ; : , . > < ? ! # # $ % ^ & * ( ) [ ] { } |
I have tried to implement this code with very simple logic. And its working perfectly.
s="/ ; : , . > < ? ! # # $ % ^ & * ( ) [ ] { } | \ "
s1=s.split()
s3=input("enter the string: ")
for i in s3:
if(i in s1):
print("please dont use the given symbol:",i)

Python Unsupported operator type for & error handling

I'm trying to do an if statement using rows of a dataframe. Sometimes, the value can be None, and this is what I am wanting to check for.
for row in tqdm(df.index):
add = df.loc[row, "add"]
name = df.loc[row, "name"]
if str(add) is not None and str(name) is not None:
add_name = add + " " + name
elif str(add) is not None:
add_name = add
elif str(name) is not None:
add_name = name
add_names.append(add_name)
As you can see above, if neither of the values are None, then I want to concatenate. If either is None, then I want to use the other value.
However, I keep getting this error:
TypeError: unsupported operand type(s) for &: 'NoneType' and 'str'
I can't figure out how to solve this. I thought by trying to cast to a str this would work but sadly not.
EDIT:
This is a sample DF I am testing with:
df = pd.DataFrame(
{
"name": [
"Random Name",
"Another Name"
],
"add": [
None,
"Pre text"
]
}
)
I am expecting the new field to be:
Random Name
Pre text Another Name
Sample:
df = pd.DataFrame(
{
"name": [
"Random Name",
"Another Name",
None,
],
"add": [
None,
"Pre text",
'something'
]
}
)
First replace missing values use Series.fillna, join by + and last add Series.str.strip for remove traling whitespaces :
df['add_name'] = (df['add'].fillna('') + ' ' + df['name'].fillna('')).str.strip()
print (df)
name add add_name
0 Random Name None Random Name
1 Another Name Pre text Pre text Another Name
2 None something something
Another solution in numpy.where with Series.fillna by empty string if match both masks and join by space or replace missing values by another column:
df['add_name'] = np.where(df['add'].notna() & df['name'].notna(),
df['add'].fillna('') + ' ' + df['name'].fillna(''),
df['add'].fillna(df['name']))
print (df)
name add add_name
0 Random Name None Random Name
1 Another Name Pre text Pre text Another Name
2 None something something
If need test more masks, e.g. also misisng values (by invert mask by ~) is possible use numpy.select:
df = pd.DataFrame(
{
"name": [
"Random Name",
"Another Name",
None,
None
],
"add": [
None,
"Pre text",
'something',
None
]
}
)
m1 = df['add'].notna()
m2 = df['name'].notna()
s1 = df['add'].fillna('') + ' ' + df['name'].fillna('')
s2 = df['add'].fillna(df['name'])
df['add_name'] = np.select([m1 & m2,
m1 & ~m2,
~m1 & m2],
[s1, df['add'], df['name']], default=None)
print (df)
name add add_name
0 Random Name None Random Name
1 Another Name Pre text Pre text Another Name
2 None something something
3 None None None
You can use numpy.where, as the following:
import numpy as np
df['Random Name'] = np.where( (df['name'].notnull()) & (df['add'].notnull()),df['name'].astype(str)+ " " + df['add'].astype(str),
np.where(df['name'].notnull(),df['name'],df['add']))
Which gives:
Out[188]:
name add Random Name
0 Random Name None Random Name
1 Another Name Pre text Another Name Pre text
We are basically checking whether both columns are notnull, and putting them together if that's the case, and then checking if individually the columns are null, and returning the other.

I have a hw question that I cant find the error to as I am able to print. Someone able to assist me?

data = [
['Video A','500'],
['Video B','300'],
['Video C','1000']
]
result = 0
for index in data:
title = index[0]
views = index[1]
if title == 'Video' :
result += views
print(result)
When I run print I keep getting 0. Answer should be 1800. Problem is there's no error and I can't find the part where I made a mistake.
seems like you want to check if the title Starts with "Video".
also, your views are a string and need to be cast to an integer.
try this:
data = [
['Video A', '500'],
['Video B', '300'],
['Video C', '1000']
]
result = 0
for index in data:
title = index[0]
views = index[1]
if title.startswith('Video'):
result += int(views)
print(result)
Right code:
data = [
['Video A','500'],
['Video B','300'],
['Video C','1000']
]
result = 0
for index in data:
title = index[0]
views = index[1]
#you can use
#if title[:len("Video")] == 'Video':
#or
#if title.startswith('Video'):
result += int(views)
print(result)
You can also use split :
data =
['Video A','500'],
['Video B','300'],
['Video C','1000']
]
result = 0
for index in data:
title = index[0]
views = index[1]
if title.split(' ',1)[0] == 'Video' :
result += int(views)
print(result)
It allows you to ensure that there's a space after the 'Video', and also to have access to the rest of the name:
v = "Video A and B"
l = v.split(" ",1)
l[0] # 'Video'
l[1] # 'A and B'

Extracting the values within the square braces

I have a file testfile with the set of server names as below.
app-server-l11[2-5].test.com
server-l34[5-8].test.com
dd-server-l[2-4].test.com
Can you please help in getting output to be as follow.
app-server-l112.test.com
app-server-l113.test.com
app-server-l114.test.com
app-server-l115.test.com
server-l345.test.com
server-l346.test.com
server-l347.test.com
server-l348.test.com
dd-server-l2.test.com
dd-server-l3.test.com
dd-server-l4.test.com
With GNU awk for the 3rd arg to match():
$ awk 'match($0,/(.*)\[([0-9]+)-([0-9]+)\](.*)/,a){for (i=a[2]; i<=a[3]; i++) print a[1] i a[4]}' file
app-server-l112.test.com
app-server-l113.test.com
app-server-l114.test.com
app-server-l115.test.com
server-l345.test.com
server-l346.test.com
server-l347.test.com
server-l348.test.com
dd-server-l2.test.com
dd-server-l3.test.com
dd-server-l4.test.com
In GNU awk:
$ awk -F"[][]" '{split($2,a,"-"); for(i=a[1];i<=a[2];i++) print $1 i $3}' file
app-server-l112.test.com
app-server-l113.test.com
app-server-l114.test.com
app-server-l115.test.com
server-l345.test.com
server-l346.test.com
server-l347.test.com
server-l348.test.com
dd-server-l2.test.com
dd-server-l3.test.com
dd-server-l4.test.com
split to fields by [ and ] using FS
use split the get the range start (a[1]) and end (a[2])
iterate the range with for and output
There is no checking whether there was a range or not. It could be implemented with something like: print (NF==3 ? $1 i $3 : $1 ).
Worst and ugliest example:
var='app-server-l11[2-5].test.com'
for i in range(int(var[(var.find('[') +1)]), int(var[(var.find("]") - 1)])+1):
print 'app-server-l11' + str(i) + '.test.com'
Use your imagination!
ser_nm = ['app-server-l11[2-5].test.com','server-134[5-8].test.com','dd-server-[2-4].test.com']
for nm in ser_nm:
for i in range(int(nm[nm.find('[')+1 : nm.find('-',(nm.find('[')+1))]), int(nm[nm.find('-',(nm.find('[')+1))+1:nm.find(']') ] )+1):
print(nm[:nm.find('[')] + str(i) + nm[nm.find(']')+1:])
This will also take care of cases where server names are like this:
'server-134[52-823].test.com'
not the best solution, but it works...
inp = open('input.txt', 'r+').read()
print(inp)
result= ''
for i in inp.split('\n'):
if len(i) > 1:
print(repr(i))
f1 = i.find('[')
f2 = i.find(']')+1
b1 = i[:f1]
b2 = i[f2:]
ins = i[f1:f2]
ins = ins[1:-1]
for j in range(int(ins.split("-")[0]),int(ins.split("-")[1])+1):
result+=b1+str(j)+b2+'\n'
outp = open('output.txt', 'w')
outp.write(result)
outp.close()
You can use the below command for the required output without any complex statement.
awk -f test.awk file.txt
test.awk must contains the below lines:
{
if(a=match($0,"\\["))
{
start=strtonum(substr($0,a+1,1));
end=strtonum(substr($0,a+3,1));
copy=$0;
for(i=start;i<=end;i++)
{
sub("\\[[0-9]{1,}-[0-9]{1,}\\]",i,copy);
print copy;
copy = $0;
}
}
else
{
print $0;
}
}
file.txt contains your input file like below lines:
app-server-l11[2-5].test.com
server-l34[5-8].test.com
dd-server-l[2-4].test.com
output:
app-server-l112.test.com
app-server-l113.test.com
app-server-l114.test.com
app-server-l115.test.com
server-l345.test.com
server-l346.test.com
server-l347.test.com
server-l348.test.com
dd-server-l2.test.com
dd-server-l3.test.com
dd-server-l4.test.com
As this sounds like a school assignment I'm going to be fairly vague.
I would use a regular expression to extract the numeric range and the rest of the address components, then use a loop to iterate over the extracted numeric range to build each address (using the other captured address components).
Since it's been over a week:
import re
inputs = [ "app-server-l11[2-5].test.com", "server-l34[5-8].test.com", "dd-server-l[2-4].test.com" ]
pattern = r"\s*(?P<subdomain>[a-zA-Z0-9-_.]+)\[(?P<range_start>\d+)-(?P<range_end>\d+)\](?P<domain>\S+)"
expr = re.compile( pattern )
def expand_domain( domain ):
mo = expr.match( domain )
if mo is not None:
groups = mo.groupdict()
subdomain = groups[ "subdomain" ]
domain = groups[ "domain" ]
range_start = int( groups[ "range_start" ] )
range_end = int( groups[ "range_end" ] )
result = [ "{}{:d}{}".format( subdomain, index, domain ) for index in range( range_start, range_end + 1 ) ]
return result
else:
raise ValueError( "'{}' does not match the expected input.".format( domain ) )
for domain in inputs:
print( "'{}':".format( domain ) )
for exp_dom in expand_domain( domain ):
print( "--> {}".format( exp_dom ) )

List doesnt hold values inside and clear

I am creating to school SAS (internet online marks from school ) and I have one problem. I created function to generate some marks but when I delete the funcion the marks will just disapear.
I have two files,this is the one when we are executing our functions
import sas as s
s.generateGrades()
s.completeAverage()
and in this, there are all of functions
import random
def generateGrades() :
for i in range(30) :
continuousClassification.append([
subjects[random.randint(0,len(subjects)-1)],
"2016"+"-"+str(random.randint(1,12))+"-"+str(random.randint(1,30)),
str(random.randint(1,5)),
])
def addGrade() :
subject = input("Zadejte předmět zkratkou: ")
date = input("Zadejte datum ve formátu RRRR-MM-DD : ")
grade = input("Zadejte známku, pokud žák nepsal zadejte N :")
continuousClassification.append([subject,date,grade])
def searchBy(typeOf,source) :
if typeOf == "predmetu" :
for i in range(len(continuousClassification)) :
if(continuousClassification[i][0] == source) :
print("Známka ",continuousClassification[i][2])
else :
for i in range(len(continuousClassification)):
if (continuousClassification[i][1] == source):
print(i, ".", "známka ", continuousClassification[i][2])
def averageOfSubject(subject) :
all = 0
total = 0
for i in range(len(continuousClassification)) :
if continuousClassification[i][0] == subject :
all+=int(continuousClassification[i][2])
total+=1
if all == 0 :
return "V předmětu "+subject+" nemáte žádnou známku"
return round(all/total,2)
def completeAverage() :
for subject in subjects :
print("Průměr z ",subject," je ",averageOfSubject(subject))
subjects = ["MAT","CJL","DEJ","FYZ","TEV","ANJ","NEJ","PAD","GRW","TVY","ASW","TEA","ZAE"]
continuousClassification = []
I want to generate marks and I want to remember it all time, but it doesnt do it. When I run my script without generating new ones it just dont load them and I have to load new again

Categories