How to check the specific element in string are equal in python? - python

There is a two input first input represent the index of the second input.I need to find the 'X' position of second input are same or not?
input:
123X56XX
Ahjutruu
Output:
True
Example:
X in input one at 4,7,8
position of 4,7,8 in second input is 'u' all are same so i need to print "true"
I tried using enumerate function but not came:
a="123X56XX"
b="Ahjutruu"
xi=[]
for i,val in enumerate(a):
if val=='X':
xi.append(i)
print(xi)
#next step only i dont know how to doo please help
Next i dont know how to check

Put all values of given indexes of xi in set, the length of this set must equal to 1:
xi = [i for i, c in enumerate(a) if c == 'X']
len(set([b[i] for i in xi])) == 1

you can do like this
a = "123X56XX"
b = "Ahjutruu"
status = len({j for i,j in zip(a,b) if i=='X'}) == 1
print(status)

An optional solution:
a="123X56XX"
b="Ahjutruu"
c = list([b[i] for i in range(len(a)) if a[i] == "X"]) # a sublist of the characters from b that correspond to "X" in a
s = set(c) # a set with the elements of c; a set has no duplicated elements, so if all of c's items are the same, s will only have one element
print(len(s) == 1)

the logic is added for matching the X places in a
a = "123X56XX"
b = "Ahjutruu"
xi = []
allSame = True
for i, val in enumerate(a):
if val == 'X':
xi.append(i)#saving the indices
allSame = len(a) == len(b) # length must be same
prev = None
for v in xi:
if not allSame:
break
if prev is None:
prev = b[v] # if previous value is not set setting it
else:
allSame = prev == b[v] # matching with previous value in b's list
print(allSame)

Minor addition to your code.
a="123X56XX"
b="Ahjutruu"
xi=[]
result = False
for i,val in enumerate(a):
if val=='X':
xi.append(i)
print(xi[0])
for index, value in enumerate(xi):
if index < len(xi) - 1:
if b[value] == b[xi[index+1]]:
result = True
else:
result = False
print(result)

Related

Code for consecutive strings works but can't pass random tests

In this problem, I'm given an array(list) strarr of strings and an integer k. My task is to return the first longest string consisting of k consecutive strings taken in the array. My code passed all the sample tests from CodeWars but can't seem to pass the random tests.
Here's the link to the problem.
I did it in two days. I found the max consecutively combined string first. Here's the code for that.
strarr = []
def longest_consec(strarr, k):
strarr.append('')
length = len(strarr)
cons_list = []
end = k
start = 0
freq = -length/2
final_string = []
largest = max(strarr, key=len, default='')
if k == 1:
return largest
elif 1 < k < length:
while(freq <= 1):
cons_list.append(strarr[start:end])
start += k-1
end += k-1
freq += 1
for index in cons_list:
final_string.append(''.join(index))
return max(final_string, key=len, default='')
else:
return ""
Since that didn't pass all the random tests, I compared the combined k strings on both sides of the single largest string. But, this way, the code doesn't account for the case when the single largest string is in the middle. Please help.
strarr = []
def longest_consec(strarr, k):
strarr.append('')
length = len(strarr)
largest = max(strarr, key=len, default='')
pos = int(strarr.index(largest))
if k == 1:
return largest
elif 1 < k < length:
prev_string = ''.join(strarr[pos+1-k:pos+1])
next_string = ''.join(strarr[pos:pos+k])
if len(prev_string) >= len(next_string):
res = prev_string
else:
res = next_string
return res
else:
return ""
print(longest_consec(["zone", "abigail", "theta", "form", "libe"], 2))
Let's start from the first statement of your function:
if k == 1:
while(p <= 1):
b.append(strarr[j:i])
j += 1
i += 1
p += 1
for w in b:
q.append(''.join(w))
return max(q, key=len)
Here q is finally equal strarr so you can shorten this code to:
if k == 1:
return max(strarr, key=len)
I see that second statement's condition checks if k value is between 1 and length of string array inclusive:
elif k > 1 and k <= 2*a:
...
If you want no errors remove equality symbol, last element of every array has index lesser than its length (equal exactly length of it minus 1).
Ceiling and division is not necessary in a definition, so you can shorten this:
a = ceil(len(strarr)/2)
into this:
a = len(strarr)
then your elif statement may look like below:
elif 1 < k < a: # Same as (k > 1 and k < a)
...
again, I see you want to concatenate (add) the longest string to k next strings using this code:
while(p <= 1):
b.append(strarr[j:i])
j += k-1
i += k-1
p += 1
for w in b:
q.append(''.join(w))
return max(q, key=len)
the more clearer way of doing this:
longest = max(strarr, key=len) # Longest string in array.
index = 0 # Index of the current item.
for string in strarr:
# If current string is equal the longest one ...
if string == longest:
# Join 'k' strings from current index (longest string index).
return ''.join(strarr[index:index + k])
index += 1 # Increase current index.
And the last statement which is:
elif k > 2*a or k<1:
return ""
if all previous statements failed then value is invalid so you can instead write:
return "" # Same as with else.
Now everything should work. I advice you learning the basics (especially lists, strings and slices), and please name your variables wisely so they are more readable.
You can try this as well
this has passed all the test cases on the platform you suggested.
def longest_consec(strarr, k):
i = 0
max_ = ""
res = ""
if (k<=0) or (k>len(strarr)):
return ""
while i<=(len(strarr)-k):
start = "".join(strarr[i:i+k])
max_ = max(max_, start, key=len)
if max_==start:
res=strarr[i:i+k]
i+=1
return max_
#output: ["zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"], 2 -> abigailtheta
#output: ["zones", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"],2 -> zonesabigail

