Random number generator comparing a list - python

Hi I am trying to compare a list of picked numbers to a list of randomly generated numbers. I want to know how many times it took to get the same numbers in the same sequence picked. I am using the choice() function which i have imported. Please see my code below. I seem to continue to get an infinite loop and never generate the same list as "my ticket"
My code below
from random import choice
my_ticket = (9, 'z', 4, 0)
lottery_numbs = ['a', 'z', 'i', 't', 'u', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
winning_numbers = []
picked_sequences = []
increment = 0
while True:
for pick in range(4):
pick = choice(lottery_numbs)
winning_numbers.append(pick)
if winning_numbers in picked_sequences:
continue
else:
picked_sequences.append(winning_numbers)
if my_ticket in picked_sequences:
print(increment)
break
else:
winning_numbers = []
print(increment)
increment += 1
print(winning_numbers)
print(my_ticket)
print(f"It took {increment} picks to pick my lottery numbers")

Think about the types of data that you're generating. What is choice(lottery_numbs) returning? What does winning_numbers contain? What are you comparing it against? If you have similar digits in different containers, you're not going to get a "match" unless you explicitly handle the containers.

The following is my take on your code.
Firstly, I changed your my_ticket into winning_ticket and made it into a list.
Then I changed your filtering of duplicate numbers inside current_ticket into a while loop, to ensure that the ticket will always contain 4 unique characters.
Then I converted your while true loop into a while condition on if the current ticket is the same as winning ticket.
Your main issue is the my_ticket being a tuple, the other minor issues are redundant for loop to filter duplicate, no guarantee on current ticket having 4 characters, variable namings, etc.
from random import choice
winning_ticket = [9, 'z', 4, 0]
lottery_numbs = ['a', 'z', 'i', 't', 'u', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
picks = 0
current_ticket = []
while current_ticket != winning_ticket:
current_ticket = []
while len(current_ticket) < 4:
pick = choice(lottery_numbs)
if pick not in current_ticket:
current_ticket.append(pick)
picks += 1
print(f"It took {picks} picks to pick my lottery numbers")

Related

How do I replace a value in a list corresponding to the user's input? [duplicate]

This question already has answers here:
Finding and replacing elements in a list
(10 answers)
Closed 12 months ago.
So I'm new to python and I'm making a tic tac toe game and for each players turn you pick a number from 0–8. It checks if it's an integer between 0–8, but I wanted to be able to take the response and replace the corresponding number in the list.
For instance, say my list looked like this
tiles = [0, 1, 2, 3, 4, 5, 6, 7, 8]
and for X's turn they typed 1.
I want it to replace 1 with an X on the board. I know I could do this with a whole bunch of if/elif/else statements but my friend did that and it looked super long and unnecessary.
I put it on GitHub in case you wanted to have look at the code to better understand what I'm talking about.
I'm using repl.it so I'm stuck on 3.8.2.
Something like this?
tiles = list(range(8+1))
while True:
user_input = input("Enter a number: ")
if not user_input.isdigit():
continue
number = int(user_input)
if number not in tiles:
continue
tiles[number] = 'x'
print(tiles)
Output:
Enter a number: asdasdasd
Enter a number: 3
[0, 1, 2, 'x', 4, 5, 6, 7, 8]
Enter a number: 4
[0, 1, 2, 'x', 'x', 5, 6, 7, 8]
Enter a number: 0
['x', 1, 2, 'x', 'x', 5, 6, 7, 8]
Enter a number: 0
Enter a number: 10
Enter a number:
This isn't meant to be a complete example - you can only set crosses, not noughts. Also, the program will just keep asking you for input even if you've set all entries to crosses.
In addition to the other answers: move the board's construction inside of the function so that after you replace a tile the board can be reconstructed.
def board():
play_board = str(tiles[0]) + "|" + str(tiles[1]) + "|" + str(tiles[2])
play_board_1 = str(tiles[3]) + "|" + str(tiles[4]) + "|" + str(tiles[5])
play_board_2 = str(tiles[6]) + "|" + str(tiles[7]) + "|" + str(tiles[8])
print(play_board)
print(divider)
print(play_board_1)
print(divider)
print(play_board_2)
First of all you need to check whose turn is it (x or o) then use this
tiles = [0, 1, 2, 3, 4, 5, 6, 7, 8]
user_input = int(input())
if turn == 'x':
tiles[tiles.index(user_input)] = 'x'
Of course you should fill in the necessary gaps

Explain [:0] in Python

Ok, so before I get flamed for not RTFM, I understand that [:0] in my case of:
s ="itsastring"
newS= []
newS[:0] = s
ends up converting s to a list through slicing. This is my end goal, but coming from a Java background, I don't fully understand the "0" part in "[:0] and syntactically why it's placed there (I know it roughly means increase by 0). Finally, how does Python know that I want to have each char of s be an element based on this syntax? I want to understand it so I can remember it more clearly.
If S and T are sequences, S[a:b] = T will replace the subsequence from index a to b-1 of S by the elements of T.
If a == b, it will act as a simple insertion.
And S[:0] is the same thing as S[0:0] : so it's a simple insertion at the front.
s = [11,22,33,44,55,66,77]
s[3:3] = [1,2,3] # insertion at position 3
print( s )
s = [11,22,33,44,55,66,77]
s[3:4] = [1,2,3] # deletion of element at position 3, and then insertion
print( s )
s = [11,22,33,44,55,66,77]
s[3:6] = [1,2,3] # deletion of elements from position 3 to 5, and then insertion
print( s )
s = [11,22,33,44,55,66,77]
s[:] = [1,2,3] # deletion of all elements, and then insertion : whole replacement
print( s )
output:
[11, 22, 33, 1, 2, 3, 44, 55, 66, 77]
[11, 22, 33, 1, 2, 3, 55, 66, 77]
[11, 22, 33, 1, 2, 3, 77]
[1, 2, 3]
Hope it helps:
s ="itsastring"
#if you add any variable in left side then python will start slicing from there
#and slice to one less than last index assigned on right side
newS = s[:]
So the [:0] means slice the string from the beggining to the 0 (or again the first) element in the s string and the result is nothing. By default the slicing is done from the first element to the last or print(s[0:]) is the same as print(s).
I suggest you try a loop through the whole string like this:
s = [x for x in "itsastring"]
print(s)
# result
['i', 't', 's', 'a', 's', 't', 'r', 'i', 'n', 'g']

What is the fastest way to convert a dictionary frequency to list in Python?

I have dictionary frequency as follows:
freq = {'a': 1, 'b': 2, 'c': 3}
It simply means that I have one a's, twob's, and three c's.
I would like to convert it into a complete list:
lst = ['a', 'b', 'b', 'c', 'c', 'c']
What is the fastest way (time-efficient) or most compact way (space-efficient) to do so?
Yes, but only if the items are (or can be represented as) integers, and if the number of items between the smallest and largest item is sufficiently close to the difference between the two, in which case you can use bucket sort, resulting in O(n) time complexity, where n is the difference between the smallest and the largest item. This would be more efficient than using other sorting algorithms, with an average time complexity of O(n log n).
In the case of List = [1, 4, 5, 2, 6, 7, 9, 3] as it is in your question, it is indeed more efficient to use bucket sort when it is known that 1 is the smallest item and 9 is the largest item, since only 8 is missing between the range. The following example uses collections.Counter to account for the possibility that there can be duplicates in the input list:
from collections import Counter
counts = Counter(List)
print(list(Counter({i: counts[i] for i in range(1, 10)}).elements()))
This outputs:
[1, 2, 3, 4, 5, 6, 7, 9]
Let's break this into two O(N) passes: one to catalog the numbers, and one to create the sorted list. I updated the variable names; List is an especially bad choice, given the built-in type list. I also added 10 to each value, so you can see how the low-end offset works.
coll = [11, 14, 15, 12, 16, 17, 19, 13]
last = 19
first = 11
offset = first
size = last-first+1
# Recognize all values in a dense "array"
need = [False] * size
for item in coll:
need[item - offset] = True
# Iterate again in numerical order; for each True value, add that item to the new list
sorted_list = [idx + offset for idx, needed_flag in enumerate(need) if needed_flag]
print(sorted_list)
OUTPUT:
[11, 12, 13, 14, 15, 16, 17, 19]
The most compact way I usually use is list comprehension -
lst = ['a', 'b', 'b', 'c', 'c', 'c']
freq = {i: 0 for i in lst}
for i in lst: freq[i] += 1
Space complexity - O(n)
Time complexity - O(n)

Count occurrences of an element in list

I know that there are already a lot of questions about this specific topic, but I can't find a proper solution for my problem.
I have the input:
2, 20, 15, 16, 17, 3, 8, 10, 7
I want to see if there are 'double' numbers in my code. I have tried working with this code.
lijst = input('Give a list: ')
teller = 0
for i in lijst.split(','):
if lijst.count(i) != 1:
teller += 1
print(teller != 0)
Normally I should get False, since there are no double numbers in the given list. However, I recieve True. I suggest that's because the 2 appears also in 20.
True
Does anyone know how to avoid this problem, so the the '2' isn't counted twice?
You can use collections.Counter which does exactly that
>>> data = [2, 20, 15, 16, 17, 3, 8, 10, 7]
>>> from collections import Counter
>>> Counter(data)
Counter({2: 1, 3: 1, 7: 1, 8: 1, 10: 1, 15: 1, 16: 1, 17: 1, 20: 1})
>>>
It counts number of occurences and returns a dict with keys indicates the item, and value is number of occurences.
If you just need to know if there are duplicates or not, regardless of which item is the duplicate, you can simply use Set over your list and check len() afterwards:
len(data) == len(set(data))
You can compare the length of the input with the length of the set of unique elements in input:
def has_repeated_elements(input):
"""returns True if input has repeated elements,
False otherwise"""
return len(set(input)) != len(input)
print(not has_repeated_elements(input))

Print a line if conditions have not been met

Hello fellow stackoverflowers, I am practising my Python with an example question given to me (actually a Google interview practice question) and ran into a problem I did not know how to a) pose properly (hence vague title), b) overcome.
The question is: For an array of numbers (given or random) find unique pairs of numbers within the array which when summed give a given number. E.G: find the pairs of numbers in the array below which add to 6.
[1 2 4 5 11]
So in the above case:
[1,5] and [2,4]
The code I have written is:
from secrets import *
i = 10
x = randbelow(10)
number = randbelow(100) #Generate a random number to be the sum that we are after#
if number == 0:
pass
else:
number = number
array = []
while i>0: #Generate a random array to use#
array.append(x)
x = x + randbelow(10)
i -= 1
print("The following is a randomly generated array:\n" + str(array))
print("Within this array we are looking for a pair of numbers which sum to " + str(number))
for i in range(0,10):
for j in range(0,10):
if i == j or i>j:
pass
else:
elem_sum = array[i] + array[j]
if elem_sum == number:
number_one = array[i]
number_two = array[j]
print("A pair of numbers within the array which satisfy that condition is: " + str(number_one) + " and " + str(number_two))
else:
pass
If no pairs are found, I want the line "No pairs were found". I was thinking a try/except, but wasn't sure if it was correct or how to implement it. Also, I'm unsure on how to stop repeated pairs appearing (unique pairs only), so for example if I wanted 22 as a sum and had the array:
[7, 9, 9, 13, 13, 14, 23, 32, 41, 45]
[9,13] would appear twice
Finally forgive me if there are redundancies/the code isn't written very efficiently, I'm slowly learning so any other tips would be greatly appreciated!
Thanks for reading :)
You can simply add a Boolean holding the answer to "was at least one pair found?".
initialize it as found = false at the beginning of your code.
Then, whenever you find a pair (the condition block that holds your current print command), just add found = true.
after all of your search (the double for loop`), add this:
if not found:
print("No pairs were found")
Instead of actually comparing each pair of numbers, you can just iterate the list once, subtract the current number from the target number, and see if the remainder is in the list. If you convert the list to a set first, that lookup can be done in O(1), reducing the overall complexity from O(n²) to just O(n). Also, the whole thing can be done in a single line with a list comprehension:
>>> nums = [1, 2, 4, 5, 11]
>>> target = 6
>>> nums_set = set(nums)
>>> pairs = [(n, target-n) for n in nums_set if target-n in nums_set and n <= target/2]
>>> print(pairs)
[(1, 5), (2, 4)]
For printing the pairs or some message, you can use the or keyword. x or y is interpreted as x if x else y, so if the result set is empty, the message is printed, otherwise the result set itself.
>>> pairs = []
>>> print(pairs or "No pairs found")
No pairs found
Update: The above can fail, if the number added to itself equals the target, but is only contained once in the set. In this case, you can use a collections.Counter instead of a set and check the multiplicity of that number first.
>>> nums = [1, 2, 4, 5, 11, 3]
>>> nums_set = set(nums)
>>> [(n, target-n) for n in nums_set if target-n in nums_set and n <= target/2]
[(1, 5), (2, 4), (3, 3)]
>>> nums_counts = collections.Counter(nums)
>>> [(n, target-n) for n in nums_counts if target-n in nums_counts and n <= target/2 and n != target-n or nums_counts[n] > 1]
[(1, 5), (2, 4)]
List your constraints first!
numbers added must be unique
only 2 numbers can be added
the length of the array can be arbitrary
the number to be summed to can be arbitrary
& Don't skip preprocessing! Reduce your problem-space.
2 things off the bat:
Starting after your 2 print statements, the I would do array = list(set(array)) to reduce the problem-space to [7, 9, 13, 14, 23, 32, 41, 45].
Assuming that all the numbers in question will be positive, I would discard numbers above number. :
array = [x for x in array if x < number]
giving [7, 9, 9, 13, 13, 14]
Combine the last 2 steps into a list comprehension and then use that as array:
smaller_array = [x for x in list(set(array)) if x < number]
which gives array == [7, 9, 13, 14]
After these two steps, you can do a bunch of stuff. I'm fully aware that I haven't answered your question, but from here you got this. ^this is the kind of stuff I'd assume google wants to see.

Categories