A friend of mine told me that she needs help with some homework, I owe her a favor so I said fine, why not. she needed help with a program that checks a sequence, if the sequence is made of the same 2 chars one after the other it will print "yes" (for example "ABABABAB" or "3$3$3$3:)
The program works fine with even length strings (for example "abab") but not with odd length one ("ububu")
I made the code messy and "bad" in purpose, computers is her worst subject so I don't want it to look obvious that someone else wrote the code
the code -
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = StringInput[0]
L2 = StringInput[1]
i = 0
while i <= len(StringInput):
if i % 2 == 0:
if StringInput[i] == L1:
i = i + 1
else:
GoodOrBad = False
break
if i % 2 != 0:
if StringInput[i] == L2:
i = i + 1
else:
GoodOrBad = False
break
if GoodOrBad == True:
print("yes")
elif GoodOrBad != True:
print("no")
main()
I hope someone will spot the problem, thanks you if you read everything :)
How about (assuming s is your string):
len(set(s[::2]))==1 & len(set(s[1::2]))==1
It checks that there is 1 char in the even locations, and 1 char in the odd locations.
a) Showing your friend bad and messy code makes her hardly a better programmer. I suggest that you explain to her in a way that she can improve her programming skills.
b) If you check for the character at the even position and find that it is good, you increment i. After that, you check if i is odd (which it is, since you found a valid character at the even position), you check if the character is valid. Instead of checking for odd position, an else should do the trick.
You can do this using two methods->
O(n)-
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = StringInput[0]
L2 = StringInput[1]
i = 2
while i < len(StringInput):
l=StringInput[i]
if(l==StringInput[i-2]):
GoodOrBad=True
else:
GoodOrBad=False
i+=1
if GoodOrBad == True:
print("yes")
elif GoodOrBad == False:
print("no")
main()
Another method->
O(1)-
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = set(StringInput[0::2])
L2 = set(StringInput[1::2])
if len(L1)==len(L2):
print("yes")
else:
print("no")
main()
There is a lot in this that I would change, but I am just showing the minimal changes to get it to work. There are 2 issues.
You have an off by one error in the code:
i = 0
while i <= len(StringInput):
# in the loop you index into StringInput
StringInput[i]
Say you have 5 characters in StringInput. Because your while loop is going from i = 0 to i < = len(StringInput), it is going to go through the values [0, 1, 2, 3, 4, 5]. That last index is a problem since it is off the end off StringInput.
It will throw a 'string index out of range' exception.
You need to use:
while i < len(StringInput)
You also need to change the second if to an elif (actually it could just be an else, but...) so you do not try to test both in the same pass of the loop. If you go into the second if after the last char has been tested in the first if it will go out of range again.
elif i % 2 != 0:
So the corrected code would be:
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = StringInput[0]
L2 = StringInput[1]
i = 0
while i < len(StringInput):
if i % 2 == 0:
if StringInput[i] == L1:
i = i + 1
else:
GoodOrBad = False
break
elif i % 2 != 0:
if StringInput[i] == L2:
i = i + 1
else:
GoodOrBad = False
break
if GoodOrBad == True:
print("yes")
elif GoodOrBad != True:
print("no")
main()
def main():
StringInput = input('your string here - ')
MaxLength = len(StringInput) // 2 + (len(StringInput) % 2 > 0)
start = StringInput[:2]
chained = start * MaxLength
GoodOrBad = chained[:len(StringInput)] == StringInput
if GoodOrBad == True:
print("yes")
elif GoodOrBad != True:
print("no")
I believe this does what you want. You can make it messier if this isn't bad enough.
Related
I'm solving this problem.
My code works when I test it but it is failing the provided check with the error:
:( Little Professor accepts valid level // timed out while waiting for program to exit
It passes the three previous checks for invalid levels. Any insight to why this might be happening would help.
Here is my code:
def main():
level = get_level()
q=1
s=0
while q<=10:
try:
x = generate_integer(level)
y = generate_integer(level)
ans = x + y
eq = int(input(f'{x} + {y} = '))
if ans == eq:
s += 1
pass
elif ans != eq:
c = 1
while c <= 2:
print('EEE')
eq = int(input(f'{x} + {y} = '))
if ans == eq:
s += 1
break
else:
c += 1
if c == 3:
print('EEE')
print(f'{x} + {y} = {ans}')
q += 1
except EOFError:
pass
print(f'Score: {s}')
def get_level():
valid_inputs = (1,2,3)
while True:
try:
level = int(input('Level: '))
if level in valid_inputs:
return level
else:
pass
except ValueError:
pass
def generate_integer(level):
max = 10**level-1
min = 10**(level-1)
if level == 1:
min == 0
num = random.randint(min,max)
return num
main()
I ran your program (as-is) and found at least 1 problem. I'm not sure if it's why check50 flags that error, but you will need to fix it before it will pass. I entered Level: 1, then got a duplicate equation (4 + 5 = ). This violates a requirement buried under How to Test: "Your program should output 10 distinct problems" (emphasis mine). It's easy to miss - I didn't see it until someone mentioned it on the CS50P ED Forum.
Also, the last 2 lines of your program are supposed to be:
if __name__ == "__main__":
main()
Instead, only you have:
main()
Finally, this is an observation on your code structure. You have a lot of if statements for the 3 attempts to answer the question. It's overly complicated and kind of hard to follow. Hint: It can be simplified with another loop to prompt and check answers.
I have to read the input and check if the number is actually a float or the string STOP. When I execute my program without the two commented out lines, the result is like this:
1.1
g=nan r=nan% s=nan
2.2
g=nan r=nan% s=nan
The code:
def CheckFloat(number):
try:
float(number)
return True
except ValueError:
return False
def read_input(period):
i = 0
info = []
nbr = []
diff = []
while True:
try:
# if not CheckFloat(input()) and input() != "STOP":
# exit(84)
info.append(input())
if info[i] == "STOP":
fnc_tendency(period, nbr)
else:
nbr.append(float(info[i]))
if i >= 0:
diff.append(nbr[i] - nbr[i - 1])
print_res(nbr, period, diff, i)
i += 1
except(EOFError, StopIteration):
exit(84)
But when I uncomment the two lines
# if not CheckFloat(input()) and input() != "STOP":
# exit(84)
the result looks like this:
1.1
2.2
g=nan r=nan% s=nan
I lose one line of printing, and I don't know why. Could someone help me through this please?
Your float function can be simplified quite a bit
def CheckFloat(n):
return type(n) == float
Otherwise, it looks like you're checking for input twice?
if not CheckFloat(input()) and input() != "STOP":
exit(84)
info.append(input())
# I think you intended to do something more like this:
val = input()
if CheckFloat(val) and val != "STOP":
# do something
else:
# do something
I have a practice question that requires me to generate x number of alternating substrings, namely "#-" & "#--" using both recursion as well as iteration. Eg.string_iteration(3) generates "#-#--#-".
I have successfully implemented the solution for the iterative method,
but I'm having trouble getting started on the recursive method. How can I proceed?
Iterative method
def string_iteration(x):
odd_block = '#-'
even_block = '#--'
current_block = ''
if x == 0:
return ''
else:
for i in range(1,x+1):
if i % 2 != 0:
current_block += odd_block
elif i % 2 == 0:
current_block += even_block
i += 1
return current_block
For recursion, you almost always just need a base case and everything else. Here, your base case it pretty simple — when x < 1, you can return an empty string:
if x < 1:
return ''
After than you just need to return the block + the result of string_iteration(x-1). After than it's just a matter of deciding which block to choose. For example:
def string_iteration(x):
# base case
if x < 1:
return ''
blocks = ('#--', '#-')
# recursion
return string_iteration(x-1) + blocks[x % 2]
string_iteration(5)
# '#-#--#-#--#-'
This boils down to
string_iteration(1) + string_iteration(2) ... string_iteration(x)
The other answer doesn't give the same result as your iterative method. If you always want it to start with the odd block, you should add the block on the right of the recursive call instead of the left:
def string_recursion(x):
odd_block = '#-'
even_block = '#--'
if x == 0:
return ''
if x % 2 != 0:
return string_recursion(x - 1) + odd_block
elif x % 2 == 0:
return string_recursion(x - 1) + even_block
For recursive solution, you need a base case and calling the function again with some other value so that at the end you will have the desired output. Here, we can break this problem recursively like - string_recursive(x) = string_recursive(x-1) + string_recursive(x-2) + ... + string_recursive(1).
def string_recursion(x, parity):
final_str = ''
if x == 0:
return ''
if parity == -1: # when parity -1 we will add odd block
final_str += odd_block
elif parity == 1:
final_str += even_block
parity *= -1 # flip the parity every time
final_str += string_recursion(x-1, parity)
return final_str
odd_block = '#-'
even_block = '#--'
print(string_recursion(3, -1)) # for x=1 case we have odd parity, hence -1
# Output: #-#--#-
I am doing a task in class about a password guesser. I stumbled into a lot of problems trying to solve this task, my first approach was to use for loops (code below), but I realized that the amount of 'for loops' is equal to the length of the string.
a_z = 'abcdefghijklmnopqrstuvwxyz'
pasw = 'dog'
tests = 0
guess = ''
azlen = len(a_z)
for i in range(azlen):
for j in range(azlen):
for k in range(azlen):
guess = a_z[i] + a_z[j] + a_z[k]
tests += 1
if guess == pasw:
print('Got "{}" after {} tests'.format(guess, str(tests)))
break
input()
The program above is very concrete. It only works if there are exactly 3 characters entered. I read that you could use a package called intertools, however, I really want to find another way of doing this. I thought about using recursion but don't even know where to start.
import string
import itertools
for possible_password in itertools.permutations(string.ascii_letters, 3):
print(possible_password)
If you don't want to use itertools you can certainly do this with recursion, which will work with passwords of any (reasonable) length—it's not wired to three characters. Basically, each recursive call will attempt to append a new character from your alphabet to your running value of guess. The base case is when the guess attains the same length as value you're seeking, in which case you check for a match. If a match is found, return an indication that you have succeeded (I used return True) so you can short circuit any further searching. Otherwise, return a failure indication (return False). The use of a global counter makes it a bit uglier, but produces the same results you reported.
ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
def brute_force_guesser(passwd, guess = ''):
global _bfg_counter
if len(guess) == 0:
_bfg_counter = 0
if len(guess) == len(passwd):
_bfg_counter += 1
if guess == passwd:
print('Got "{}" after {} tests'.format(guess, str(_bfg_counter)))
return True
return False
else:
for c in ALPHABET:
if brute_force_guesser(passwd, guess + c):
return True
return False
brute_force_guesser('dog') # => Got "dog" after 2399 tests
brute_force_guesser('doggy') # => Got "doggy" after 1621229 tests
One way to avoid the global counter is by using multiple return values:
ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
def brute_force_guesser(target, guess = '', counter = 0):
if len(guess) == len(target):
counter += 1
if guess == target:
print('Got "{}" after {} tests'.format(guess, str(counter)))
return True, counter
return False, counter
else:
for c in ALPHABET:
target_found, counter = brute_force_guesser(target, guess + c, counter)
if target_found:
return True, counter
return False, counter
brute_force_guesser('dog') # => Got "dog" after 2399 tests
brute_force_guesser('doggy') # => Got "doggy" after 1621229 tests
Here is my full answer, sorry if it's not neat, I'm still new to coding in general. The credit goes to #JohnColeman for the great idea of using bases.
import math
global guess
pasw = str(input('Input password: '))
chars = 'abcdefghijklmnopqrstuvwxyz' #only limeted myself to lowercase for simplllicity.
base = len(chars)+1
def cracker(pasw):
guess = ''
tests = 1
c = 0
m = 0
while True:
y = tests
while True:
c = y % base
m = math.floor((y - c) / base)
y = m
guess = chars[(c - 1)] + guess
print(guess)
if m == 0:
break
if guess == pasw:
print('Got "{}" after {} tests'.format(guess, str(tests)))
break
else:
tests += 1
guess = ''
cracker(pasw)
input()
import itertools
import string
def guess_password(real):
chars = string.ascii_lowercase + string.digits
attempts = 0
for password_length in range(1, 20):
for guess in itertools.product(chars, repeat=password_length):
attempts += 1
guess = ''.join(guess)
if guess == real:
return 'the password is {}, found in {} guesses.'.format(guess, attempts)
print(guess, attempts)
print(guess_password('abc'))
So, I'm quite nooby at python. I decided to make a program that makes prime numbers. I know there's probably a function built in that does this but I decided to do it myself.
number = 1
numlist = list()
for x in range (0, 1000):
numlist.append("")
print "Created list entry " + str(x)
while True:
number = number + 1
if number % 2 != 0:
numscrollerA = 1
numscrollerB = 1
while numscrollerA <= number:
if float(number) / float(numscrollerA) == float(int(number)):
numlist[numscrollerA] = "true"
if float(number) / float(numscrollerA) != float(int(number)):
numlist[numscrollerA] = "false"
numscrollerA = numscrollerA + 1
while numscrollerB <= number:
if numscrollerB != 1 and numscroller != number and numlist[numscrollerB] == "true":
primestatus = "false"
else:
primestatus = "true"
if primestatus == "true":
print number
I get "Created list entry x" 1000 times as I should. Then the program just hangs.
while numscrollerB <= number:
if numscrollerB != 1 and numscroller != number and numlist[numscrollerB] == "true":
primestatus = "false"
else:
primestatus = "true"
You don't increase numscrollerB in this loop, so it runs infinitedly. Anyway, You should rather use 'for loop':
for numscrollerB in range(1, number+1):
pass # do something
Your code is very unpythonic. Typical of a newcomer experienced in a different style of coding.
Your list is uneccessary.
In python you could create the list like this
def check_even(val):
#this contains your logic
return val % 2 == 0
evenslist = [check_even(i) for i in xrange(1, 1001)]
print numlist