Compare elements of a character list with a character input - python-3.x

I have a question, I have a character list similar to this:
letras_lista = ['gcjcf', 'afadd', 'ibfah', 'ihdha', 'cdigc', 'kaaci', 'ihiga', 'jbjji', 'hbjjj', 'bcdjg', 'ieika']
And I have a two character input like this:
orden = 'ah'
For this I created this code:
cont = 0
for i in letras_lista:#lista que puse de ejemplo
lista = [i]
for x in lista:
if orden in x:#patron a comparar
cont +=1
print(cont)
Could you tell me if there is a way to optimize the code, I am new to programming and I don't know many ways to do it.
Beforehand thank you very much

A very simple way is to take advantage of the fact that bool is a subclass of int, and sum over the condition:
cont = sum(orden in x for x in letras_lista)
Here is a step by step way to get from your implementation to mine:
First, notice that your inner loop is iterating over a list of length 1. Not only that, but you artificially constructed this list lista. That means that you can get rid of lista and the inner loop, and just run the conditional:
cont = 0
for i in letras_lista:
if orden in i:
cont += 1
Now notice that the boolean value orden in i is equivalent to what you want to add to cont. Since True == 1 in python, and False == 0, you can write
cont = 0
for i in letras_lista:
cont += (orden in i)
Hopefully it is now clear how you can place the boolean condition directly into the sum call.

print(len([i for i in letras_lista if orden in i]))

Related

saving the result of the recursion iterations

This is a standart permutation function. Im tring to return the list of the lists of the permutations)
Could you help me with storaging the result of the recursion iterations? for example this code returns nonsense. It would be perfect if there was no global variable and rezulting list was inside the func
Thanks!
'''
z=[]
def func(N,M=-1,pref=None):
global z
if M == -1:
M = N
pref = pref or []
if M==0:
z.append(pref)
print(pref)
for i in range(N):
if i not in pref:
pref.append(i)
func(N,M-1,pref)
pref.pop()
func(3)
print(z)
'''
You are passing a list (pref variable in for loop) reference to your function and you are removing a single item from that and that's why you are ending with an empty list z.
Create a new list or copy the list before passing it to the function to avoid this situation.
z = []
def func(N, M=-1, pref=None):
global z
if M == -1:
M = N
pref = pref or []
if M == 0:
z.append(pref)
print(pref)
for i in range(N):
if i not in pref:
pref.append(i)
func(N, M - 1, pref[:])
pref.pop()
func(3)
print(z)
For better understand please read this one. List changes unexpectedly after assignment. How do I clone or copy it to prevent this?
If you want to have some kind of accumulator you must pass it to the recursion function, beware it could be a little nightmare.

How can i optimise my code and make it readable?

The task is:
User enters a number, you take 1 number from the left, one from the right and sum it. Then you take the rest of this number and sum every digit in it. then you get two answers. You have to sort them from biggest to lowest and make them into a one solid number. I solved it, but i don't like how it looks like. i mean the task is pretty simple but my code looks like trash. Maybe i should use some more built-in functions and libraries. If so, could you please advise me some? Thank you
a = int(input())
b = [int(i) for i in str(a)]
closesum = 0
d = []
e = ""
farsum = b[0] + b[-1]
print(farsum)
b.pop(0)
b.pop(-1)
print(b)
for i in b:
closesum += i
print(closesum)
d.append(int(closesum))
d.append(int(farsum))
print(d)
for i in sorted(d, reverse = True):
e += str(i)
print(int(e))
input()
You can use reduce
from functools import reduce
a = [0,1,2,3,4,5,6,7,8,9]
print(reduce(lambda x, y: x + y, a))
# 45
and you can just pass in a shortened list instead of poping elements: b[1:-1]
The first two lines:
str_input = input() # input will always read strings
num_list = [int(i) for i in str_input]
the for loop at the end is useless and there is no need to sort only 2 elements. You can just use a simple if..else condition to print what you want.
You don't need a loop to sum a slice of a list. You can also use join to concatenate a list of strings without looping. This implementation converts to string before sorting (the result would be the same). You could convert to string after sorting using map(str,...)
farsum = b[0] + b[-1]
closesum = sum(b[1:-2])
"".join(sorted((str(farsum),str(closesum)),reverse=True))

