Randomizing Sentences In Python - python

I not long ago finished my project which comments on a video based on a keyword on YouTube, it will pick a random comment using the random library.
The program has been acting strange when "randomizing" the comments to add to the
YouTube videos. I'm starting to think I may need to improve the randomness, the fact being that
it has chosen the 4th comment (out of 9) 7 times, and the 9th one 3 times. Both of these
results occur after each other, in other words, it is sending the same message in a row
when it's meant to pick randomly and not repeat.
Is there any way I can increase how random this is? If you know, please do tell me, I will appreciate it a bunch!
PS: This is more of stopping it from repeating the same sentence on YouTube.
code:
if __name__ == "__main__":
from googleapiclient.errors import HttpError
import random
import time
import sys
# Comments are getting loaded
comments = load_comments('Comments.txt')
# Getting the number of comments you want to add
number_of_comments = int(input('Enter the number of comments: '))
count, cycle, videoid_store = 0, 1, []
# Getting the keyword
keyword = input('Enter the Keyword: ')
# This loop keeps running until all comments have been added
youtube = authentication()
while count < number_of_comments:
print("Searching for videos .. (Cycle:%d)" %cycle)
time.sleep(10)
random.shuffle(comments)

If you want to keep the randomness but avoid repeats or frequent re-occurrences, you have to remember the previous outcomes, to manipulate the odds in favour of the ones that have occurred less frequently so far.
Some examples:
Shuffle the outcomes. Go through all, by the order obtained. Repeat.
Keep a count of the last few outcomes. If we get an outcome that has been drawn X times already, draw again up to X times.
Code, for the above examples:
import random
import collections
class ShuffleAndExhaust(): # cycle in random order each time
def __init__(self,N): # N: number of possible outcomes
self.N = N
self.queue = list()
def draw(self):
if not self.queue: # exhausted (or 1st ever draw)
self.queue.extend(range(self.N))
random.shuffle(self.queue)
return self.queue.pop()
class RememberAndRetry(): # re-draw, if reoccurring
def __init__(self,N): # N: number of possible outcomes
self.N = N
self.history = collections.deque(maxlen=3*self.N) # maxlen = rule-of-thumb constant * N
def draw(self):
triesleft = collections.Counter(self.history)
while True:
n = random.randint(0,self.N-1)
if triesleft[n] > 0: # drew this number N times already
triesleft[n] -= 1 # 1 less try left drawing this same number until we accept it
else: break
self.history.append(n)
return n
Testing 100 draws of 10 possible outcomes:
>>> random.seed(0) # for reproducibility in testing only
>>> r = ShuffleAndExhaust(10)
>>> print(*(r.draw() for i in range(100)))
6 9 0 2 4 3 5 1 8 7 5 3 2 7 1 0 6 8 4 9 4 1 8 6 5 2 3 9 0 7 5 6 9 4 7 1 3 8 2
0 0 8 9 7 5 3 6 2 1 4 5 3 9 7 0 1 4 6 2 8 8 7 1 0 2 4 3 6 9 5 8 4 1 9 2 6 7 5
3 0 7 1 6 2 4 8 9 0 3 5 2 0 4 3 8 5 1 7 9 6
>>> r = RememberAndRetry(10)
>>> print(*(r.draw() for i in range(100)))
1 8 6 4 3 9 7 5 1 3 0 2 0 9 1 0 4 6 2 7 8 5 9 3 6 7 0 1 4 5 2 5 4 8 7 6 3 1 7
9 8 9 4 0 7 9 1 0 8 6 1 5 3 2 5 2 3 6 6 2 7 4 0 4 1 8 6 7 0 1 5 3 9 8 0 9 5 4
7 7 1 6 8 3 8 5 2 3 9 0 5 0 2 6 2 1 4 4 7 4
Use N = the number of comments and each draw as the index of the comment to pick.

Try random.choice()
x=random.choice(['option1','option2'])

Related

How to print following pattern getting issue with spaces?

