Here is the code:
aWord = input("enter the word now")
num = 0
def palindromeMethod(theWord):
length = len(theWord)
if(theWord[num]==theWord[length-num]):
if(num>length):
print("its a palindrome")
num = num+1
palindromeMethod(theWord)
else:
return False
palindromeMethod(aWord)
I am getting errors at the three nums, which say: unresolved reference 'num', and I am getting the error local variable 'num' referenced before assignment when I run it. But I defined num before the method, so why am I getting these errors? thanks
edit: answered it myself
In python, to keep track of variables that need to exist during the recursion, you use an argument with a default value.
def palindromeMethod(theWord, num=0):
# here ^
length = len(theWord)
if(theWord[num]==theWord[length-num-1]):
if(num>=length-1):
return True
return palindromeMethod(theWord, num+1)
# pass it here ^
else:
return False
if palindromeMethod('aabbccbbaa'):
# don't need to pass it here ^
print('its a palindrome')
I moved the print outside the function and fixed some off-by-one errors.
Variables inside the functions has a local scope ,thus you need to initial the num inside the function ! But as you have a recursion function here you couldn't specify a num=0 in your function .
So my suggestion for such problem is :
pass the num as an argument to your function :
def palindromeMethod(theWord,num=0):
length = len(theWord)
if(theWord[num]==theWord[length-num]):
if(num>length):
print(theWord, "is a palindrome")
return True
num = num+1
return palindromeMethod(theWord,num)
else:
return False
No need for indices or lengths
def pal(w):
if w == "": return True
if w[0] != w[-1]: return False
return pal(w[1:-1])
but you may have been requested to use them...
Edit
Following a comment of the OP, that effectively narrows the spectrum of possible responses, here it is a look ma, no slices version of the above.
def pal(w, l=0, n=0):
# in production use: l = l if l else len(w)
if l ==0:
l = len(w)
print(("0123456789"*3)[:l])
print(w)
print(n, l-n-1, w[n], w[l-n-1])
if w[n] != w[l-n-1]: return False
if n+1 >= l-n-2: return True
return pal(w,l,n+1)
# a bit of testing
for word in ('aabbcbbaa', 'aabbccbbaa', 'aabbccbaa', 'aabbcdbbaa',
'saippuakivikauppias'):
print('Is the word "%s" palindrome? %s.' % (word, pal(word)))
The print expressions were used to show the work in progress of the function, the OP may want to remove them, as they were not requested (NB: w/o prints etc it's 5 LOC).
Output of testing
012345678
aabbcbbaa
0 8 a a
1 7 a a
2 6 b b
3 5 b b
Is the word "aabbcbbaa" palindrome? True.
0123456789
aabbccbbaa
0 9 a a
1 8 a a
2 7 b b
3 6 b b
4 5 c c
Is the word "aabbccbbaa" palindrome? True.
012345678
aabbccbaa
0 8 a a
1 7 a a
2 6 b b
3 5 b c
Is the word "aabbccbaa" palindrome? False.
0123456789
aabbcdbbaa
0 9 a a
1 8 a a
2 7 b b
3 6 b b
4 5 c d
Is the word "aabbcdbbaa" palindrome? False.
0123456789012345678
saippuakivikauppias
0 18 s s
1 17 a a
2 16 i i
3 15 p p
4 14 p p
5 13 u u
6 12 a a
7 11 k k
8 10 i i
Is the word "saippuakivikauppias" palindrome? True.
Final fireworks: the much expected one-liner
def pal(w): return 1 if w=="" else 0 if w[0]!=w[-1] else pal(w[1:-1])
ok I played around with it and came up with this, which works with no errors:
aWord = input("enter the word now")
num = 0
def palindromeMethod(theWord, num):
length = len(theWord)
if(theWord[num]==theWord[length-(1+num)]):
if(num>=length-1):
print("its a palindrome")
return True
num = num+1
palindromeMethod(theWord,num)
else:
return False
palindromeMethod(aWord,0)
however i am not 100% certain why this works. I'm guessing that when i say 'return True' it breaks out of the outer if block and doesn't execute the next two lines in the if block (num = num+1 and palindromeMethod(theWord,num).... is this correct?
Related
So I am very new to code and have learnt the basics of python. I am testing out my skills on codeforces by first solving some of their easier problems. I am trying to do 158A on codeforces. I think I have got it because it passed a few tests I assigned. So, I tried submitting it and it told me something about a runtime error. I don't really know what it is so I would like it if someone could tell me what it is and how to fix it in my code. Here is the link to the problem: https://codeforces.com/problemset/problem/158/A
n = int(input())
k = int(input())
b = []
for i in range(n):
a = int(input())
b.append(a)
c = 0
for i in b:
if i >= b[k]:
c = c+1
else:
pass
print(c)
The input you are given is "8 5" and "10 9 8 7 7 7 5 5". That doesn't mean you are given "8" and "5" as two different inputs. It means you have a very long string that contains numbers separated by spaces. You should turn these into a list.
a = input()
n = int(a.split(" ")[0])
k = int(a.split(" ")[1])
a should equal "8 5". We then turn the string into a list using a.split(" "). This will produce ["8", "5"].
In the problem 158A the expected input are:
1. Two numbers (int) separated by a single space, where 1 ≤ k ≤ n ≤ 50
2. n space-separated integers, where ai ≥ ai + 1
There is also a condition: Scores MUST be positive (score>0) so you can advance
This is all you need, I tested it and I got the expected output everytime
a = input("Input n and k: ")
n = int(a.split(" ")[0])
k = int(a.split(" ")[1])
b = input("Input n scores: ")
willAdvance = 0
scores = b.split()
print(scores)
for element in scores:
if int(element) >= int(scores[k-1]) and int(scores[k-1]) > 0:
willAdvance += 1
print(willAdvance)
TEST
Input:
8 5
10 9 8 7 7 7 5 5
Output:
6
Input:
4 6
0 0 0 0
Output:
0
I want my code to show that all rows, columns, and diagonals equal 15. And the numbers 1-9 can only show once in the 3 x 3 grid.
My code keeps telling me that false is not defined so when I change the false to "False" with a capital F all my code turns up as invalid instead of valid. The first 3 rows of my input file should show up as valid so I'm a bit confused.
input file:
4 3 8 9 5 1 2 7 6
8 3 4 1 5 9 6 7 2
6 1 8 7 5 3 2 9 4
6 9 8 7 5 3 2 1 4
6 1 8 7 5 3 2 1 4
6 1 3 2 9 4 8 7 5
5 5 5 5 5 5 5 5 5
my code:
def contains(grid, i):
#Returns true if i appears in the grid & returns false otherwise
for row in grid:
for value in row:
if value == i:
return true
return False
def isValidMagicSquare(grid):
#make sure each # appears exactly once in grid
for i in range(1, 10):
if not contains(grid, i):
return False
#make sure rows add to 15
for row in grid:
r1 = sum(grid[0])
r2 = sum(grid[1])
r3 = sum(grid[2])
if r1 == 15 and r2 == 15 and r3 == 15:
return true
else:
return false
#Make sure columns equal 15
for column in grid:
c1 = grid[0][0]+ grid[1][0]+ grid[2][0]
c2 = grid[0][1]+ grid[1][1]+ grid[2][1]
c3 = grid[0][2]+ grid[1][2]+ grid[2][2]
if c1 == 15 and c2 == 15 and c3 == 15:
return true
else:
return false
#Make sure diagonals equal 15
for diagonal in grid:
dL = full[0][0]+ full[1][1]+ full[2][2]
dR = full[0][2]+ full[1][1]+ full[2][0]
if dL == 15 and dR == 15:
return true
else:
return false
def main():
lst = []
f = open('input.txt')
for line in f:
grid = [0, 0, 0]
grid[0] = lst[0:3]
grid[1] = lst[3:6]
grid[2] = lst[6:9]
if isValidMagicSquare(grid):
print("Valid")
else:
print("Invalid")
main()
Its supposed to show:
valid
valid
valid
invalid
invalid
invalid
invalid
def main():
lst = []
f = open('input.txt')
for line in f:
grid = [0, 0, 0]
grid[0] = lst[0:3]
grid[1] = lst[3:6]
grid[2] = lst[6:9]
In this code, lst is always an empty list. Therefore lst[0:3], lst[3:6], and lst[6:9] will also be empty lists. Perhaps you meant line[0:3] instead?
However, even assuming that is what you meant, you still need to convert each input line to a list of integers. Try this:
for line in f:
numbers = [int(n) for n in line.split()]
grid = [0, 0, 0]
grid[0] = numbers[0:3]
...
There are a few issues to work out...
1) Here, you're comparing a number held as a string (in the grid) to a number held as an integer (passed in a i) - so this function will always return False.
def contains(grid, i):
#Returns true if i appears in the grid & returns false otherwise
for row in grid:
for value in row:
if value == i:
return true
return False
Converting the integer to a string to compare will work:
def contains(grid, i):
#Returns true if i appears in the grid & returns false otherwise
for row in grid:
for value in row:
if value == str(i):
return true
return False
2) Then, you'll run into the problem that this code throws an error, as you're trying to use the sum function on a string (e.g. '123') rather than a list of numbers (e.g. [1,2,3]) here:
r1 = sum(grid[0])
r2 = sum(grid[1])
r3 = sum(grid[2])
You can hack around this with a quick custom sum function:
def string_sum(s):
return int(s[0]) + int(s[1]) + int(s[2])
...and then drop it in...
r1 = string_sum(grid[0])
r2 = string_sum(grid[1])
r3 = string_sum(grid[2])
At this point, it appears to work and (interestingly) give the answers you want, but there are still two problems, one major, one minor:
3) Your logic for the isValidMagicSquare function is broken overall: returning a value from a function ends the function's operation at that point. Thus, as the row-checking section of logic always returns either true or false, you'll never move onto checking the columns or the diagonals - this code is never used. For this, I think you will need a rethink of the logic and structure, which is probably beyond this scope of this question/answer.
4) You've got undeclared variables here:
dL = full[0][0]+ full[1][1]+ full[2][2]
dR = full[0][2]+ full[1][1]+ full[2][0]
I assume full should be grid. But the code will run, as (as said) this section is never reached.
Trying to simulate 20 dice throws randomly, the code needs to enclose with parenthesis a value that is the same, the parenthesis appear, but I am missing something on my formula, any advise can greatly help, eg:
1 ( 4 1 ) 2 3 6 1 4 3 2 6 6 6 5 6 2 1 3 5 3 # incorrect
1 4 1 2 3 6 1 4 3 2 ( 6 6 6 ) 5 6 2 1 3 5 3 # this is a correct example
def main():
exampleList = [ ]
for i in range(20):
exampleList.append(randint(1, 6))
print(exampleList)
print(list(range(0,20)))
max_count = 0
run_count = 0
matched = False #inRun = False
# find max run
for rollValue in exampleList:
#print(rollValue)
if run_count == 19:
print()
else:
print("-------")
print("Roll Value %s" % exampleList[run_count])
print("Position %s" % run_count)
print("Next Roll value %s" % exampleList[run_count + 1])
if exampleList[run_count] == exampleList[run_count + 1]:
matched = True
print("------->>>matched")
else:
matched = False#inRun = False
run_count += 1
if rollValue < 19:
if exampleList[rollValue] == exampleList[rollValue + 1]:
run_count += 1
if matched == False:
matched == True
run_count = rollValue
else:
matched = False
if run_count > max_count:
run_count = 1
# print sequence
for rollValue in range(20):
if rollValue == run_count:
print("(", exampleList[rollValue], end = " ")
elif rollValue == run_count + max_count + 1:
print(exampleList[rollValue], ")", end = " ")
else:
print(exampleList[rollValue], end = " ")
main()
Here is a solution using regex. This creates a string out of the dice rolls, then finds repeating digits and uses re.sub to add parenthesis.
import re
import random
rolls = ''.join(map(str, [random.choice(range(1, 7)) for _ in range(20)]))
rolls = ' '.join(re.sub(r'(\d)(\1+)', r'(\1\2)', rolls))
print(rolls)
A couple sample runs:
4 1 4 3 4 6 5 2 3 ( 5 5 ) 1 6 4 3 5 2 5 ( 4 4 )
2 ( 1 1 ) 4 1 ( 5 5 ) ( 3 3 ) 6 2 ( 1 1 ) 5 1 4 3 4 ( 5 5 )
Regex explanation:
( // start of matching group 1
\d // matches a single digit
) // end of matching group 1
( // start of matching group 2
\1+ // matches group 1, 1 or more times
) // end of matching group 2
This adds the parenthesis as part of the list:
#!/usr/bin/python
import sys
from random import randint
# add parenthesis as part of the list
def main():
exampleList = [ ]
previous = -1
opened = False
for i in range(20):
roll = randint(1, 6)
if roll == previous:
if not opened:
exampleList.insert(-1, '(')
opened = True
else:
if opened:
exampleList.append(')')
opened = False
exampleList.append(roll)
previous = roll
if opened:
exampleList.append(')')
for item in exampleList:
sys.stdout.write('{0} '.format(item))
sys.stdout.write('\n')
if __name__ == '__main__':
main()
Examples:
( 2 2 ) 4 5 1 2 1 ( 6 6 ) 1 6 1 4 1 ( 6 6 ) 1 6 2 4
2 ( 6 6 ) ( 1 1 ) 3 2 1 ( 4 4 ) 1 2 5 4 1 5 3 ( 5 5 5 )
There are a number of issues with your code, so it was just quicker to rewrite the whole thing.
def main():
example_list = []
for _ in range(20):
example_list.append(random.randint(1, 6))
inside = False
for index in range(len(example_list)):
try:
if inside:
if example_list[index] != example_list[index + 1]:
print("%d )" % example_list[index], end=" ")
inside = False
else:
print(example_list[index], end=" ")
else:
if example_list[index] == example_list[index + 1]:
print("( %d" % example_list[index], end=" ")
inside = True
else:
print(example_list[index], end=" ")
except IndexError:
print("%d" % example_list[index], end=" ")
if inside:
print(")")
else:
print()
As you can see I keep track of whether I'm inside a parenthesis by using a variable. I look to the next number to guess if I should add a closing parenthesis.
The last case is handled by a try-except.
You could also handle each number by looking forward and backward but that'd require you to add some extra condition for the try-except part so this was just
There are various ways to do this, but this is the most similar to what you were doing already. Basically just iterate over the index of your list of rolls. Each number we examine it to see if it is the same as the one before, if yes, then we increment the count and move on. If not then we add however many of that number were in the count to the output. If there was one, we write it out by itself, if more, in parenthesis.
exampleList = [randint(1, 6) for i in range(20)]
# the current number that could be a potential sequence
current = exampleList[0]
# count for the number of occurences in a sequence (often 1)
count = 1
# The string to outpu
output = ''
# Iterate over the rolls, ignoring the first one
for i in range(1, len(exampleList)):
if exampleList[i] == current:
count += 1
else:
if count > 1:
output += ('(' + count * str(current) + ')')
else:
output += str(current)
current = exampleList[i]
count = 1
# Handle final addition
if count > 1:
output += ('(' + count * str(current) + ')')
else:
output += str(current)
print(output)
Output:
64(66)15253(66)2143454(22)
The logical error is that you're confusing "the index where the run starts" with "the length of the (last) run".
You need a variable like max_run_start_index.
Look at the code:
if rollValue == run_count:
print("(", exampleList[rollValue], end = " ")
Read it back to yourself 'if the index of the next output is equal to the length of the last run, output open bracket before it'.
So if the length of the last run is 3 the longest run starts at index 3?
Surely not...
I'm not a Python coder, so you'll need to fix it yourself...
I have really been struggling to solve this problem. This is the problem:
Given a string describing the circuit, calculate the total resistance
of the circuit.
Here is an example:
input: 3 5 S
expected output: 8
The operands in the string are trailed by the operator, denoting if the resistors are either in Series or Parallel. However let's analyze a more complicated circuit:
input: 3 5 S 0 P 3 2 S P
expected output: 0
Step by step:
The 3 5 S at the beginning of the input gives us 8 and hence the first intermediate step is the string 8 0 P 3 2 S P.
8 0 P gives us 0, as one resistor is short-circuited and consequently we get 0 3 2 S P.
3 2 P is 5.
and finally 0 5 P is 0.
Here is my attempt. I tried using recursion as it seemed like a problem that can be solved that way. Firstly I wrote a helper function:
def new_resistance(a,b,c):
if c == '':
if int(a) == 0 or int(b) == 0:
return 0
else:
return 1/(1/int(a) + 1/int(b))
else:
return int(a) + int(b)
And the function that calculates the newn resistance of the circuit:
def resistance(array):
if isinstance(array, int):
return array
else:
if isinstance(array,list):
temp = array
else:
temp = array.split(" ")
i = 0
while True:
try:
a = new_resistance(temp[i], temp[i+1], temp[i+2])
except Exception as e:
i += 1
if len(temp[i+3:]) == 0:
return resistance(new_resistance(temp[i], temp[i+1], temp[i+2]))
else:
return resistance(temp[:i] + [new_resistance(temp[i], temp[i+1], temp[i+2])] + temp[i+3:])
The idea behind the program is to start at the beginning of the list and calculate the resistance of the first three elements of the list, then to append them at the beginning of a new list (without the three elements) and call the function again with the new list. Do this until only a single integer remains and return the integers.
Any help is appreciated.
UPDATE:
The solution to the problem, using a stack and a parser similar to a NPR parser.
operator_list = set('PS')
def resistance(circuit):
temp = circuit.split(" ")
stack = []
for char in temp:
if char in operator_list:
a = new_resistance(stack.pop(), stack.pop(), char)
print(a)
stack.append(a)
else:
print(char)
stack.append(char)
return stack[-1]
def new_resistance(a,b,c):
if c == 'P':
if float(a) == 0 or float(b) == 0:
return 0
else:
return 1/(1/float(a) + 1/float(b))
else:
return float(a) + float(b)
circuit = '3 5 S 0 P 3 2 S P'
resistance(circuit)
# 3
# 5
# 8.0
# 0
# 0
# 3
# 2
# 5.0
# 0
The problem is that once you reach 0 3 2 S P, you cannot simply take the first 3 elements. You need to look for number number S_or_P, wherever it is in the string.
You can use a regex for this task:
import re
circuit = '3 5 S 0 P 3 2 S P'
pattern = re.compile('(\d+) +(\d+) +([SP])')
def parallel_or_serie(m):
a, b, sp = m.groups()
if sp == 'S':
return str(int(a) + int(b))
else:
if a == '0' or b == '0':
return '0'
else:
return str(1/(1/int(a) + 1/int(b)))
while True:
print(circuit)
tmp = circuit
circuit = re.sub(pattern, parallel_or_serie, circuit, count=1)
if tmp == circuit:
break
# 3 5 S 0 P 3 2 S P
# 8 0 P 3 2 S P
# 0 3 2 S P
# 0 5 P
# 0
Note that 1 1 P will output 0.5. You could replace int by float and modify the regex in order to parse floats.
Your program, or more specifically your parser, seems to be relying on the Reverse Polish Notation, which in turn is a small variant of the Normal Polish Notation. Simply put, the RPN is an abstract representation where the operators of an arithmetical expression follow their operands, unlike in the Normal Polish Notation where the operators precede their operands. Parsers based on this representation can be easily implemented by using stacks (and usually do not need to interpret parentheses).
If you are tasked with developing that parser you may get some input from the Wikipedia article I linked above.
Credits to #none who first recognized the RPN.
Old memories came to my mind. I was playing with the FORTH language on 8-bit computers in 1980s. OK, back to Python:
circuit = '3 5 S 0 P 3 2 S P'
stack = []
for n in circuit.split():
if n == 'S':
r1 = stack.pop()
r2 = stack.pop()
stack.append(r1+r2)
elif n == 'P':
r1 = stack.pop()
r2 = stack.pop()
stack.append(0.0 if (r1 == 0 or r2 == 0) else 1/(1/r1+1/r2))
else:
stack.append(float(n))
assert len(stack) == 1
print(stack[0])
On in the spirit of VPfB for any combination of serial parallel (not only in pairs)
def calculateresistor(dataString):
stack = []
r = []
cicuit=dataString
for n in circuit.split():
if n == 'S':
stackSize=size(stack)
if size(stack)>=2:
for k in range(0,size(stack)-1):
r.append(float(stack.pop()))
r.append(float(stack.pop()))
stack.append((r[-1]+r[-2]))
elif n == 'P':
stackSize=size(stack)
if size(stack)>=2:
for k in range(0,size(stack)-1):
r.append(float(stack.pop()))
r.append(float(stack.pop()))
r.append(0.0 if (r[-1] == 0 or r[-2] == 0) else (1/(1/r[-1]+1/r[-2])))
stack.append(r[-1])
else:
stack.append(float(n))
assert len(stack) == 1
return(stack)
Please explain how does for loop work.
i know how to solve the problem, using both while loop and for loop(commented code)
def decode(string):
aux = ''
for i in range(len(string)):
if(string[i] == '['):
num = ''
i+=1
print(i,"lol")
while(string[i].isdigit()):
num+=string[i]
i+=1
print(i,'inside')
aux+= string[i]*int(num)
i+=1
print(i)
#elif string[i].isalpha():
else:
print(i,'else')
aux += string[i]
return aux
if __name__ == '__main__':
print(decode("AB[12c]d[2E][4F]g"))
Shell
>>> 0 else
>>> 1 else
>>> 3 lol
>>> 4 inside
>>> 5 inside
>>> 6
>>> 3 else
>>> 4 else
>>> 5 else
>>> 6 else
>>> 7 else
>>> 9 lol
>>> 10 inside
>>> 11
>>> 9 else
>>> 10 else
>>> 11 else
>>> 13 lol
>>> 14 inside
>>> 15
>>> 13 else
>>> 14 else
>>> 15 else
>>> 16 else
>>> ABcccccccccccc12c]dEE2E]FFFF4F]g
how does that work? Thanks
Your for in range loop will iterate exactly the number of times of the length of the string you pass... You cant cause the loop to jump further ahead by incrementing i within the loop... Its not the same things as a for i = 0 to i < length...
Think about your output this way...
first iteration in range gives you ...
0 else
second iteration in range gives you...
1 else
third iteration in range gives you...
3 lol
4 inside
5 inside
6
the fourth iteration goes back to 3 because the loop is zero indexed and its the fourth iteration so you get...
3 else
In order for loop with i changing by steps different than one, you can specify the steps in the range... eg.
for i in range(0,10,2):
In summary:
You are thinking that your manipulation of i within the loop should carry over to when you get back to the top of the loop, but it does not, it merely increments by one from the last time you were at the top of the loop.