If elif one liner

if i == len(a):
tempList.extend(b[j:])
break
elif j == len(b):
tempList.extend(a[i:])
break
I am using this in a mergesort-program in Python. Is there any way to put this into a oneliner?
Maybe, but let's give a dedicated non-answer: don't even try.
You don't write your code to be short. You write it so that:
it gets the job done in a straight forward manner
it clearly communicates its meaning to human readers
The above code does that already.
In other words: of course being precise is a valuable property of source code. So, when you have to equally readable pieces of code doing the same thing, and one version is a one-liner, and the other is way more lengthy - then you go for the short version.
But I very much doubt that the above can be expressed as readable as above - with less code.
You can use and and or boolean operations to make a pretty readable one-liner:
l = []
a = [1,2,3,4]
b = [8,9,10]
i = 4
j = 2
l.extend(i == len(a) and b[j:] or j == len(b) and a[i:] or [])
l == [10]
i = 0
j = 3
l.extend(i == len(a) and b[j:] or j == len(b) and a[i:] or [])
l == [10, 1, 2, 3, 4]
This example uses next properties:
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
We have to add or [] to mitigate TypeError: 'bool' object is not iterable exception raised when i == len(a) and j > len(b) (e.g. i == 4 and j == 5).
I'd still prefer an expanded version though.

What does this input via list-comprehension do?

You know when you find a solution via trial and error but you stumbled so much thtat you can't understand the answer now?
Well this is happening to me with this piece:
entr = [list(int(x) for x in input().split()) for i in range(int(input()))]
The input is done by copying and pasting this whole block:
9
8327 0
0070 0
2681 2
1767 0
3976 0
9214 2
2271 2
4633 0
9500 1
What is my list comprehension exactly doing in each step? And taking into account this: How can I rewrite it using for loops?
In fact, your code is not a nested list-comprehension, beause you use list construtor rather than mere list-comprehension.
This line serves as same as your code:
entr = [[int(x) for x in input().split()] for i in range(int(input()))]
To understand this line, you must remember the basic structure of list-comprehension in python, it consists of two component obj and condition with a square brackets surrounding:
lst = [obj condition]
it can be converted to a loop like this:
lst = []
condition:
lst.append(obj)
So, back to this question.
What you need to do now is to break the nested list-comprehension into loop in loop, usually you begin from the condition in latter part, from outer space to inner space. You got:
entr = []
for i in range(int(input())):
entr.append([int(x) for x in input().split()])) # the obj is a list in this case.
And now, you can break the list-comprehension in line 3.
entr = []
for i in range(int(input())):
entry = []
for x in input().split():
entry.append(int(x))
entr.append(entry)
So, now the stuff the original line can be easily understand.
the program construct a entry list named entr;
the program ask for user input and convert the input string into an int, which is the number of the entrys you want to input(assume it is num);
the program ask for user input for num times, each time you should input something seperate with spaces.
The program split every string into a list (named entry in above code) you input with str.split() method (with parameter sep default to space). And append each entry list in every loop.
for every element in the entry list, it converted to int.
My English may be poor, feel free to improve my answer:)
That is equivalent to this:
entr = []
for i in range(int(input())):
row = []
for x in input().split():
row.append(int(x))
entr.append(row)
You can copy-paste that into a list comprehension in a couple steps. First the inner loop/list:
entr = []
for i in range(int(input())):
row = [int(x) for x in input().split()]
entr.append(row)
Without the row variable:
entr = []
for i in range(int(input())):
entr.append([int(x) for x in input().split()])
Then the outer loop/list (copied over multiple lines for clarity):
entr = [
[int(x) for x in input().split()]
for i in range(int(input()))
]
You have that same nested comprehension except that the inner one has been written as a generator passed to the list constructor so it looks like list(int(x) for x in input().split()) instead of [int(x) for x in input().split()]. That's a little more confusing than using a list comprehension.
I hope that explanation helps!