I am trying to write the code but not getting how to achieve expected output
Causing issue with space and not able to make proper judgement how to get exact spaces after every iteration
My code :
n=15
cnt=0
lst=[str(' ') for x in range(1,n+1)]
initial_length=len(''.join(lst))
print(initial_length)
for row in range(1,n+1):
lst[cnt-1]=str(row)
cnt=cnt-1
print(' '.join(lst))
Output of above code is not as expected output
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
6 5 4 3 2 1
7 6 5 4 3 2 1
8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
11 10 9 8 7 6 5 4 3 2 1
12 11 10 9 8 7 6 5 4 3 2 1
13 12 11 10 9 8 7 6 5 4 3 2 1
14 13 12 11 10 9 8 7 6 5 4 3 2 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Expected output :
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
6 5 4 3 2 1
7 6 5 4 3 2 1
8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
11 10 9 8 7 6 5 4 3 2 1
12 11 10 9 8 7 6 5 4 3 2 1
13 12 11 10 9 8 7 6 5 4 3 2 1
14 13 12 11 10 9 8 7 6 5 4 3 2 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Another approximation, by knowing the quantity of spaces in advance using a recursive function:
def findDigits(N):
if N <= 1:
return N
# Changing number to string
s = str(N)
# Add length of number to total_sum
return len(s) + findDigits(N - 1)
def print_inverse_pyramid(n):
# Calculate number of total digits until n
total_digits = findDigits(n)
# Print the pyramid
for row in range(1, n + 1):
total_digits -= len(str(row))
l_r = [str(i) for i in range(row, 0, -1)]
print(" " * (total_digits + (n - row)) + " ".join(l_r))
print_inverse_pyramid(15)
You have to account for larger digits taking up more space, which means that when creating the list that contains spaces, you need to multiply the space by how many digits are in that number which you can get by len(str(number)):
n = 15
# create a list containing how many spaces each number will take up
# in reverse order because the figure is reverse
lst = [' ' * len(str(x)) for x in range(n, 0, -1)]
# go over each number
for x in range(1, n + 1):
# replace the digit in its place from end
# by the string represantion of itself
lst[-x] = str(x)
# print joined list
print(' '.join(lst))
Also:
I strongly suggest following PEP 8 - Style Guide for Python Code. Function and variable names should be in snake_case, class names in CapitalCase. Don't have space around = if it is used as a part of keyword argument (func(arg='value')) but have space around = if it is used for assigning a value (variable = 'some value'). Have space around operators (+-/ etc.: value = x + y(except here value += x + y)). Have two blank lines around function and class declarations. Object method definitions have one blank line around them.
Quick and dirty: 'looking' at the last line
n = 15
def serie(n):
return ' '.join([str(j) for j in range(n, 0, -1)])
maxlen = len(serie(n))
for i in range(1, n +1):
s = serie(i)
print(" " * (maxlen - len(s)) + s)
With math, computing the length as the sum of the int of the log10 of values and adding for the spaces
import math
n = 15
def lenserie(n):
return sum(map(lambda i : int(math.log(i, 10)) + 1 ,range(1, n+1))) + (n-1)
maxlen = lenserie(n)
for i in range(1, n+1):
print(" " * (maxlen - lenserie(i)) + " ".join([str(i) for i in range(i, 0, -1)]))

Rearrange data file

I am trying to reorganize a .txt file containing a list of data with traits in the columns and the family on the rows. Basically, I need to write a program that creates rows comparing the people in each family so that the traits persons 1 and 2, 1 and 3, and 2 and 3 are compared. i.e.:
A 1 2 7 8 9 10
A 1 3 7 9 9 11
etc.
where A is the family, the first 2 numbers are the people compared, the 3rd and 4th numbers are trait1 such as the measurements for each person, and the final numbers are trait2 such as the BMI values for each person.
My input is like this:
A 1 trait trait
A 2 trait trait
A 3 trait trait
I was able to create a data frame using:
data = pandas.read_csv('family.txt.', sep=" ", header = None)
print(data)
I cannot seem to figure out an efficient way to concatenate the data into the rows needed above. Any help is greatly appreciated!
Thank you
Ok, Consider your data was as follows
A 1 7 4 5 6
A 2 6 5 4 7
A 3 7 7 5 4
B 1 7 4 5 6
B 2 6 5 4 7
B 3 7 7 5 4
Where the first column is the family and the second column is the person_id and all subsequent columns are traits.
Some super dirty and super hastily written code below seems to give you what you want
file_lines = []
out_list = []
final_out = []
def read_file():
global file_lines
with open("sample.txt", 'r') as fd:
file_lines = fd.read().splitlines()
print file_lines
def make_output():
global file_lines, out_list, final_out
out_line = []
for line1 in file_lines:
for line2 in file_lines:
line1c = line1.split(" ")
line2c = line2.split(" ")
if line1c[0] == line2c[0]:
if line1c[1] >= line2c[1]:
continue
else:
out_list = []
out_list.append(line1c[0])
out_list.append(line1c[1])
out_list.append(line2c[1])
for i in range(2, len(line1c)):
out_list.append(line1c[i])
out_list.append(line2c[i])
print " ".join(out_list)
read_file()
make_output()
The output of print is
A 1 2 7 6 4 5 5 4 6 7
A 1 3 7 7 4 7 5 5 6 4
A 2 1 6 7 5 4 4 5 7 6
A 2 3 6 7 5 7 4 5 7 4
A 3 1 7 7 7 4 5 5 4 6
A 3 2 7 6 7 5 5 4 4 7
B 1 2 7 6 4 5 5 4 6 7
B 1 3 7 7 4 7 5 5 6 4
B 2 1 6 7 5 4 4 5 7 6
B 2 3 6 7 5 7 4 5 7 4
B 3 1 7 7 7 4 5 5 4 6
B 3 2 7 6 7 5 5 4 4 7
As you can see In family A person 1 is compared with 2 and 3. 2 is compared with 1 and 3 and 3 is compared with 1 and 2.
Obviously there will be duplication because each person is compared with every other person in the family twice.
It's trivial to remove this by maintaining a list of who has been compared with whom.
P.S: I know the script is really dirty but I just wanted to illustrate what i've done. Not write production code
EDIT: I wanted to write a slightly more complicated duplicate remover. But since the data is so simple a small modification in the continue criterion solved it. the output after this edit is
A 1 2 7 6 4 5 5 4 6 7
A 1 3 7 7 4 7 5 5 6 4
A 2 3 6 7 5 7 4 5 7 4
B 1 2 7 6 4 5 5 4 6 7
B 1 3 7 7 4 7 5 5 6 4
B 2 3 6 7 5 7 4 5 7 4
which is free of duplicates