Find the difference between two strings of uneven length in python

a = 'abcdfjghij'
b = 'abcdfjghi'
Output : j
def diff(a, b):
string=''
for val in a:
if val not in b:
string=val
return string
a = 'abcdfjghij'
b = 'abcdfjghi'
print(diff(a,b))
This code returns an empty string.
Any solution for this?
collections.Counter from the standard library can be used to model multi-sets, so it keeps track of repeated elements. It's a subclass of dict which is performant and extends its functionality for counting purposes. To find differences between two strings you can mimic a symmetric difference between sets.
from collections import Counter
a = 'abcdfjghij'
b = 'abcdfjghi'
ca = Counter(a)
cb = Counter(b)
diff = (cb-ca)+(ca-cb) # symmetric difference
print(diff)
#Counter({'j': 1})
Its hard to know exactly what you want based on your question. Like should
'abc'
'efg'
return 'abc' or 'efg' or is there always just going to be one character added?
Here is a solution that accounts for multiple characters being different but still might not give your exact output.
def diff(a, b):
string = ''
if(len(a) >= len(b)):
longString = a
shortString = b
else:
longString = b
shortString = a
for i in range(len(longString)):
if(i >= len(shortString) or longString[i] != shortString[i]):
string += longString[i]
return string
a = 'abcdfjghij'
b = 'abcdfjghi'
print(diff(a,b))
if one string just has one character added and i could be anywhere in the string you could change
string += longString[i]
to
string = longString[i]
In your example, there are 2 differences between the 2 strings :
The letter g and j.
I tested your code and it returns g because all the other letters from are in b:
a = 'abcdfjghij'
b = 'abcdfjhi'
def diff(a, b):
string=''
for val in a:
if val not in b:
string=val
return string
print(diff(a,b))
updated
But you have j twice in a. So the first time it sees j it looks at b and sees a j, all good. For the second j it looks again and still sees a j, all good.
Are you wanting to check if each letter is the same as the other letter in the same sequence, then you should try this:
a = 'abcdfjghij'
b = 'abcdfjghi'
def diff(a, b):
if len(a)>len(b):
smallest_len = len(b)
for index, value in enumerate(a[:smallest_len]):
if a[index] != b[index]:
print(f'a value {a[index]} at index {index} does not match b value {b[index]}')
if len(a) == len(b):
pass
else:
print(f'Extra Values in A Are {a[smallest_len:]}')
else:
smallest_len = len(a)
for index, value in enumerate(b[:smallest_len]):
if a[index] != b[index]:
print(f'a value {a[index]} at index {index} does not match b value {b[index]}')
if len(a) == len(b):
pass
else:
print(f'Extra Values in B Are {b[smallest_len:]}')
diff(a, b)
if I understand correctyl your question is:
"given 2 strings of different length, how can I find the characters
that are different between them?"
So judging by your example, this implies you want either the characters that are only present in 1 of the strings and not on the other, or characters that might be repeated and which count is different in between the two strings.
Here's a simple solution (maybe not the most efficient one), but one that's short and does not require any extra packages:
**UPDATED: **
a = 'abcdfjghij'
b = 'abcdfjghi'
dict_a = dict( (char, a.count(char)) for char in a)
dict_b = dict( (char, b.count(char)) for char in b)
idx_longest = [dict_a, dict_b].index(max([dict_a, dict_b], key = len))
results = [ k for (k,v) in [dict_a, dict_b][idx_longest].items() if k not in [dict_a, dict_b][1-idx_longest].keys() or v!=[dict_a, dict_b][1-idx_longest][k] ]
print(results)
> ['j']
or you can try with other pair of strings such as
a = 'abcaa'
b = 'aaa'
print(results)
> ['b', 'c']
as 'a' is in both string an equal number of times.

