You are given a list jumps of positive and negative integers which signify forward or negative jumps.
Starting at index 0, you jump to index 0+jump[0] . In general, if you are at index k, you would jump to index k+jump[k] Let's say jumps[0] was 2 . Index becomes 2. Assuming jumps[2] was -1, index would become 1.
Write the function list_jumps(jumps) where jumps is the aforementioned list. The function should return the string 'cycle' if the index will never leave the boundaries of the input list otherwise it must return 'out-of-bounds'. The starting index is always 0.
dm=[3,0,0,-2]
def list_jump(jumps):
xs=jumps
xy=jumps
max=len(xs)
while(True):
p = int(xs[0])
print p
for i in range (0,max,p):
print i,"iii"
p = xs[i]
if xs[i]=="visited":
return False
else:
xs[i]="visited"
print xs
return True
if list_jump(dm):
print "not cycle"
else:
print "cycle"
I really don't need solution. I just want to know what is the error.
note that I would just make a set seen and add each index to that.
def list_jump(jumps):
i = 0
seen = {0}
while True:
try:
i += jumps[i]
if i < 0:
# negative indices are legal, but we should exit if we have one.
return "out-of-bounds"
except IndexError:
# we've escaped the list: non-cyclic!
return "out-of-bounds"
else:
if i in seen:
return "cycle"
else:
seen.add(i)
Related
I have this string 0123456789 and I want to use recursion to create a method that returns
'09182736455463728190'
So basically the above says that first I get the first num from the left and then the first from the right, and add them to the string, then I get the second from the left and the second from the right, etc.
When I reach the middle, I start adding to the final string the values of the initial string, but now int the opposite order. So 546372, etc. So Starting from the edges I add first the most left and then the most right element.
Starting from the middle and moving to the edges, I favour the right side element first.
I cannot come up with the recursion relationship
Here it is. The base case is when the final string length is twice the original string length. This signals the end of recursion and returns the final string. The recursive step consists of advancing the start index forward and the end index backward on the original string:
def transform_sequence(original, final = '', start_index = 0, end_index = -1):
#base case:
if len(final) == 2* len(original):
return final
#recursion
final += original[start_index] + original[end_index]
return transform_sequence(original, final, start_index + 1, end_index - 1)
print(transform_sequence('0123456789'))
#output: 09182736455463728190
If you want to use recursion to handle this, you'd better try to solve it from top-down like this
def rec(nums):
if len(nums) == 0:
return ''
elif len(nums) == 1:
return nums * 2
else:
first = nums[0]
last = nums[-1]
return ''.join([first, last, rec(nums[1:-1]), last, first])
if __name__ == '__main__':
nums = '0123456789'
print(rec(nums)) # 09182736455463728190
nums = '012'
print(rec(nums)) # 021120
nums = '0'
print(rec(nums)) # 00
Fun problem and great way to learn about recursion. We can use inductive reasoning to ensure our program is valid for all input strings -
if the input s is empty, return the empty result
(inductive) s is not empty. get the first and last characters, a and b, and prepend/append them to the result of the sub-problem, s[1:-1]
We can easily encode this in python -
def first_and_last(s):
return (s[0], s[-1])
def puzzle(s):
if not s:
return "" # 1
else:
(a,b) = first_and_last(s) # 2
return a + b + puzzle(s[1:-1]) + b + a
We can see it working below -
print(puzzle("0123456789"))
print(puzzle("12345"))
09182736455463728190
152433334251
When then puzzle input is an odd length, notice how the middle character is repeated four times. When we reach the sub-problem puzzle("3"), a=3 and b=3, and the result of a + b + puzzle("") + b + a is 3333.
If you wish to handle this situation differently, we could modify puzzle
def puzzle(s):
if len(s) < 2: # <- if input is empty or singleton string
return s # <- return s
else:
(a,b) = first_and_last(s)
return a + b + puzzle(s[1:-1]) + b + a
print(puzzle("0123456789"))
print(puzzle("12345"))
09182736455463728190
152434251 # <-
The nice answer from Menglong Li presents another option for dealing with puzzle inputs of an odd length. I encourage you to see it :D
I'd take a different approach to this problem and assume the argument is a sequence rather than a str. This simplifies our logic, allowing us to pass str to the initial call, but the recursive calls can pass list:
def puzzle(sequence):
if len(sequence) > 1:
first, *middle, last = sequence
return first + last + puzzle(middle) + last + first
return sequence[0] if sequence else ""
if __name__ == '__main__':
print(puzzle("0123456789"))
print(puzzle("12345"))
print(puzzle("012"))
print(puzzle("0"))
OUTPUT
> python3 test.py
09182736455463728190
152434251
02120
0
>
If you approach this as processing the first character (placing it at the beginning and end) and recursing with the inverted remainder of the string then your exit condition will be an empty string:
def mirror(S):
return "" if not S else S[0]+mirror(S[:0:-1])+S[0]
print(mirror("0123456789")) # 09182736455463728190
If you want to avoid generating new (inverted) strings on every recursion, you could also implement it using an index that you carry along and map to alternating start/end relative positions:
def mirror(S,i=0):
j = (i+1)//2 * (-1)**i
return S[j]+mirror(S,i+1)+S[j] if i<len(S) else ""
I'm solving this HackerRank challenge:
Alice has a binary string. She thinks a binary string is beautiful if and only if it doesn't contain the substring '010'.
In one step, Alice can change a 0 to a 1 or vice versa. Count and print the minimum number of steps needed to make Alice see the string as beautiful.
So basically count the number of '010' occurrences in the string 'b' passed to the function.
I want to increment i by 2 once the if statement is true so that I don't include overlapping '010' strings in my count.
And I do realize that I can just use the count method but I wanna know why my code isn't working the way I want to it to.
def beautifulBinaryString(b):
count = 0
for i in range(len(b)-2):
if b[i:i+3]=='010':
count+=1
i+=2
return count
Input: 0101010
Expected Output: 2
Output I get w/ this code: 3
You are counting overlapping sequences. For your input 0101010 you find 010 three times, but the middle 010 overlaps with the outer two 010 sequences:
0101010
--- ---
---
You can't increment i in a for loop, because the for loop construct sets i at the top. Giving i a different value inside the loop body doesn't change this.
Don't use a for loop; you could use a while loop:
def beautifulBinaryString(b):
count = 0
i = 0
while i < len(b) - 2:
if b[i:i+3]=='010':
count += 1
i += 2
i += 1
return count
A simpler solution is to just use b.count("010"), as you stated.
If you want to do it using a for loop, you can add a delta variable to keep track of the number of positions that you have to jump over the current i value.
def beautifulBinaryString(b):
count = 0
delta = 0
for i in range(len(b)-2):
try:
if b[i+delta:i+delta+3]=='010':
count+=1
delta=delta+2
except IndexError:
break
return count
You don't need to count the occurrences; as soon as you find one occurrence, the string is "ugly". If you never find one, it's beautiful.
def is_beautiful(b):
for i in range(len(b) - 2):
if b[i:i+3] == '010':
return False
return True
You can also avoid the slicing by simply keeping track of whether you've started to see 010:
seen_0 = False
seen_01 = False
for c in b:
if seen_01 and c == '0':
return False
elif seen_1 and c == '1':
seen_01 = True
elif c == '0':
seen_0 = True
else:
# c == 1, but it doesn't follow a 0
seen_0 = False
seen_01 = False
return True
This question already has answers here:
Indices of matching parentheses in Python
(5 answers)
Closed 6 years ago.
The Problem:
I am attempting to write some python code that searches through a list and returns the index of a matching bracket. For example:
array = ["(","foo",")","(","bar","(",")",")"]
f(0) => 2
f(1) => ERROR: Not a bracket.
f(2) => 0
f(3) => 7
My Feeble Attempts:
I tried looping through the list and finding the closest bracket, but then I realised it didn't work when you had loops inside loops (loopception). I have also tried adding a counter that adds one to the counter if it's a new bracket ( and takes one if it's a close bracket ), then checks to see if it equals -1, but that doesn't work.
Previous Code:
while True:
if(count == -1):
iterator = j+1
break
else:
j += 1
print j
if(commands[j] == "("):
count += 1
if(commands[j] == ")"):
count -= 1
Where iterator is the input and commands is the array
Assuming the array holds a correct sequence of opening/closing backets:
array = ["(","foo",")","(","bar","(",")",")"]
bracketPositions = []
for i, item in enumerate(array):
if i == 0 and item == ')':
print("Non sense ! Exit")
break
if item == '(':
bracketPositions.append(i)
elif item ==')':
if len(bracketPositions) > 0:
openingPosition = bracketPositions.pop()
print(openingPosition, '-->', i)
else:
print('ERROR: Not a bracket. Word is: %s.' % item)
Prints:
ERROR: Not a bracket (foo).
0 --> 2
ERROR: Not a bracket (bar).
5 --> 6
3 --> 7
With the counter variable you were on the right track, but it's difficult to say what exactly went wrong without seeing the entire code. Basically, what you have to do is: Determine in which direction to go and what to look out for. Initialize the number of matching parens to find as 1, then iterate through the array. If you find the original parens again, increment the counter, if you find the counterpart, decrement the counter. If the counter reaches zero, return the current position.
You can try something like this:
def match(array, pos):
try:
step = {"(": +1, ")": -1} [array[pos]] # go left or right?
other = {"(": ")", ")": "("}[array[pos]] # what to look for?
count = 1 # number of 'other' we have to find
cur = pos # current position
while True:
cur += step # go one step further
if array[cur] == array[pos]: # nested parens
count += 1
if array[cur] == other: # found match (but maybe for nested)
count -= 1
if count == 0: # found match for original parens
return cur
except KeyError:
# not a ( or ) or no match found
return None
array = ["(","foo",")","(","bar","(",")",")"]
print([match(array, i) for i, _ in enumerate(array)])
# [2, None, 0, 7, None, 6, 5, 3]
I need to find the first missing number in a list. If there is no number missing, the next number should be the last +1.
It should first check to see if the first number is > 1, and if so then the new number should be 1.
Here is what I tried. The problem is here: if next_value - items > 1:
results in an error because at the end and in the beginning I have a None.
list = [1,2,5]
vlans3=list
for items in vlans3:
if items in vlans3:
index = vlans3.index(items)
previous_value = vlans3[index-1] if index -1 > -1 else None
next_value = vlans3[index+1] if index + 1 < len(vlans3) else None
first = vlans3[0]
last = vlans3[-1]
#print ("index: ", index)
print ("prev item:", previous_value)
print ("-cur item:", items)
print ("nxt item:", next_value)
#print ("_free: ", _free)
#print ("...")
if next_value - items > 1:
_free = previous_value + 1
print ("free: ",_free)
break
print ("**************")
print ("first item:", first)
print ("last item:", last)
print ("**************")
Another method:
L = vlans3
free = ([x + 1 for x, y in zip(L[:-1], L[1:]) if y - x > 1][0])
results in a correct number if there is a gap between the numbers, but if no space left error occurs: IndexError: list index out of range. However I need to specify somehow that if there is no free space it should give a new number (last +1). But with the below code it gives an error and I do not know why.
if free = []:
print ("no free")
else:
print ("free: ", free)
To get the smallest integer that is not a member of vlans3:
ints_list = range(min(vlans3), max(vlans3) + 1)
missing_list = [x for x in ints_list if x not in vlans3]
first_missing = min(missing_list)
However you want to return 1 if the smallest value in your list is greater than 1, and the last value + 1 if there are no missing values, so this becomes:
ints_list = [1] + list(range(min(vlan3), max(vlan3) + 2))
missing_list = [x for x in ints_list if x not in vlan3]
first_missing = min(missing_list)
First avoid using reserved word list for variable.
Second use try:except to quickly and neatly avoid this kind of issues.
def free(l):
if l == []: return 0
if l[0] > 1: return 1
if l[-1] - l[0] + 1 == len(l): return l[-1] + 1
for i in range(len(l)):
try:
if l[i+1] - l[i] > 1: break
except IndexError:
break
return l[i] + 1
How about a numpy solution? Below code works if your input is a sorted integer list with non-duplicating positive values (or is empty).
nekomatic's solution is a bit faster for small inputs, but it's just a fraction of a second, doesn't really matter. However, it does not work for large inputs - e.g. list(range(1,100000)) completely freezes on list comprehension with inclusion check. Below code does not have this issue.
import numpy as np
def first_free_id(array):
array = np.concatenate((np.array([-1, 0], dtype=np.int), np.array(array, dtype=np.int)))
where_sequence_breaks = np.where(np.diff(array) > 1)[0]
return where_sequence_breaks[0] if len(where_sequence_breaks)>0 else array[-1]+1
Prepend the array with -1 and 0 so np.diff works for empty and 1-element lists without breaking existing sequence's continuity.
Compute differences between consecutive values. Seeked discontinuity ("hole") is where the difference is bigger than 1.
If there ary any "holes" return the id of the first one, otherwise return the integer succeeding the last element.
im running a for to check a list of tuples. something in the lines of
for i in range of b:
actual=i
temp1=(actual[0]+1,actual[1])
temp2=(actual[0],actual[1]-1)
temp3=(actual[0],actual[1]+1)
temp4=(actual[0]-1,actual[1])
And i want to make sure the temp's NEVER take the value of the tuple verified on the cycle before. Any idea on how to do this?
First, it seems that there's a problem with your code. range accepts integer input, so if b is an integer, for i in range(b) will give you integers [0, 1, 2, .. , b-1 ] in a list. You can't index into i using [], as you do on the next two lines.
If b is not an integer, but a collection, then you should use something like:
# Assuming b is a collection
for i in range(len(b)):
actual=b[i]
temp1=(actual[0]+1,actual[1])
temp2=(actual[0],actual[1]-1)
temp3=(actual[0],actual[1]+1)
temp4=(actual[0]-1,actual[1])
# Check if this is the first one. If it is, previous won't exist.
if i == 0:
continue
previous = b[i-1]
if previous in [ temp1, temp2, temp3, temp4 ]:
# This is what you want not to happen. Deal with it somehow.
pass
Here's my two cents.
Note that this will make temp(1-4) None if any match.
# assuming b is a collection
for i in range(len(b)):
actual=b[i]
if i!=0:
prev = b[i-1]
if i==0:
prev = [[['something']],[['ridiculous']]] #this is so that the rest of the code works even if index is 0
if (actual[0]+1,actual[1]) != prev: #if it is not the previous item
temp1=(actual[0]+1,actual[1]) #assign temp1
else:
temp1 = None #temp1 would otherwise automatically take on the value of (b[i-1][0]+1,b[i-1][1])
if (actual[0],actual[1]-1) != prev:
temp2=(actual[0],actual[1]-1)
else:
temp2 = None
if (actual[0],actual[1]+1) != prev:
temp3=(actual[0],actual[1]+1)
else:
temp3 = None
if (actual[0]-1,actual[1]) != prev:
temp4=(actual[0]-1,actual[1])
else:
temp4 = None