Credit Card Number Sensor Challenge - python

So I am trying to write a program that sensors the first 12 digits of a 'credit card number' and then prints it with the last 4 digits still there. (4444444444444444=************4444). I am having a problem making the loop stop at just the first 12 digits. The output is always 12 *'s. Here is the code:
credit=""
while len(credit)<16 or len(credit)>16:
credit=input("Please input credit card number: ")
x=1
k="*"
while x<12:
for ele in credit:
if ele.isdigit() and x<12:
credit=credit.replace(ele, k)
x=x+1
print(credit)

Without the re module you could this.
First of all ensure that the input is exactly 16 characters and is comprised entirely of digits.
Then print 12 asterisks (constant) followed by the last 4 characters of the input which can be achieved with traditional slicing.
while len(ccn := input('Please input credit card number: ')) != 16 or not ccn.isdigit():
print('Must be 16 digits. Try again')
print('*'*12, ccn[-4:], sep='')

import re
print(re.sub('\d{12}', '*'*12, credit))

Related

Python Output not Aligned Using Space and Tab

My code is here:
days = int(input("How many days did you work? : "))
totalSalary = 0
print("Day", "\tDaily Salary", "\tTotal Salary")
for day in range(days):
daily = 2**day
totalSalary += daily
print(day+1, "\t ", daily, "\t\t ", totalSalary)
When I enter 6 as input, here is the output:
Day Daily Salary Total Salary
1 1 1
2 2 3
3 4 7
4 8 15
5 16 31
6 32 63
Why last 2 lines are not aligned?
Edit: I forgot to say that I know there are better solutions like using format, but I just wanted to understand why there is problem with tabs and spaces.
Edit2: The visualization of tabstops in Jason Yang's answer satisfied me.
For statement
print(day+1, "\t ", daily, "\t\t ", totalSalary)
each '\t' will stop at 1, 9, 17, ..., at each 8th character
So it will look like this
1=------____=1=-........____=1
2=------____=2=-........____=3
3=------____=4=-........____=7
4=------____=8=-........____=15
5=------____=16=--------........=31
6=------____=32=--------........=63
12345678123456781234567812345678 <--- Tab stop before each 1
Here
= is the separator space between each two arguments of print
- is the space generated by not-last TAB
_ is the space specified by you in your print.
. is the sapce generated by last TAB.
From here you can find the differece why they stop at different position.
Try to add option sep='' in your print, or change the numbers of spaces you added.
print(day+1, "\t ", daily, "\t\t ", totalSalary, sep='')
then it will be fine.
How many days did you work? : 6
Day Daily Salary Total Salary
1 1 1
2 2 3
3 4 7
4 8 15
5 16 31
6 32 63
When the 2nd columns has double digit values, the rest of the tab and 3rd column gets shifted. You must use zero padding for the values, if you expect correctly aligned column values.
If your python version is 3+, and if you want 2 digit values, you can call print(f'{n:02}'), so as to print 01 if the value of n was having 1.
For 2.7+ version of python, you could use the format like so print('{:02d}'.format(n)).
tab is not just collection of white spaces
Any character before tab fills the space.
>>> print("A\tZ")
A Z
>>> print("AB\tZ")
AB Z
>>> print("ABC\tZ")
ABC Z
and if there are no spaces to fill tab, then it will be shifted
>>> print("ABCDEFGH\tZ")
ABCDEFGH Z
I suppose your question is due to a misunderstanding on what a tab character is and how it behaves:
A tab character should advance to the next tab stop. Historically tab stops were every 8th character, although smaller values are in common use today and most editors can be configured. Source:
How many spaces for tab character(\t)?
try this and see:
print('123456789')
print('1\t1')
print('12\t1')
print('123\t1')
I think that you added too much spaces in " print(day+1, "\t ", daily, "\t\t ", totalSalary)".
when you remove the tab spaces you will not get the "not aligned" problem.
Dynamic space declaration. Due to length of the digit
days = int(input("How many days did you work? : "))
totalSalary = 0
day_data = []
for day in range(days):
daily = 2**day
totalSalary += daily
day_data.append([day+1,daily,totalSalary])
num_space = len(str(day_data[-1][-1]))+2
f_space_len, s_space_len = 5+num_space, 9+num_space
print(f"Day{num_space*' '}Daily Salary{num_space*' '}Total Salary")
for i in day_data:
day, daily, totalSalary = map(str, i)
print(day, (f_space_len-len(day)+1)*' ', daily,(s_space_len-len(daily)+1)*' ', totalSalary)

How can I extract numbers based on context of the sentence in python?

I tried using regular expressions but it doesn't do it with any context
Examples::
"250 kg Oranges for Sale"
"I want to sell 100kg of Onions at 100 per kg"
You can do something like this.
First you split the text in words and then you try to convert each word to a number.
If the word can be converted to a number, it is a number and if you are sure that a quantity is always followed by the word "kg", once you find the number you can test if the next word is "kg".
Then, depending on the result, you add the value to the respective array.
In this particular case, you have to assure the numbers are written alone (e.g. "100 kg" and not "100kg") otherwise it will not be converted.
string = "250 kg Oranges for Sale. I want to sell 100 kg of Onions at 100 per kg."
# Split the text
words_list = string.split(" ")
print(words_list)
# Find which words are numbers
quantity_array = []
price_array = []
for i in range(len(words_list)):
try:
number = int(words_list[i])
# Is it a price or a quantity?
if words_list[i + 1] == 'kg':
quantity_array.append(number)
else:
price_array.append(number)
except ValueError:
print("\'%s\' is not a number" % words_list[i])
# Get the results
print(quantity_array)
print(price_array)

Using split(":") to get numbers from a string but I keep missing the first number

