Python, print colored duplicates found in 2 list - python-3.x

I'm 63 and just started with Python (My first steps with Udemy).
I'm Croatian so this is croatian language in program but you will understand when you run a program. I know it can be cleaner, shorter, more elegant etc, but as I mentioned before - I'm beginner.
import random
jedan = random.sample(range(1,99),15)
dva = random.sample(range(1,99),15)
def raspaljot(jedan, dva, i):
for x in jedan:
for y in dva:
if y == x:
index1 = jedan.index(x)
index1_str = str(index1)
index2 = dva.index(y)
index2_str = str(index2)
i += 1
x = str(x)
print(" Broj \033[31m" + x + "\033[0m,je dupli i nalazi se u listi jedan: na poziciji: \033[34m"
+ index1_str + "\033[0m a u listi dva na poziciji: \033[35m"+ index2_str + "\033[0m")
print()
print(jedan)
print(dva)
if i != 0:
print("\n *** Ukupno ima ", i, 'duplih brojeva. ***')
elif i == 0:
print("Nema duplih brojeva. :) ")
i = 0
raspaljot(jedan, dva,i)
What program do is finding duplicates in 2 random lists, them print duplicates in color and detecting position inside list[1] and list[2].
What I trying to do is printing list1 and list2 but showing duplicates in color.
For example:
[14, 78, 85, 31, 5, 54, 13, 46, 83, 4, 35, 41, 52, 51, 32]
[72, 40, 67, 85, 54, 76, 77, 39, 51, 36, 91, 70, 71, 38, 55]
here we have 3 duplicates (85,54,51). This above example on the console End was printed in white color, but I wanna these 3 numbers in red color in those two lines above.
Is this possible? I couldn't find a solution.
PS. Wing Pro version 7 on Fedora 33 Workstation / In WIngIde colors are only displayed in an external console and not the Debug I/O tool. :)

Simple solution would be something like this:
# Change list to string
jedan_str = str(jedan)
# Create set with numbers that need new color
num_set = {"85", "54", "51"}
# Iterate over every number and wrap it with color change
for i in num_set:
# Note that I used f-string to format string
# But you can also do this as "\033[31m" + i + "\033[0m"
jedan_str = jedan_str.replace("85", f"\033[31m{i}\033[0m")
# Print string that represent list
print(jedan_str)

Following the idea of using a set to determine which elements are in both lists (as Cv4niak proposed in his answer), I created a function to print the output as you desire. There are numerous other ways of achieving it, but I think this is a simple yet effective way.
The idea is to use the cprint() function from the termcolor package. You can install it with pip install termcolor, and then print normally all elements, except the ones that are duplicates, which will be printed using cprint(item, "red").
The "{:0>2d}" formatting in each ìtem print serves only to pad the number with zeros (so 2 will be printed as 02, for example), in order for the output of both lists to be aligned.
import random
from termcolor import cprint
def mark_duplicates(first, second):
duplicates = list(set(first).intersection(second))
if duplicates:
for list_ in [first, second]:
print("[", end="")
for item in list_:
if item in duplicates:
cprint("{:0>2d}".format(item), "red", end=",")
else:
print("{:0>2d}".format(item), end=",")
print("\b]")
else:
print("No duplicates.")
jedan = random.sample(range(1, 99), 15)
dva = random.sample(range(1, 99), 15)
mark_duplicates(jedan, dva)
With this, if there are no duplicates, the No duplicates. string will be printed. Also you can change the color with not much effort, and use other nice functionalities from termcolor package.

Related

A Rule of Divisibility by 13 - Codewars python challenge (RecursionError)

