Loop over list with and condition - python

I am trying to write a code for below pseudocode
for all element in list do
match and condition
if all match
return True
for example, List A=[1,2,3,4,5],B=10
What I want is like
def match():
for i in range(len(A)):
if B%A[0]==0 and B%A[1]==0 and B%A[2]==0 and B%A[3]==0 and B%A[4]==0: #Generate all these
#and condition one by one
#automatically in this function
return True
How can I do?
NOTE:I am asking about write code match and condition with a loop, not write a remainder

Try this one:
result = all( [(B%a==0) for a in A] )

You can use a pythonic one liner
result = all(B % x == 0 for x in A)
Or maybe in a slightly more familiar syntax
res = True
for x in A:
if B % x != 0:
res = False
break

Related

Determining validity if sum divisible by 10

Outline:
Find out if id is acceptable. Acceptable parameters is the sum of the
digits for each part of the id. If each sum is evenly divisible by 10
then the function returns the string "Acceptable", otherwise it
returns the string "Unacceptable".
Example:
isValid('123-12-134') → 'Unacceptable'
isValid('550-55-055') → 'Acceptable'
isValid('123-55-055') → 'Unacceptable'
I've tried converting the entire string into an int, but get some differing results in determining divisible by 10.
My attempted code is:
def isValid(id) :
id=id.replace('-','0')
id=int(id)
if id % 10==0:
return "Valid"
else:
return "Invalid"
Thanks in advance!
You might as well return boolean variables and just compare the output to determine what to print:
def summation(item):
return sum([int(i) for i in item])
def isValid(id_) :
id_part = id_.split('-')
result = [summation(item) % 10 == 0 for item in id_part]
return all(result)
Essentially this loops through all the characters in the split string and determines their sum - 3 sums per provided id.
Then we convert the summed list to a boolean list using your condition of x%10 == 0.
Finally we look at all() the elements of this boolean list to determine if it all True or contains a False.
If all are True then the return of isValid(id_) is True else it is False.
Usage:
ids = ['123-12-134', '550-55-055', '123-55-055']
for id_ in ids:
validity = isValid(id_)
print("Acceptable") if validity else print("Unacceptable")
Output:
Unacceptable
Acceptable
Unacceptable
you mean like this?
sentence = "123-123-123"
a = sum(int(x) for x in sentence if x.isdigit())
Hope this code can help you.
Found on this answer
you mean like this?
sentence = "123-123-123"
a = sum(int(x) for x in sentence if x.isdigit())
return a % 10 == 0
Hope this code can help you.
Found on this answer
We want to short-circuit the 'Unacceptable'.
def isValid(ID):
s = 0
for x in ID:
if x.isdigit():
s += int(x)
else:
if s % 10 == 0:
s = 0
else:
return 'Unacceptable'
return 'Acceptable' if s%10 == 0 else 'Unacceptable'
The solution requires splitting the string into parts using hyphens as separators, which are tested to ensure that the sum of each part's characters is a multiple of 10. The test fails if any of the parts are not a multiple of ten, so each part must be greater than or equal to ten. If any part fails, the string fails, so, there is no need to continue testing if a failed part is found. Acceptable must be returned if the string passes, or Unacceptable if it fails.
This single function solution is easy to read:
def teststring(test):
for part in test.split('-'):
part_failed = int(part)<10
if not part_failed:
sum_chars = 0
for char in part:
sum_chars += int(char)
part_failed = ((sum_chars % 10) != 0)
if part_failed: break
return 'Acceptable' if not part_failed else 'Unacceptable'
This solution uses list comprehension in two functions:
def testpart_comprehended(part):
return ((int(part)>=10) and ((sum(int(char) for char in part) % 10) == 0))
def acceptable_comprehended(test):
return 'Acceptable' if all(testpart_comprehended(part) for part in test.split("-")) else 'Unacceptable'
This solution uses list comprehension in one function:
def all_comprehended(test):
return 'Acceptable' if all(((int(part)>=10) and ((sum(int(char) for char in part) % 10) == 0)) for part in test.split("-")) else 'Unacceptable'
These answers are all too understandable. Please use
isValid = lambda x: (any(sum(map(int, s)) % 10 for s in x.split('-'))
* 'un' + 'acceptable').title()
Unacceptable
for example
>>> isValid('123-123')
'Unacceptable'
>>> isValid('123-127')
'Unacceptable'
>>> isValid('127-127')
'Acceptable'

Isomorphic Strings (the easy way?)