I need to extract 2 numbers from several strings.
This is an example and the code i am using:
data = 'Ant Graph first exam is :2 and the score after the second exam is :10'
print ([int (s) for s in data.split(":") if s.isdigit()])
output [10]
but if I remove the : and change a bit the code:
data = 'Ant Graph first exam is 2 and the score after the second exam is 10'
print ([int (s) for s in data.split(" ") if s.isdigit()])
output [2, 10]
Why in the first case do I miss the number 2?
the reason the first code doesn't work is because it split you data like this :
["Ant Graph first exam is","2 and the score after the second exam is ","10"]
So when you try to test isdigit() on the second item this cannot return a digit because "2" is inside a larger string. And "10" is by itself.
Hope it's clear and i'm not wrong.

How to split string such that it contains less than n characters with a twist

I have a long string which I want to save to a file. Words are separated by spaces. It is given that the number of words in long string is divisible by 3.
Basically I'm looking for a way to split string into chunks. Each chunk is less than n characters and the number of words in a chunk is also divisible by 3.
e.g.
>>> longstring = "This is a very long string and the sum of words is divisible by three"
>>> len(longstring.split())
>>> 15
say max line length is n=30:
>>>split_string(longstring, 30)
['This is a very long string', 'and the sum of words is', 'divisible by three']
In summary, the rules are:
No line longer than n characters.
A twist is that each new line must contain multiple of 3 words.
So far I tried using textwrap but I don't know how to implement 2.
import textwrap
textwrap.fill(long_line, width=69)
If you are certain that the total number of words in a string will always be divisible by 3, you can do something like this:
import sys
#long string; 84 words; divisible by 3
longString = "The charges are still sealed under orders from a federal judge. Plans were prepared Friday for anyone charged to be into custody as soon as Monday, the sources said. It is unclear what the charges are. A spokesman for the special counsel's office declined to comment. The White House also had no comment, a senior administration official said Saturday morning. A spokesman for the special counsel's office declined to comment. The White House also had no comment, a senior administration official said Saturday morning."
#convert string to list
listOfWords = longString.split()
#list to contain lines
lines = []
#make sure number of words is divisible by 3
if len(listOfWords) % 3 != 0:
#exit
print "words number is not divisible by 3"
sys.exit()
#keep going until list is empty
while listOfWords:
i = 0
line = ""
#loop for every line
while True:
#puts the next 3 words into a string
temp = " ".join(listOfWords[i:i+3])
#check new length of line after adding the new 3 words, if it is still less than 70, add the words, otherwise break out of the loop
if len(line) + len(temp) > 70:
break
line += "{} ".format(temp)
i+=3
#remove finished words from the list completely
listOfWords = listOfWords[i:]
#adds line into result list
lines.append(line.strip())
#to make sure this works
for line in lines:
print len(str(line))
print "Number of words: {}".format(len(line.split()))
print "number of chars: {}".format(len(line))
print line
print "----------------------------------------"

Why is my function is not able to find a phone number in the given string?

I was writing some code that would find a phone number, if any in a given string. Here’s the code:
def k(num):
import sys
def f():
print('NO')
sys.exit()
if (num[0:2]).isdecimal() and (num[4:6]).isdecimal() and (num[8:11]).isdecimal():
pass
else:
f()
if num[3]=='-' and num[7]=='-' :
print('The number that I found is' + ' ' + str(num))
else:
f()
inpt1=input('please enter the string.')
inpt2=inpt1.split()
for i in inpt2:
if len(i)==12:
k(i)
else:
pass
The number should be of the format xxx-xxx-xxxx.
I then copied some text from Wikipedia “These compact structures guide the interactions between DNA and other proteins, helping control which parts of the DNA are transcribed.DNA was first isolated by Friedrich Miescher in 1869. Its molecular structure was first identified by James Watson and Francis 123-333-1111 Crick at the Cavendish Laboratory within the University of Cambridge” and inserted a number (123-333-1111) somewhere in the middle of the text but the program is just returning NO instead of returning that number. Why is this happening?
Also, if I put in some simple input like:
My name is Harry Potter. My number is 222-333-1111
Then the code works perfectly fine!
EDIT: The code that would work is :
def k(num):
while True:
if (num[0:2]).isdecimal() and (num[4:6]).isdecimal() and (num[8:11]).isdecimal():
pass
else:
break
if num[3]=='-' and num[7]=='-' :
print('The number that I found is' + ' ' + str(num))
break
else:
break
inpt1=input('please enter the string.')
inpt2=inpt1.split()
for i in inpt2:
if len(i)==12:
k(i)
else:
pass
I executed your code and after a run, I found that the problem is that in the input text, the word interactions is also of 12 characters. So initially the criterion to enter the function is met but inside the function it fails the first criterion as its a word and it prints NO and the statement sys.exit() is executed therefore the other words are never checked.Hope this helps.
You can simply use re to easily achieve the desired result.
>>> import re
>>> re.findall(r'\d{3}\-\d{3}\-\d{4}', 'My name is Harry Potter. My number is 222-333-1111')
['222-333-1111']
>>> tmp = 'These compact structures guide the interactions between DNA and other proteins, helping control which parts of the DNA are transcribed.DNA was first isolated by Friedrich Miescher in 1869. Its molecular structure was first identified by James Watson and Francis 123-333-1111 Crick at the Cavendish Laboratory within the University of Cambridge'
>>> re.findall(r'\d{3}\-\d{3}\-\d{4}', tmp)
['123-333-1111']
This \d{3}\-\d{3}\-\d{4} part basically implies that we need to find a pattern which starts with 3 digit, then a -, then 3 digit, then a -, and finally another 4 digit.

Categories