Instructions:
When you divide the successive powers of 10 by 13 you get the following remainders of the integer divisions:
1, 10, 9, 12, 3, 4.
Then the whole pattern repeats.
Hence the following method: Multiply the right most digit of the number with the left most number in the sequence shown above, the second right most digit to the second left most digit of the number in the sequence. The cycle goes on and you sum all these products. Repeat this process until the sequence of sums is stationary.
...........................................................................
Example: What is the remainder when 1234567 is divided by 13?
7×1 + 6×10 + 5×9 + 4×12 + 3×3 + 2×4 + 1×1 = 178
We repeat the process with 178:
8x1 + 7x10 + 1x9 = 87
and again with 87:
7x1 + 8x10 = 87
...........................................................................
From now on the sequence is stationary and the remainder of 1234567 by 13 is the same as the remainder of 87 by 13: 9
Call thirt the function which processes this sequence of operations on an integer n (>=0). thirt will return the stationary number.
thirt(1234567) calculates 178, then 87, then 87 and returns 87.
thirt(321) calculates 48, 48 and returns 48
My Code:
def thirt(n):
a = []
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
else:
return c
thirt(5634)
When I run this I get an error
Traceback (most recent call last):
File "main.py", line 5, in <module>
Test.assert_equals(thirt(8529), 79)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
[Previous line repeated 994 more times]
File "/home/codewarrior/solution.py", line 3, in thirt
n = [int(i) for i in list(str(n))][::-1]
RecursionError: maximum recursion depth exceeded while getting the str of an object
when I remove some part of the code and leave it like
def thirt(n):
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
return y
thirt(5634)
I get 148 in the output, and then I thirt(148), I get 57, which is the desired answer, same goes for other examples as well.
so I just need a proper way to recur this function, and I just want it to stop as soon as the values start repeating, i.e. I want the loop of recursion to break as soon as I get two 57's in a row, and then I need it to return 57.
But I can't figure out a proper way to do it, because this is the first time I've applied recursion in a function, my code is really messed up, I'll really appreciate any help.
You are getting the error depth exceeded while getting the str of an object because you are assigning the list of digits n to the same variable name as the function parameter n. That means after the first recursive call, you are running [int(i) for i in list(str(n))][::-1] on a list of individual digits, and then a list of lists, and so on, rather than a single input number as you're expecting.
Once you fix that, you run into the issue of how you are checking for whether to make the recursive call:
a = []
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
I can see what you're trying to do, and it will not work in recursion because every time the function is called, a is reset to an empty list. That means a.count(c) == 1 is always true, and your function will go into an infinite recursive loop.
Instead, for this algorithm all you need to do is check whether your newly calculated y is equal to the number n that was passed to the function. If they're the same, that means you've gotten the same number twice in a row, so the algorithm is done.
After that is fixed, it will look like you're getting somewhere. You can use this logic:
if n != y:
thirt(y)
else:
print(y) # expected answer outputted to console
return y
Except when you call thirt(1234567), the value returned is None ! What the heck? I printed y and it's correct, it's right there! What is happening is, the inner-most call to thirt is returning the number you need, but then the next level up in the function call stack doesn't do anything with it. So the function ends and returns None. To fix this, you need each level of the recursive call to pass its return value up the chain. So use return thirt(y) instead of just thirt(y).
Finally, you need to account for the case when the number passed to the function is longer than 6 digits. Your l list needs to repeat in a cycle, not stop with the 6 numbers you've listed. You can get the list to be the length you need by multiplying it by the length of n divided by six, rounded up whenever there's a remainder.
After all that, you'll end up with something like the following:
def thirt(n):
nList = [int(i) for i in list(str(n))][::-1]
remainders = [1, 10, 9, 12, 3, 4] * (
len(nList) // 6 + min(1, len(nList) % 6)
)
y = sum([a * b for a,b in zip(nList,remainders)])
if n != y:
return thirt(y)
else:
return y
print(thirt(1234567)) #87
Isn't this what you mean?
def thirt(n_raw):
a = []
n = [int(i) for i in list(str(n_raw))][::-1]
l = [1, 10, 9, 12, 3, 4]*(len(n)//6+1)
y = sum([a * b for a,b in zip(n,l)])
if(y==n_raw): return y
else: return thirt(y)
I think you just went in a very wrong direction with the second half of your function, but I might misunderstood the premise behind...

Python Random no function refreshes without running

My function is as below. I am taking input of 2 nos, finding random nos between them and then multiplying them all.
start = int(input("Enter start value"))
end = int(input("Enter end value"))
import random
numlist = random.sample(range(start,end),10)
print("list of random nos are" + str(numlist))
from functools import reduce
prod = reduce(lambda x,y: x*y, numlist)
print("the product of random nos: {0} is {1}".format(numlist,prod))
The output is as below
Enter start value7
Enter end value89
list of random nos are: [58, 13, 47, 43, 44, 56, 86, 14, 25, 71]
the product of random nos: [51, 30, 7, 25, 49, 29, 35, 54, 27, 67] is 1300840136977500
My question is a) why does the list of random nos change (first line [58,13..second line [51,30...) even though i haven't run this numlist = random.sample(range(start,end),10) line of code again.
What is happening here ?
i just added print(numlist) and the random numbers are not changing for me.Try this instead
end = int(input("Enter end value"))
import random
numlist = random.sample(range(start,end),10)
print(numlist)
from functools import reduce
prod = reduce(lambda x,y: x*y, numlist)
print("the product of random nos: {0} is {1}".format(numlist,prod))
Use a function so that the random value is regenerated each time the function is called.
>>> f = random.random()
>>> f
0.27924394986694034
>>> def randomizer(): return random.random()
...
>>> randomizer()
0.10425940372082476
>>> randomizer()
0.5703202999521394```

Is there a way to convert a list of integers to a single variable?

I'd like to convert a list of integers to a singe variable.
I tried this (found on another question):
r = len(message) -1
res = 0
for n in message:
res += n * 10 ** r
r -= 1
This does not work for me at all.
I basically need this:
message = [17, 71, 34, 83, 81]
(This can vary in length as I use a variable to change each one)
To convert into this:
new_message = 1771348381
A combination of join, map and str will do.
message = [17, 71, 34, 83, 81]
new_message = int(''.join(map(str, message)))
# 1771348381

How to take user input when it is seperated by any number of spaces and line breaks in python?

I have been trying to take integer inputs seperated by any number of white spaces or line breaks. I know how to take space seperated outputs and outputs having line breaks. In C based languages we don't have to care about where the input is, it automatically takes the input when found, but I don't think this is the case with Python(correct me if I am wrong). Can anybody help?
I tried using a While statement till True and using a try statement in it. But it doesn't work.
a = []
try:
while(True):
a.append(int(input()))
except:
pass
print(a)
when i input
12 12
12
it returns an empty list. If i remove the int in the input it returns a list [12 12, 12].
Try this: The Shortest way possible
a = []
s=input()
while s != '':
i = s.split()
[a.append(int(j)) for j in i]
s=input()
print(a)
Input:
1 2 3
4 5
6
Output:
[1, 2, 3, 4, 5, 6]
You can also try:
a = []
s=input()
while s != '':
i = s.split()
a.extend(map(lambda s: int(s),i))
s=input()
print(a)
Wait, so I think I understand it now. You want to accept any amount of input, but save each input separated by whitespace as its own entry? There is actually a string method for that. Here's an example script for it. It's not the best, but it demonstrates the method pretty well.
list = []
string = "user input goes here"
splitString = string.split()
for word in splitString:
list.append(word)
print(list)
Output:
["user", "input", "goes", "here"]
The string.split() method uses space by default, but you can specify another delimiter like the # sign.
List = []
String = "Hi#my#name#is#bob"
newString = String.split("#")
for word in newString:
list.append(word)
EDIT: Here is a full working implementation that will work whether the thing separating two inputs is whitespace, newlines, or anything else you'd like.
import re
list = []
while True:
string = input()
if string == "break":
break
splitString = re.split("[\s | \r\n]", string)
for word in splitString:
list.append(word)
cleanList = []
for word in list:
if word != '':
cleanList.append(word)
print(cleanList)
Input:
12 94 17
56
3
Output:
[12, 94, 17, 56, 3]
Functional proof: Click here
Hope you will some insight in this example & have added my personal view of how to code.
Firstly, giving input with multi-spaces is understandable but not multi-lines. Prefer taking input one by one.
For testing & debugging purposes, prefer separate collecting user and processing input data.
Now, say you have collected your user input and stored as data using raw_input, which is handy when you need to collect multiline inputs. Please explore raw_input, it is supported in Python3 and Python2.
>>>
>>> data = '''12
...
... 12 12
...
...
... 12'''
>>> data
'12 \n\n12 12\n\n\n12'
>>> print(data)
12
12 12
12
step1: clear all line separations
>>> double_spaces = ' '
>>> single_space = ' '
>>> data = data.strip().replace('\n', single_space)
>>> data
'12 12 12 12'
step2: Fix multiple spaces
>>> while double_spaces in data:
... data = data.replace(double_spaces, single_space)
...
>>> data
'12 12 12 12'
>>> print(list(map(int, data.split()))
...
... )
[12, 12, 12, 12]
>>>
Problems with you code
>>> a = []
>>> try:
... while(True):
... a.append(int(input()))
... except:
... pass
...
12
1
12 12
>>> a
[12, 1]
>>>
When you enter 12 12, below is supposed to happen.
>>> int('12 12')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '12 12'
Since this code had bad exception handling except:, your use case is returning an empty list as expected.
Since I have changed the input, you see this difference.

Two sample dependent T test in python and rank sum test

I have a data set for which has two labels, label 1 = 0(case), label 2 =1(control). I have already calculated the mean for the two different labels. Furthermore, I need to calculate two sample t test(dependent) and two sample rank sum test. My data set looks like :
SRA ID ERR169499 ERR169500 ERR169501 mean_ctrl mean_case
Label 1 0 1
TaxID PRJEB3251_ERR169499 PRJEB3251_ERR169500 PRJEB3251_ERR169501
333046 0.05 0 0.4
1049 0.03 0.9 0
337090 0.01 0.6 0.7
I am new to statistics.The code I have so far is this:
label = []
data = {}
x = open('final_out_transposed.csv','rt')
for r in x:
datas = r.split(',')
if datas[0] == ' Label':
label.append(r.split(",")[1:])
label = label[0]
label[-1] = label[-1].replace('\n','')
counter = len(label)
for row in file1:
content = row.split(',')
if content[0]=='SRA ID' or content[0]== 'TaxID' or content[0]==' Label':
pass
else:
dt = row.split(',')
dt[-1] = dt[-1].replace('\n','')
data[dt[0]]=dt[1:]
keys = list(data)
sum_file = open('sum.csv','w')
for key in keys:
sum_case = 0
sum_ctrl = 0
count_case = 0
count_ctrl = 0
mean_case = 0
mean_ctrl = 0
print(len(label))
for i in range(counter):
print(i)
if label[i] == '0' or label[i] == 0:
sum_case=np.float64(sum_case)+np.float64(data[key][i])
count_case = count_case+1
mean_case = sum_case/count_case
else:
sum_ctrl = np.float64(sum_ctrl)+np.float64(data[key][i])
count_ctrl = count_ctrl+1
mean_ctrl = sum_ctrl/count_ctrl
Any help will be highly appreciated.
Instead of using open to read your csv file, I would use Pandas. That will place it in a dataframe that will be easier to use
import pandas as pd
data_frame = pd.read_csv('final_out_transposed.csv')
For a Two Sample dependent T-test you want to use ttest_rel
notice ttest_ind is for independent groups. Since you specifically asked for dependent groups, use ttest_rel.
It's hard from your example above to see where your two columns of sample data are, but imagine I had the following made up data of 'case' and 'control'. I could calculate a dependent Two Sample t-test using pandas as shown below:
import pandas as pd
from scipy.stats import ttest_rel
data_frame = pd.DataFrame({
'case':[55, 43, 51, 62, 35, 48, 58, 45, 48, 54, 56, 32],
'control':[48, 38, 53, 58, 36, 42, 55, 40, 49, 50, 58, 25]})
(t_stat, p) = ttest_rel(data_frame['control'], data_frame['case'])
print (t_stat)
print (p)
p would be the p-value, t_stat would be the t-statistic. You can read more about this in the documentation
In a similar manner, once you have your sample .csv data in a dataframe, you can perform a rank sum test:
from scipy.stats import ranksums
(t_stat, p) = ranksums(data_frame['control'], data_frame['case'])
documentation for ranksums

Resources