I am making a game where you crack a code. I want it so it can be any code from 0000 to 9999. I made this script.
from random import *
from time import sleep
pin = [randint(0,9),randint(0,9),randint(0,9),randint(0,9)]
print(pin)
usrinp = int(input(''))
if int(usrinp) == pin:
print('cracked')
the trouble is when I input that code it doesn't work as in nothing comes out as an output. Is there a way to combine these 4 numbers to make a hash or whatever its called?
You have a list of integers, and are comparing it with a single integer. That doesn't work for two reasons:
single integers are never equal to a list, whatever the contents
int() doesn't preserve leading 0 characters; int('0999') returns 999, int('0000') returns 0.
Keep your input and your secret as strings, so you can keep the leading 0. Make them both the same type, so generate a single string, not a list of integers.
Your secret pin can be generated by picking string digits:
digits = '0123456789' # or use from string import digits
pin = ''.join([random.choice(digits) for _ in range(4)]) # 4 random digits, one string
then test the input() value against that pin:
usrinp = input('')
if usrinp == pin:
# ...
Note: you could pick a single random integer too, with random.randint(0, 9999), but that would make it harder for you to then to tell the player if they got some of the digits correct. By generating a string instead, you could, for example, trivially count how many digits they had correct:
if usrinp == pin:
print('Cracked!')
else:
correct_count = 0
for pindigit, userdigit in zip(pin, usrinp):
if pindigit == userdigit:
correct_count += 1
print('Sorry, not the right pin, but you guessed",
correct_count, 'digits correctly!')
You can achieve the same with two integers, but then you'd have to use maths or string conversions to extract each digit and handle values with leading zeros correctly. It all becomes just that little bit more complicated.
Another alternative is to convert the user input to separate integers (so keep your original generated list of integers):
userinp = [int(digit) for digit in input('')]
but unless you also plan to use the digits in arithmetic (summing them, multiplying, etc.) there is no real advantage in that approach over using strings. Both lists and strings are sequences, but generating strings saves you from having to handle users that stubbornly enter 'Your mamma is a <censored>' every time they play your game and break the int() conversions. :-)
None of this requires hashing; hashing is of no use here, because you want to test for equality, not trying to reduce a large amount of potential values to a limited set of options (like trying to put arbitrary values into a table of limited size, or to direct a large number of incoming connections to a limited number of servers that can handle those connections).
It's because you are comparing an integer value with a list.
import random
from time import sleep
pin = 1000*randint(0, 9) + 100*randint(0, 9) + 10*randint(0, 9) + randint(0, 9)
print(pin)
usrinp = int(input(''))
if usrinp == pin:
print('cracked')
this should work, if your pin always is going to be 4 digits, not for the ones with leading zeroes.
To get a four digit int use this:
pin = randint(0, 9999)
So the resulting code would be:
from random import *
from time import sleep
pin = randint(0, 9999)
print('%04d'%pin) # print with leading zeros
usrinp = int(input(''))
if usrinp == pin:
print('cracked')
Related
I am creating a guessing game where you need to guess the exact number that the computer (i.e Python) has generated. I am making it have an easy mode (which generates a 3-digit number for the user to guess) and a hard mode (which generates a 4-digit number for the user to guess).
However, for the easy mode, I want to be able to tell the user that they have one (or more) number in their guess which is correct but it is in the wrong position.
So far, I have used index positions for the computer to note what numbers (in what order) are in the computer-generated, as shown in my code below:
def easy_mode():
easy_num = randint(100,999)
easy_digit_splitter1 = str(easy_num)[0]
easy_digit_splitter2 = str(easy_num)[1]
easy_digit_splitter3 = str(easy_num)[2]
I know that I will need a variable that stores the user's guess under the code above (as well as a while loop), but how do I compare both the "easy_num" and the variable which will store the user's guess and tell the user that they have a correct number in their guess but it's in the wrong position?
Once you get your user guess and your random number you can convert to list and iterate:
easy_num_list = list(str(easy_num))
user_guess_list = list(user_guess)
#iterate through each digit in the user guess. `i` is the index of the digit we are iterating.
for i in range(0, len(user_guess_list)):
Then in that loop you can do your testing:
easy_num_list = list(str(easy_num))
user_guess_list = list(user_guess)
#iterate through each digit in the user guess. `i` is the index of the digit we are iterating.
for i in range(0, len(user_guess_list)):
#use the `in` operator to see if this digit from the user's guess is in the randomly generated number
if user_guess_list[i] in easy_num_list:
print("number",user_guess_list[i],"is in the random number")
#check to see if this digit from the user's guess is in the exact same index/position as the randomly generated number
if user_guess_list[i] == easy_num_list[i]:
print("and it's in the right spot")
else:
print("but it's not in the right spot")
else:
print("number",user_guess_list[i],"is not in the random number")
There's more clean and elegant ways to do this logic, but this should get you in the ballpark.
In Python I'm attempting to make a product_ID generator, which takes a number of any value and converts it into a hexadecimal format of "#AA0000". When the 4 numbers overflow past 9999, they increment the first letter by one in the ASCII uppercase set. Meaning if I give 10000 as input, I get #AB0001.
Currently I am using the modulus operator (%) to find the remainder of the input number so it is always within 4 digits. (For reference, the formula I used was Numb%9999.)
The issue I am currently having with is getting the second letter to increment properly. I've managed to get a single letter version working, which you can see here:
from string import ascii_uppercase as upper
upper = [a for a in upper]
def Convert_Numb_To_Ref(Order_Number):
"""Takes an Order_Number (int), and converts it into a unique Order_ID"""
Number = str((Order_Number%9999)+1) # Makes it so it never is bigger than 4 digits
Number = ("0"*(4-len(str(Number))))+Number # If number < 1000, adds on 0s to the beginning, so 1 -> 0001
try:
Letter = upper[Order_Number//9999] # Divides and floors
except IndexError:
print("Number too large! Cannot generate Product_ID")
return False
return f"#{Letter}{Number}"
If I was to input 10000, I would get #B0002.
This works fine, returning what I want to see. (Currently the above code only works with a single letter, which is why there aren't 2.) I'm just stuck with incrementing the second letter.
The problem is in this line:
Letter = upper[Order_Number//9999] # Divides and floors
If the order number becomes too large, the index becomes larger than 25, so you would get an IndexError. To avoid this, you should use "modulo 26" to get a number lower than 26. And you should do another lookup for the next letter (the left one).
Some other remarks:
To separate the high part and the low part you should not divide by 9999 but by 10000 (idem for the module operation), unless you want to skip the number 9999 (or 0000). This is not entirely clear from your question.
For the digits you can use standard Python formatting: '%04d' % nr will do the trick.
Putting it together you could write something like this:
import string
def number_to_reference(order_number):
"""Take an order number and convert it into a unique order id."""
if order_number >= 26 * 26 * 10000:
print("Number too large! Cannot generate Product_ID")
return False
# NB: You could also do the following instead:
# raise ValueError('Number too large! Cannot generate Product_ID')
high_part = order_number // 10000
low_part = order_number % 10000
letter1 = string.ascii_uppercase[high_part // 26]
letter2 = string.ascii_uppercase[high_part % 26]
return '#%s%s%04d' % (letter1, letter2, low_part)
print(number_to_reference(1)) # AA0001
print(number_to_reference(123)) # AA0123
print(number_to_reference(9999)) # AA9999
print(number_to_reference(10000)) # AB0000
print(number_to_reference(1234567)) # ET4567
print(number_to_reference(6759999)) # ZZ9999
print(number_to_reference(6760000)) # Number too large! Cannot generate Product_ID
Trying to generate a certain length credit card number with a prefix given.
while len(str(cc_number)) < (len(str(length)) - 1):
digit = str(random.randrange(0, 9))
cc_number = str(cc_number) + str((digit))
return cc_number
I'm expecting to get say 16 digits long number with a variable size prefix given. How do i make this piece of code generate a right size string of numbers? This code by the way only concatenates 1 random digit to the end of the string... So i expect to get '4349578451278456', but the actual output is '41'
If length is 16, str(length) will give you the string '16' which has a len of 2. Just use length without len or str.
Beyond that, your return statement should be outside of the loop
Since you're already using the random module, I just want to offer an alternative solution:
from random import choices
from string import digits
cc_digits = choices(digits, k=16)
cc_number = "".join(cc_digits)
print(cc_number)
Alrighty, first post here, so please forgive and ignore if the question is not workable;
Background:
I'm in computer science 160. I haven't taken any computer related classes since high school, so joining this class was a big shift for me. It all seemed very advanced. We have been working in Python and each week we are prompted to write a program.
I have been working with this problem for over a week and am having a hard time even starting.
The prompt is to read an integer containing only 1's and 0's,
process the binary number digit by digit and report the decimal equivalent. Now, I have gotten some tips from a classmate and it sent me at least in a direction.
Set up a couple of counters;
using the % operator to check the remainder of the number divided by 2, and slicing off the last number (to the right) to move on to and process the next digit.
I am having an incredibly hard time wrapping my head around what formula to use on the binary digits themselves which will convert the number to decimal.
setbitval = 0
counter = 0
user = int(input("enter a binary value. "))
if user % 2 == 1:
user = (user/10) - .1
setbitval += 1
This is all I've got so far.. My thinking is getting in the way. I've searched and searched, even through these forums.
Any information or thoughts are extremely appreciated,
T
Edit: okay guys, everyone's help has been extremely useful but I'm having a problem checking if the user input is not a binary number.
for i in reversed(bits):
decimal += 2**counter * int(i)
counter += 1
This is the formula someone here gave me and I've been trying different iterations of "for i in bits: if i in bits: != 0 or 1" and also "if i in bits: >= 1 or <=0".
Any thoughts?
you can use this code:
binary= raw_input("Binary: ")
d= int(binary, 2)
print d
To convert binary value to decimal you need to do the following:
Take the least significant bit and multiply it by 2^0, then take the next least significant beat and multiply it by 2^1, next one by 2^2 and so on...
Let's say, for example you need to convert a number 1010 to decimal:
You would have 0*2^0 + 1*2^1 + 0*2^2 + 1*2^3 = 0 + 2 + 0 + 8 = 10
So in your python code, you need to:
read the int that the user inputted (representing the binary value).
convert that int and convert it to string, so you can break it into list of digits
make a list of digits from the string you created (a list int python can be created from a string not an int, that's why you need the conversion to string first)
go trough that list of bits in reverse and multiply every bit by 2^k, k being the counter starting from 0
Here's the code that demonstrates what I just tried to explain:
user_input = int(input("enter a binary value"))
bits = list(str(user_input))
decimal = 0
counter = 0
for i in reversed(bits):
decimal += 2**counter * int(i)
counter+=1
print 'The decimal value is: ', decimal
I'll agree this is close to the "code this for me" territory, but I'll try to answer in a way that gets you on the right track, instead of just posting a working code snippet.
A simple way of doing this is just to use int()'s base argument, but I'm guessing that is disallowed.
You already have a way of testing the current bit in your question, namely checking whether n % 2 == 1. If this is the case, we need to add a power of two.
Then, we need some way of going to the next bit. In binary, we would use bit shifts, but sadly, we don't have those. a >> b is equivalent to a // (2**b) - can you write a decimal equivalent to that?
You also need to keep a counter of which power of two the current bit represents, a loop, and some way of detecting an end condition. Those are left as exercises to the reader.
I’d recommend reading the following articles on Wikipedia:
https://en.wikipedia.org/wiki/Radix
https://en.wikipedia.org/wiki/Binary_number
The first one gives you an idea how the numeral systems work in general and the second one explains and shows the formula to convert between binary and decimal systems.
Try to implement the solution after reading this. That’s what I did when I dealt with this problem. If that doesn’t help, let me know and I’ll post the code.
Hopefully, this code clarifies things a bit.
x = input("Enter binary number: ").strip()
decimal = 0
for i in range(len(x)):
decimal += int(x[i]) * 2**abs((i - (len(x) - 1)))
print(decimal)
This code takes in a binary number as a string, converts it to a decimal number and outputs it as an integer. The procedure is the following:
1st element of binary number * 2^(length of binary number - 1)
2nd element of binary number * 2^(length of binary number - 2)
and so on till we get to the last element and ...2^0
If we take number 10011, the conversion using this formula will look like this:
1*2^4 + 0*2^3 + 0*2^2 + 1*2^1 + 1*2^0, which equals to 19.
This code, however, assumes that the binary number is valid. Let me know if it helps.
Another implementation using while loop might look like this. Maybe it'll be easier to understand than the code with the for loop.
x = input("Enter binary number: ").strip()
decimal = 0
index = 0
exp = len(x) - 1
while index != len(x):
decimal += int(x[index]) * 2**exp
index += 1
exp -= 1
print(decimal)
In this one we start from the beginning of the number with the highest power, which is length of binary number minus one, we loop through the number, lowering the power and changing index.
Regarding checking if number is binary.
Try using helper function to determine if number is binary and then insert this function inside your main function. For example:
def is_binary(x):
""" Returns True if number x is binary and False otherwise.
input: x as a string
"""
for i in list(x):
if i not in ["1", "0"]:
return False
return True
def binary_decimal(x):
""" Converts binary to decimal.
input: binary number x as a string
output: decimal number as int
"""
if not is_binary(x):
return "Number is invalid"
decimal = 0
for i in range(len(x)):
decimal += int(x[i]) * 2**abs((i - (len(x) - 1)))
return decimal
The first function checks if number consists only of ones and zeros and the second function actually converts your number only if it's binary according to the first function.
You can also try using assert statement or try / except if you'd better raise an error if number is not binary instead of simply printing the message.
Of course, you can implement this solution without any functions.
I need to record SerialNumber(s) on an object. We enter many objects. Most serial numbers are strings - the numbers aren't used numerically, just as unique identifiers - but they are often sequential. Further, leading zeros are important due to unique id status of serial number.
When doing data entry, it's nice to just enter the first "sequential" serial number (eg 000123) and then the number of items (eg 5) to get the desired output - that way we can enter data in bulk see below:
Obj1.serial = 000123
Obj2.serial = 000124
Obj3.serial = 000125
Obj4.serial = 000126
Obj5.serial = 000127
The problem is that when you take the first number-as-string, turn to integer and increment, you loose the leading zeros.
Not all serials are sequential - not all are even numbers (eg FDM-434\RRTASDVI908)
But those that are, I would like to automate entry.
In python, what is the most elegant way to check for leading zeros (*and, I guess, edge cases like 0009999) in a string before iterating, and then re-application of those zeros after increment?
I have a solution to this problem but it isn't elegant. In fact, it's the most boring and blunt alg possible.
Is there an elegant solution to this problem?
EDIT
To clarify the question, I want the serial to have the same number of digits after the increment.
So, in most cases, this will mean reapplying the same number of leading zeros. BUT in some edge cases the number of leading zeros will be decremented. eg: 009 -> 010; 0099 -> 0100
Try str.zfill():
>>> s = "000123"
>>> i = int(s)
>>> i
123
>>> n = 6
>>> str(i).zfill(n)
'000123'
I develop my comment here, Obj1.serial being a string:
Obj1.serial = "000123"
('%0'+str(len(Obj1.serial))+'d') % (1+int(Obj1.serial))
It's like #owen-s answer '%06d' % n: print the number and pad with leading 0.
Regarding '%d' % n, it's just one way of printing. From PEP3101:
In Python 3.0, the % operator is supplemented by a more powerful
string formatting method, format(). Support for the str.format()
method has been backported to Python 2.6.
So you may want to use format instead… Anyway, you have an integer at the right of the % sign, and it will replace the %d inside the left string.
'%06d' means print a minimum of 6 (6) digits (d) long, fill with 0 (0) if necessary.
As Obj1.serial is a string, you have to convert it to an integer before the increment: 1+int(Obj1.serial). And because the right side takes an integer, we can leave it like that.
Now, for the left part, as we can't hard code 6, we have to take the length of Obj1.serial. But this is an integer, so we have to convert it back to a string, and concatenate to the rest of the expression %0 6 d : '%0'+str(len(Obj1.serial))+'d'. Thus
('%0'+str(len(Obj1.serial))+'d') % (1+int(Obj1.serial))
Now, with format (format-specification):
'{0:06}'.format(n)
is replaced in the same way by
('{0:0'+str(len(Obj1.serial))+'}').format(1+int(Obj1.serial))
You could check the length of the string ahead of time, then use rjust to pad to the same length afterwards:
>>> s = "000123"
>>> len_s = len(s)
>>> i = int(s)
>>> i
123
>>> str(i).rjust(len_s, "0")
'000123'
You can check a serial number for all digits using:
if serial.isdigit():