index out of range in a recursive call - python

I´m getting index out of range when I try to call my function more than once. I´m new to programming and cant figure out why or how to solve it.
the code works fine when:
if n == 9:
return strng
here is my code:
def swap(n, strng): # helper
s = ""
for i in range(len(strng)):
s += strng[i-n]
return s
def encode(n, strng):
temp_lst = []
result = ""
space_idx = [i for i in range(len(strng)) if strng[i] == " "]
if n == 8: # works when 9
return strng
temp_lst.extend(encode(n-1, swap(n, "".join(strng.split()))))
for insert_idx in space_idx:
temp_lst.insert(insert_idx, " ")
for i in "".join(temp_lst).split():
result += encode(n-1, swap(n % len(i), i))
result += " "
return result
print(encode(10, "the quick brown fox jumps over the lazy dog."))
thanks in advance, and let me know if you need more information.

Related

Replace a single character in a string

I am trying to make a function that automatically generated a response to a selection of an action in a text adventure game. My problem is that I have to replace every second '_' with ' '. However I have tried everything I have though of and whenever I google the question the only solution I get is to use .replace(). However .replace() replaces every instance of that character. Here is my code, could you please fix this for me and explain how you fixed it.
example_actions = ['[1] Search desk', '[2] Search Cupboard', '[3] Search yard'
def response(avaliable_actions):
for i in avaliable_actions:
print(i, end=' ')
x = avaliable_actions.index(i)
avaliable_actions[x] = avaliable_actions[x][4:]
avaliable_actions = ' '.join(avaliable_actions)
avaliable_actions = avaliable_actions.lower()
avaliable_actions = avaliable_actions.replace(' ', '_')
avaliable_actions = list(avaliable_actions)
count = 0
for i in avaliable_actions:
if count == 2:
count = 0
index = avaliable_actions.index(i)
avaliable_actions[index] = ' '
elif i == '_':
count += 1
avaliable_actions = ' '.join(avaliable_actions)
print('\n\n' + str(avaliable_actions)) #error checking
Here's one approach:
s = 'here_is_an_example_of_a_sentence'
tokens = s.split('_')
result = ' '.join('_'.join(tokens[i:i+2]) for i in range(0,len(tokens),2))
print(result)
The result:
here_is an_example of_a sentence
Did I understand you correct, that you wanna produce something like this?
this_is_a_test -> this is_a test or this_is a_test?
If so, adapt the following for your needs:
s = "this_is_just_a_test"
def replace_every_nth_char(string, char, replace, n):
parts = string.split(char)
result = ""
for i, part in enumerate(parts):
result += part
if i % n == 0:
result += replace
else:
result += char
return ''.join(result)
res = replace_every_nth_char(s, "_", " ", 2)
print(s, "->", res)
# "this_is_just_a_test" -> "this is_just a_test"

Python reverse each word in a sentence without inbuilt function python while preserve order

Not allowed to use "Split(),Reverse(),Join() or regexes" or any other
helping inbuilt python function
input something like this:
" my name is scheven "
output like this:
"ym eman si nevehcs"
you need to consider removing the starting,inbetween,ending spaces aswell in the input
I have tried 2 tries, both failed i will share my try to solve this and maby an idea to improve it
First try:
def reverseString(someString):
#lenOfString = len(someString)-1
emptyList = []
for i in range(len(someString)):
emptyList.append(someString[i])
lenOfString = len(emptyList)-1
counter = 0
while counter < lenOfString:
if emptyList[counter] == " ":
counter+=1
if emptyList[lenOfString] == " ":
lenOfString-=1
else:
swappedChar = emptyList[counter]
emptyList[counter] = emptyList[lenOfString]
emptyList[lenOfString] = swappedChar
counter+=1
lenOfString-=1
str_contactantion = ""
#emptyList = emptyList[::-1]
#count_spaces_after_letter=0
for letter in emptyList:
if letter != " ":
str_contactantion+=letter
#str_contactantion+=" "
str_contactantion+=" "
return str_contactantion
second try:
def reverse(array, i, j):
emptyList = []
if (j == i ):
return ""
for k in range(i,j):
emptyList.append(array[k])
start = 0
end = len(emptyList) -1
if start > end: # ensure i <= j
start, end =end, start
while start < end:
emptyList[start], emptyList[end] = emptyList[end], emptyList[start]
start += 1
end -= 1
strconcat=""
for selement in emptyList:
strconcat+=selement
return strconcat
def reverseStr(someStr):
start=0
end=0
help=0
strconcat = ""
empty_list = []
for i in range(len(someStr)):
if(someStr[i] == " "):
continue
else:
start = i
j = start
while someStr[j] != " ":
j+=1
end = j
#if(reverse(someStr,start,end) != ""):
empty_list.append(reverse(someStr,start,end))
empty_list.append(" ")
for selement in empty_list:
strconcat += selement
i = end + 1
return strconcat
print(reverseStr(" my name is scheven "))
The following works without managing indices:
def reverseString(someString):
result = crnt = ""
for c in someString:
if c != " ":
crnt = c + crnt # build the reversed current token
elif crnt: # you only want to do anything for the first space of many
if result:
result += " " # append a space first
result += crnt # append the current token
crnt = "" # and reset it
if crnt:
result += " " + crnt
return result
reverseString(" my name is scheven ")
# 'ym eman si nevehcs'
Try this:
def reverseString(someString):
result = ""
word = ""
for i in (someString + " "):
if i == " ":
if word:
result = result + (result and " ") + word
word = ""
else:
word = i + word
return result
You can then call it like this:
reverseString(" my name is scheven ")
# Output: 'ym eman si nevehcs'
Try this:
string = " my name is scheven "
def reverseString(someString):
result = ''
curr_word = ''
for i in someString:
if i == ' ':
if curr_word:
if result:
result = f'{result} {curr_word}'
else:
result = f'{result}{curr_word}'
curr_word = ''
else:
curr_word = f'{i}{curr_word}'
return result
print(repr(reverseString(string)))
Output:
'ym eman si nevehcs'
Note: if you're allowed to use list.append method, I'd suggest using a collections.deque as it's more performant than appending to a list. But of course, in the end you'll need to join the list together, and you mentioned that you're not allowed to use str.join, so that certainly poses an issue.

printing out or returning strings between brackets

I'm trying to write a function in similar manner as started, so that I will get what it's doing. I'm assuming this can be done with one line of code, with some fancy functions, but for the sake of practice and understanding I'm trying to come up with similar solution.
The task is the following: the function takes a text once it encounters enclosed square brackets [ word ] It should print out or return all words which are between square brackets. For example, if the text string would be "[a]n example[ string]", you are expected to print out "a string".
def string():
text = "some random text [and I need this bit of txt] but I don't know how to continue [to get this bit as well]"
for i in text:
for j in range(len(text)):
if text[j] == '[':
new = text.find(']')
return(text[j+1:new])
print(string())
Try this:
def extract(text, skip_chars=("\n", )):
output = ""
flag = False
for c in text:
if c == "]":
flag = False
if flag and not c in skip_chars:
output += c
if c == "[":
flag = True
return output
print(extract("""[a]n example[
stri
ng]"""))
# -> "a string"
def string():
result = []
text = "some random text [and I need this bit of txt] but I don't know how to continue [to get this bit as well]"
for i in text:
if i == '[':
new = text.find(']')
result.append(text[text.index(i) + 1:new])
return " ".join(result)
print(string())
def parse(source):
i = source.index("[") # throw an exception
result = ""
while i < len(source):
if s[i] == "[":
i += 1
while i < len(source):
temp = ""
if source[i] == "]":
result += temp
break;
temp += source[i]
i += 1
i += 1
return result

why does this get an error and this doesn't?

i'm working through a hackerrank problem: https://www.hackerrank.com/challenges/kaprekar-numbers/problem
and kept having to deal with this error:
ValueError: invalid literal for int() with base 10: ''
the line 12 of code in mine that churned out error, is in the working code too. So i don't understand why mine didn't work :( please help
this is my code:
a = input()
b = input()
l = []
for i in range(a, b + 1):
s = i*i
s = str(s)
if i == 1:
l.append(i)
length = len(s)
if length <= 1:
pass
temp = int(s[0:length/2]) + int(s[length/2:]) #error came from this line
if temp == i:
l.append(i)
else:
pass
if not l:
print "INVALID RANGE"
else:
print " ".join(map(str, l))
and this is the one that works:
def kaprekar(i):
if i == 1:
return True
s = i ** 2
s = str(s)
length = len(s)
if len(s) <= 1:
return False
temp = int(s[0:length/2]) + int(s[length/2:])
if temp == i:
return True
else:
return False
a = input()
b = input()
l = []
for i in range(a, b + 1):
if kaprekar(i):
l.append(i)
if not l:
print "INVALID RANGE"
else:
print " ".join(map(str, l))
if length <= 1:
pass
pass literally doesn't do anything, so this check doesn't do anything. Whether the length is or isn't <= 1, you're proceeding to int(s[length/2:]), which will produce said error in case the string is too short.
However, return False exits the function and the following code will not execute, so that check protects you from trying to process short strings.

PYTHON IndexError : string index out of range

Problem statement : Write a function called censor that takes two strings, text and word, as input. It should return the text with the word you chose replaced with asterisks
Here is my code,
def censor(text, word):
i = 0
j = 0
ans = ""
while i<len(text):
while text[j] == word[j]:
j = j + 1
if text[j+1] == " " or j+1 == len(text):
while i<j:
ans += "*"
i = i + 1
ans += " "
i = i + 1
else:
while text[j] != " ":
j = j + 1
while i<=j:
ans += text[i]
i = i + 1
i = i + 1
j = j + 1
return ans
print censor("how are you? you are not fine.","you")
But I am getting the following error,
Traceback (most recent call last):
File "python", line 27, in <module>
File "python", line 7, in censor
IndexError: string index out of range
This is much more complicated than it needs to be. You can just do this:
def censor(text, censored_word):
return text.replace(censored_word, '*'*len(censored_word))
>>> censor('How are you? Are you okay?', 'you')
'How are ***? Are *** okay?'
If you don't want the word youth to be censored but you do want you to be censored, here's how:
def censor(text, censored_word):
repl = '*'*len(censored_word)
return ' '.join([repl if word == censored_word else word for word in text.split()])
If you want to have multiple censored words:
def censor(text, censored_words):
return ' '.join(['*'*len(word) if word in censored_words else word for word in text.split()])
When dealing with index errors, it is often helpful to print out the index and figure out why the index has a value not within the required bounds.
It's good to use string replace in python for replacing the string.
In your case, you should make use of word's length to match word in the text as:
def censor(text, word):
i = 0
j = 0
ans = ""
wl=len(word)
while i<(len(text)):
if word==text[i:i+wl]:
ans=ans+'*'*wl
i=i+wl
else:
ans=ans+text[i]
i = i + 1
return ans
print censor("how are you? you are not fine.","you")

Categories