Julia: Unique sets of n elements with replacement

Given a vector v = [1,..,n], I try to compute all unique sets of n elements with replacements in julia.
Since I want to do this for larger values of n, I'm looking for an efficient solution, possibly using iterators.
For example, let's consider v = [1, 2, 3]: This should results in [1,1,1], [1,1,2], [1,1,3], [1,2,2], [1,2,3], [1,3,3], [2,2,2], [2,2,3], [2,3,3], [3,3,3]. With unique, I mean that if [1,1,2] is a solution, any of its permutations [1,2,1], [2,1,1] is not.
My current solution is based on the partitions function, but does not allow me to restrict the computation on the elements [1,..,n]
for i in n:n^2
for j in partitions(i, n)
## ignore sets which exceed the range [1,n]
if maximum(j) <= n
## accept as solution
end
end
end
In julia v0.5.0, combinatorics.jl has a with_replacement_combinations method.
julia> collect(with_replacement_combinations(1:4,3))
20-element Array{Array{Int64,1},1}:
[1,1,1]
[1,1,2]
[1,1,3]
[1,1,4]
[1,2,2]
[1,2,3]
[1,2,4]
[1,3,3]
[1,3,4]
[1,4,4]
[2,2,2]
[2,2,3]
[2,2,4]
[2,3,3]
[2,3,4]
[2,4,4]
[3,3,3]
[3,3,4]
[3,4,4]
[4,4,4]
I guess, it doesn't get shorter than one-line (using Iterators).
using IterTools
import Combinatorics.combinations
n=3
collect(imap(c -> Int[c[k]-k+1 for k=1:length(c)],combinations(1:(2n-1),n)))
I believe you're looking for the product function from the Iterators package. In your case product(v,v,v) should do what's required.
Here is a function to calculate the required collection:
function calcset(n=3)
res = []
for c in combinations([1:(2n-1)],n-1)
c3 = [c,2n].-[0,c]
push!(res,vcat([fill(i,c3[n-i+1]-1) for i=1:n]...))
end
return res
end
calcset(3)
There is probably some better way to code this, but this should be enough.
Notice the result is generated through repeated push!s, so this is easily turned into an iterator, if necessary.
And in iterator form:
import Base: start, next, done, eltype, length
type ImageTypeIterator
inneritr::Base.Combinations{Array{Int64,1}}
n::Int
end
imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n-1),n)
eltype(itr::ImageTypeIterator) = Array{Int64,1}
start(itr::ImageTypeIterator) = start(itr.inneritr)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
c3 = [c,2*itr.n].-[0,c]
(vcat([fill(i,c3[itr.n-i+1]-1) for i=1:itr.n]...),s)
end
done(itr::ImageTypeIterator,s) = done(itr.inneritr,s)
length(itr::ImageTypeIterator) = length(itr.inneritr)
# test with [1,2,3]
for t in imagetype(3) println(t) ; end
The test at the end should print the collection set in the question.
BTW the name ImageTypeIterator is an attempt to characterize the collection as the distinct types of sizes of preimages when looking at a function f : [1:n] -> [1:n]. But a different interpretation might be appropriate. Other names suggestion welcome in comments.
A faster?/clearer? implementation could use:
imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n),n)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
v = Array(Int,itr.n)
j = 1 ; p = 1
for k=1:itr.n
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
(v,s)
end
Its the same logic as above, but without too much slicing. The logic takes a subset of 2n-1 and views non-gaps as repeated values and gaps as a trigger to advance to next value.
OK, a simpler version using Iterators.jl:
using Iterators
function ff(c)
v = Array(Int,length(c))
j = 1 ; p = 1
for k=1:length(c)
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
v
end
# test
n = 3
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end
This is perhaps the simplest version, although equivalent in methods to the other answers.
And in the spirit of brevity:
using Iterators
ff(c) = begin
j=1;p=1; [(while !(j in c) j+=1;p+=1 ; end ; j+=1 ; p) for k=1:length(c)]
end
n = 3 # test
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end

Resources