I would like that as soon as we meet three consecutive True or less (1 or 2) in a list, they are replaced by False

I would like that as soon as we meet three consecutive True or less (1 or 2) in a list, they are replaced by False. Would you please know how to do this?
For example :
alist = [True,True,True,False,False,True,True,False,False,True,True,True,True,True,False,True,True,True,True]
The input is =
[False,False,False,False,False,False,False,False,False,False,False,False,True,True,False,False,False,False,True]
This code below only works for three True consecutive.
alist = [True,True,True,False,False,True,True,False,False,True,True,True,True,True,False,True,True,True,True]
tmp= []
count = 0 # counter for consecutive values of True
for ind,val in enumerate(alist) :
if val is False:
tmp.append(val) # add ele to the temporary list
count=0 # reset the counter of consecutive values of True
else :
tmp.append(val)
count+=1
if count == 3: # if this is the 4th (or bigger) value of True
k = ind - 2
for j in range(k,ind+1):
tmp[j] = False
count = 0
alist=tmp # assign the temporary list to the variable
I have changed your code a bit. Set the count to 0 when you get a False. If you get a True increment the count and if count <= 3 push False in the list otherwise push True.
alist = ([True,True,True,False,False,True,True,False,False,
True,True,True,True,True,False,True,True,True,True])
tmp= []
count = 0 # counter for consecutive values of True
for val in alist :
count = count * val + val
if count <= 3:
tmp.append(False)
else:
tmp.append(True)
alist=tmp

Recursive Elimination of Character Groups in a String in Python