digits 0 to 9 in a triangle

I need help with a task in my intro to python programming course that requires a code that will print the following using two 'for-loops', one being nested:
0
0 1
0 1 2
0 1 2 3
0 1 2 3 4
0 1 2 3 4 5
0 1 2 3 4 5 6
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8 9
So far i have come up with the following code, but my triangle of numbers begins at the digit 1 instead of 0:
for i in range(-1,9):
print ('\n')
for i in range (int(i+1)):
j = i+1
print (j, end=' ')
Can anyone advise what I should do to make my list of digits begin from 0 instead of 1? Also any suggestions on how to make my code more readable? Thanks.
When using range, if you want the last integer to be included, you need to add one. With this in mind, I think the following makes sense:
for i in range(9+1): # +1 since you want the loop to include 9
for j in range(i+1): # +1 since you want your print to include i
print (j, end=' ')
print ('\n')
The print(\n) statement can go before or after your j for-loop, although the output will be slightly different. (Maybe because I'm used to mechanical typewrites, I think of \n as finishing a line rather than getting ready for a new one, but both are reasonable.)
I don't like the idea of starting at -1 so you can then add 1 later. It's unduly complicated, and a bad habit to start with as a beginner.
Keeping your code structure, the following will work:
for i in range(-1, 10): # you need 10 so that the triangle goes up to 9
print("\n")
for j in range(i + 1):
print(j, end=" ")
Result:
0
0 1
0 1 2
0 1 2 3
0 1 2 3 4
0 1 2 3 4 5
0 1 2 3 4 5 6
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8 9

Calling function and passing arguments multiple times

I want to call the function multiple time and use it's returned argument everytime when it's called. For example:
def myfunction(first, second, third):
return (first+1,second+1,third+1)
1st call: myfunction(1,2,3)
2nd call is going to be pass returned variables: myfunction(2,3,4) and loop it until defined times. How can I do such loop? Thank you!
a,b,c = 1,2,3
while i<n:
a,b,c = myfunction(a,b,c)
i +=1
def myF(x,y,z,i):
print x, i
while i:
x += 1
i -= 1
return myF(x,i)
This will keep calling myF until i is 0 which will break the while loop, example:
>>> myF(1,10)
1 10
2 9
3 8
4 7
5 6
6 5
7 4
8 3
9 2
10 1
11 0
For three arguments, you can do as follows:
>>> def myF(x,y,z,i):
print x,y,z,i
while i:
i -= 1
x,y,z = map(lambda s:s+1,(x,y,z))
return myF(x,y,z,i)
>>>
>>>
>>> myF(1,1,1,10)
1 1 1 10
2 2 2 9
3 3 3 8
4 4 4 7
5 5 5 6
6 6 6 5
7 7 7 4
8 8 8 3
9 9 9 2
10 10 10 1
11 11 11 0

If and only if all given conditions are true

import numpy as np
def data_verify(source):
rows = [x.strip().split(' ') for x in open(source)]
columns = zip(*rows)
blocks = np.array(rows).reshape((3,3,3,3)).transpose((0,2,1,3)).reshape((9,9))
#check iff, see further
return rows, columns, blocks
else:
return False
Got a sudoku grid in txt as such:
3 2 7 4 8 1 6 5 9
1 8 9 3 6 5 7 2 4
6 5 4 2 7 9 8 1 3
7 9 8 1 3 2 5 4 6
5 6 3 9 4 7 2 8 1
2 4 1 6 5 8 3 9 7
8 1 2 7 9 3 4 6 5
4 7 5 8 1 6 9 3 2
9 3 6 5 2 4 1 7 8
The function collects all relevant data and will return the respective rows, columns and blocks iff the length of the rows is the same as the columns' (got a few other functions that determine whether the puzzle is legit). I figured it is enough to compare the first row to all the columns (or vice versa, doesn't make a difference). How can I create a check that goes something like:
for i in range(len(rows)):
if len(row[0]) == len(column[i]):
#do something only if all of the lengths check out
Use all:
if all(len(row[0]) == len(column[i]) for i in range(len(rows))):
#do something only if all of the lengths check out
You can run the check in a for loop and set a flag if there is any mismatch, this example checks all rows with all columns:
match = True
for r in row:
for c in column:
if len(c) != len(r):
match = False
# Only continue if match == True

Categories

Resources