So I have been trying to solve the Easy questions on Leetcode and so far I dont understand most of the answers I find on the internet. I tried working on the Isomorphic strings problem (here:https://leetcode.com/problems/isomorphic-strings/description/)
and I came up with the following code
def isIso(a,b):
if(len(a) != len(b)):
return false
x=[a.count(char1) for char1 in a]
y=[b.count(char1) for char1 in b]
return x==y
string1 = input("Input string1..")
string2 = input("Input string2..")
print(isIso(string1,string2))
Now I understand that this may be the most stupid code you have seen all day but that is kinda my point. I'd like to know why this would be wrong(and where) and how I should further develop on this.
If I understand the problem correctly, because a character can map to itself, it's just a case of seeing if the character counts for the two words are the same.
So egg and add are isomorphic as they have character counts of (1,2). Similarly paper and title have counts of (1,1,1,2).
foo and bar aren't isomorphic as the counts are (1,2) and (1,1,1) respectively.
To see if the character counts are the same we'll need to sort them.
So:
from collections import Counter
def is_isomorphic(a,b):
a_counts = list(Counter(a).values())
a_counts.sort()
b_counts = list(Counter(b).values())
b_counts.sort()
if a_counts == b_counts:
return True
return False
Your code is failing because here:
x=[a.count(char1) for char1 in a]
You count the occurrence of each character in the string for each character in the string. So a word like 'odd' won't have counts of (1,2), it'll have (1,2,2) as you count d twice!
You can use two dicts to keep track of the mapping of each character in a to b, and the mapping of each character in b to a while you iterate through a, and if there's any violation in a corresponding character, return False; otherwise return True in the end.
def isIso(a, b):
m = {} # mapping of each character in a to b
r = {} # mapping of each character in b to a
for i, c in enumerate(a):
if c in m:
if b[i] != m[c]:
return False
else:
m[c] = b[i]
if b[i] in r:
if c != r[b[i]]:
return False
else:
r[b[i]] = c
return True
So that:
print(isIso('egg', 'add'))
print(isIso('foo', 'bar'))
print(isIso('paper', 'title'))
print(isIso('paper', 'tttle')) # to test reverse mapping
would output:
True
False
True
False
I tried by creating a dictionary, and it resulted in 72ms runtime.
here's my code -
def isIsomorphic(s: str, t: str) -> bool:
my_dict = {}
if len(s) != len(t):
return False
else:
for i in range(len(s)):
if s[i] in my_dict.keys():
if my_dict[s[i]] == t[i]:
pass
else:
return False
else:
if t[i] in my_dict.values():
return False
else:
my_dict[s[i]] = t[i]
return True
There are many different ways on how to do it. Below I provided three different ways by using a dictionary, set, and string.translate.
Here I provided three different ways how to solve Isomorphic String solution in Python.
from itertools import zip_longest
def isomorph(a, b):
return len(set(a)) == len(set(b)) == len(set(zip_longest(a, b)))
here is the second way to do it:
def isomorph(a, b):
return [a.index(x) for x in a] == [b.index(y) for y in b]

Overlapping lists function returns False when True in python

I'm a programming semi-noob and am working through Torbjoern Lager's 46 Simple Python Exercises. This is number 10: Define a function overlapping() that takes two lists and returns True if they have at least one member in common, False otherwise. You may use your is_member() function, or the in operator, but for the sake of the exercise, you should (also) write it using two nested for-loops.
def over(list1,list2):
for i in list1:
for j in list2:
return i==j
I thought I had a nice, simple solution, but it can't recognize that the lists overlap, unless the overlapping elements are the first ones.
over(["a","b","c","d"],["e","f","a","h"])
returns False
over(["a","b","c","d"],["a","f","g","h"])
returns True
For some reason, it's not searching through all of the combinations. Any help would be appreciated.
It's not searching through all the combinations because you're returning on the first iteration of the nested loop. You could do this:
def over(list1,list2):
for i in list1:
for j in list2:
if i == j:
return True
return False
This returns True as soon as any overlap is found. If no overlap is ever found, it'll get to the last line and return False.
The problem is that you return i==j on the first iteration. Your function will justs compare list1[0] and list2[0]. The solution is to add if.
Here is an example:
def over(list1,list2):
for i in list1:
for j in list2:
if i == j:
return True
return False
You should be testing with an if as suggested in the other answers as you are returning after the very first iteration but using any would be a nicer approach:
def over(list1,list2):
return any(i ==j for i in list1 for j in list2)
Which is equivalent to:
def over(list1,list2):
for i in list1:
for j in list2:
if i == j:
return True
return False
short circuiting on a match and returning True if there is any match or returning False if there are none.
Or using sets for larger input would be the fastest approach:
def over(list1, list2):
return not set(list1).isdisjoint(list2)
if not set(list1).isdisjoint(list2) is True we have at least one common element.
When you execute the "return" stament de execution stops there, like it happens in Java. It returns true because you have 'a' in the first position in both arrays.
You can try this:
result = False;
for i in list1:
for j in list2:
if i == j:
result=True;
return result
If you want it more efficient:
for i in list1:
for j in list2:
if i == j:
return True;
return False;

Python, check if sets check out

I have made the function, but I need to make a guess so it will run through the function and check if it fits, if not, start over again with new numbers.
If I find a set that works, the loop should break, the problem is that I am new to python and math programming.
def checkStuff(X):
ok = True
#i.
if(min(X) <= 0):
ok = False
#ii.A
A = set()
for x in X:
A.add(x % 2)
#ii.B
B = set()
for y in X:
B.add(y**2)
#ii.C
C = set()
for z in X & B:
C.add(z**0.5)
#ii.D
D = set()
for w in C:
D.add(w**2)
#iii.
if(len(X)<=0):
ok = False
#iv.
if(len(X) not in X):
ok = False
#v.
if len(A) in X:
ok = False
#vi.
if sum(X) not in B:
ok = False
#vii.
if sum(X&B) in B:
ok = False
#viii.
if sum(C.union(D)) not in X:
ok = False
return ok
without giving you the exact code, try looking at the while loop and the random function
Your function can be simplified and optimized, returning as soon as possible, avoiding further computations... for compactness I used set comprehensions instead of your loops
def checkStuff(X):
if(min(X) <= 0): return False
if(len(X)<=0): return False
if(len(X) not in X): return False
A = {x % 2 for x in X}
if len(A) in X: return False
B = {x**2 for x in X}
if sum(X) not in B: return False
if sum(X&B) in B: return False
C = {xb**0.5 for xb in X&B}
D = {c**2 for c in C}
if sum(C.union(D)) not in X: return False
return True
Assuming that you have a function that returns a list of trial sets or, possibly better, yields a new trial set for each loop, and that you want to use ONLY the first X that matches your conditions, then you can write your stuff like this
for X in generate_trial_sets():
if checkStuff(X):
do_stuff(X)
break
else:
print("No X was generated matching the criteria")
...
Note that the else clause is aligned correctly, because Python has a for ... else .. control flow construct.
Blind Attempt at a generate_trial_sets Function
Given that each X is a set of numbers (integers? reals? complex numbers? who knows? you, but you didn't care to tell...) and that we don't know how many numbers you want in the set, and also that you want to stop the iteration somehow, I'd write
def generate_trial_sets(nmin=1, nmax=5,
xmin=0.0, xmax=10.0, iterations=10):
from random import randint
for _ in range(iterations):
n = randint(nmin,nmax+1)
x = {n}
for i in range(1,n):
x.add((xmax-xmin)*random()+xmin)
yield x
When you call it like
for X in generate_trial_sets():
without modifying the default args, you get back 10 sets of length comprised between 1 and 5, with real values comprised between 0 and 10 (one of the values is equal to the length, so one of your tests is automatically fulfilled).
To use different parameters, specify them at the invocation:
for X in generate_trial_sets(nmin=6,nmax=6,xmax=100.0,iterations=200):
This is not a solution of your problem but if you understand the logic you'll get started in the right direction or, at least, I hope so...

How can I return false if more than one number while ignoring "0"'s?

This is a function in a greater a program that solves a sudoku puzzle. At this point, I would like the function to return false if there is more then 1 occurrence of a number unless the number is zero. What do am I missing to achieve this?
L is a list of numbers
l =[1,0,0,2,3,0,0,8,0]
def alldifferent1D(l):
for i in range(len(l)):
if l.count(l[i])>1 and l[i] != 0: #does this do it?
return False
return True
Assuming the list is length 9, you can ignore the inefficiency of using count here (Using a helper datastructure - Counter etc probably takes longer than running .count() a few times). You can write the expression to say they are all different more naturally as:
def alldifferent1D(L):
return all(L.count(x) <= 1 for x in L if x != 0)
This also saves calling count() for all the 0's
>>> from collections import counter
>>> def all_different(xs):
... return len(set(Counter(filter(None, xs)).values()) - set([1])) == 0
Tests:
>>> all_different([])
True
>>> all_different([0,0,0])
True
>>> all_different([0,0,1,2,3])
True
>>> all_different([1])
True
>>> all_different([1,2])
True
>>> all_different([0,2,0,1,2,3])
False
>>> all_different([2,2])
False
>>> all_different([1,2,3,2,2,3])
False
So we can break this down into two problems:
Getting rid of the zeros, since we don't care about them.
Checking if there are any duplicate numbers.
Striping the zeros is easy enough:
filter(lambda a: a != 0, x)
And we can check for differences in a set (which has only one of each element) and a list
if len(x) == len(set(x)):
return True
return False
Making these into functions we have:
def remove_zeros(x):
return filter(lambda a: a != 0, x)
def duplicates(x):
if len(x) == len(set(x)):
return True
return False
def alldifferent1D(x):
return duplicates(remove_zeros(x))
One way to avoid searching for every entry in every position is to:
flags = (len(l)+1)*[False];
for cell in l:
if cell>0:
if flags[cell]:
return False
flags[cell] = True
return True
The flags list has a True at index k if the value k has been seen before in the list.
I'm sure you could speed this up with list comprehension and an all() or any() test, but this worked well enough for me.
PS: The first intro didn't survive my edit, but this is from a Sudoku solver I wrote years ago. (Python 2.4 or 2.5 iirc)

Categories