Given a string with a series of Rs and Gs, search for a way to eliminate them by groups. You can ONLY eliminate if characters are grouped (at least 2).
Example 1: RGRRRGGGRR
v v v
RGRRRGGGRR = RGGGGRR = RRR = {empty}, thus there is a possible solution.
Example 2: GGGRGRGRG
v
GGGRGRGRG = RGRGRG, can no longer find groups, thus there is NO possible solution.
I made an initial recursive function but it ends with no solution even though there is a possible solution.
def fn(string, start):
l = len(string)
if l-start > 0:
counter, isPop = 0, False
if string[start] == 'R':
while counter + start < l and string[counter + start] == 'R': counter+=1
if counter > 1: # If there is the same letter adjacent to the current letter being checked, it will pop this group.
for i in range(counter):
string.pop(start)
isPop = True
if not isPop and start+counter == l: return False # Returns false if previous action did not pop and
else: return fn(string, 0 if isPop else start+counter) # Letter being checked is the last element (it means
# that there are still elements in the string that can
else: # no longer be grouped and eliminated.
while counter + start < l and string[counter + start] == 'G': counter+=1
if counter > 1:
for i in range(counter):
string.pop(start)
isPop = True
if not isPop and start+counter == len(string): return False
else: return fn(string, 0 if isPop else start+counter)
if string: return False
else: return True
ways = []
string = input()
for j in range(len(string)): # Iterates through every position in the list and calls the fn just to see if it is possible.
if True in ways: # If there is a possible solution, it breaks the loop and prints "possible"
break
ways.append(fn(list(string), j))
if True in ways: print("Possible")
else: print("Impossible")
Cases that my algo doesn't work (returns false but there is actually a way):
1. GGRRGRRRRGGGGRGRGG
v v v v v v
GGRRGRRRRGGGGRGRGG = GGRRGRRRRRGRGG = GGRRGGRGG = GGRRRGG = GGRRRGG = GGGG = {empty}
2. GRRRGRRRGRRRGRRRGR
v v v v v v
GRRRGRRRGRRRGRRRGR = GRRRGRRRGGRRRGR = GRRRGRRRGGGR = GRRRGRRRR = GGRRRR = RRRR = {empty}
You can use recursion with a generator. Additionally, applying itertools.groupby to produce groupings up front leads to a shorter solution:
from itertools import groupby as gb
def get_groups(s, chain=[]):
if not s:
yield chain+[s]
else:
r = [list(b) for _, b in gb(s)]
for i, a in enumerate(r):
if len(a) > 1:
t = ''.join(map(''.join, [*r[:i], *([] if i >= len(r) else r[i+1:])]))
yield from get_groups(t, chain+[s])
cases = ['RGRRRGGGRR', 'GGGRGRGRG', 'GGRRGRRRRGGGGRGRGG', 'GRRRGRRRGRRRGRRRGR']
for case in cases:
print(f'{case}: {any(get_groups(case))}')
Output:
RGRRRGGGRR: True
GGGRGRGRG: False
GGRRGRRRRGGGGRGRGG: True
GRRRGRRRGRRRGRRRGR: True
get_groups produces an empty list [] if there is no possible path whereby the input is completed reduced to an empty string by removing groupings, and a listing of all the possible paths to an empty string.
I believe your primary issue with respect to debugging this code is your coding style.
Besides being messy, you have ambiguous return situations; your 'R' and 'G' parallel blocks aren't identical; you fail to update the array length variable after popping the array; you appear to start the recursion at the wrong index.
The best I could come up with cleaning up your code is the following that passes one more case but still fails one:
def fn(characters, start):
length = len(characters)
if length - start > 0:
for character in ['R', 'G']:
counter = 0
isPop = False
if characters[start] == character:
while start+counter < length and characters[start+counter] == character:
counter += 1
if counter > 1:
# If there is the same letter adjacent to the current
# letter being checked, it will pop this group.
for _ in range(counter):
characters.pop(start)
isPop = True
length -= 1 # we've shortened the array
if not isPop and start+counter == length:
# Returns false if previous action did not pop and
# letter being checked is the last element (it means
# that there are still elements in characters that can
# no longer be grouped and eliminated.
return False
return fn(characters, start if isPop else start+counter)
if characters:
return False
return True
My own solution is akin to that of #Ajax1234 as far as groupby goes:
from itertools import groupby
def eliminate_groups(string):
if not string: # base case of recursion
return True
# "RGRRRGGGRR" -> ['R', 'G', 'RRR', 'GGG', 'RR']
groups = [''.join(g) for _, g in groupby(string)]
for index, group in enumerate(groups):
if len(group) < 2:
continue
reduced = groups[:index] + groups[index+1:] # a deficient copy
status = eliminate_groups(''.join(reduced))
if status: # one of the variants succeeded!
return status
return False # all of the variants failed!
if __name__ == '__main__':
strings = ["RGRRRGGGRR", "GGGRGRGRG", "GGRRGRRRRGGGGRGRGG", "GRRRGRRRGRRRGRRRGR"]
for string in strings:
print(string, eliminate_groups(string))
OUTPUT
> python3 test.py
RGRRRGGGRR True
GGGRGRGRG False
GGRRGRRRRGGGGRGRGG True
GRRRGRRRGRRRGRRRGR True
>

Can I check if an element exists within a nested list at a specific index?

Someone recently posted this question. Before I could respond with my answer, the post was removed. The request was to check for the existence of an integer value within a 4x4 array without defining a function.
Given a value and a column the answer would be:
if sum([True for x in array2d if x[col] == value]) > 0:
#!/usr/bin/env python3
import random
if __name__ == "__main__":
# initialize a 4 x 4 array with integers
array2d = [[x for x in range(0,4)] for i in range(0,4)]
# shuffle the numbers for variability
for i in range(1,4):
random.shuffle(array2d[i])
# print each row for validation
for row in array2d:
print(row)
# pick colum 2 to check for value 2
col = 2
value = 2
if sum([True for x in array2d if x[col] == value]) > 0:
print("value {0} found in colum {0}".format(value, col))
else:
print("value {0} missing in colum {0}".format(value, col))
# pick colum 3 to check for value 2
col = 2
value = 20 # This vauel will always be missing.
if any([True for x in array2d if x[col] == value]) > 0:
print("value {0} found in colum {0}".format(value, col))
else:
print("value {0} missing in colum {0}".format(value, col))
your going to want to traverse the 2 dimensional array with nested for loops.
first initialize a boolean isFound to false. and ints i and j to -1. use iterators i and j to represent the current row and current column being search. check if the waldo that u are searching for is in the given array's column i row j. if so u have found waldo, so record the location by storing a tuple with i and j, and change your isFound boolean to true. if not increment the iterators and keep traversing the array.
waldo = #value being searched
array[][] = #array being traversed
isFound = False
i = -1
j = -1
for i in range(4):
for j in range(4):
if array[i][j] == waldo:
isFound = True
location = (i, j)
print('found waldo? ', isFound)
print('location: array[', i, '][', j, ']')
output (examples):
found waldo? true
location: array[3][2]
found waldo? false
location: array[-1][-1]

Categories