I saw this question somewhere.
There is a 8 digit number. First digit from left to right tells how many zeroes in the number. Second digit tells you how many 1s in the number, third digit tells u how many 2 in the number and so on till 8th digit which tells u how many 7 in the number. Find the number.
So I wrote a piece of code in python to find out the digit. Apart from the conditions mentioned above, I have few additional checks like 'sum of digits should be 8' and 'no 8 or 9 should be present in the number'. I've pasted the code below. This is just brute force since I take every number and check for conditions. I was curious to know if there is any better way of solving the problem
def returnStat(number, digit, count):
number = str(number)
digit = str(digit)
print "Analysing for ",digit," to see if it appears ",count, " times in ",number,"."
actCnt = number.count(digit)
count = str(count)
actCnt = str(actCnt)
if (actCnt == count):
return 1
else:
return 0
def validateNum(number):
numList = str(number)
if '8' in numList:
print "Skipping ",number, " since it has 8 in it"
return (-1)
elif '9' in numList:
print "Skipping ",number, " since it has 9 in it"
return (-1)
elif (sum(int(digit) for digit in numList) != 8):
print "Skipping ",number, " since its sum is not equal to 8"
return (-1)
index = 0
flag = 0
for num in numList:
if (returnStat(number,index,num)) :
index = index+1
continue
else:
flag = 1
break
if (flag == 1):
return (-1)
else:
return number
for num in range(0,80000000):
number = '{number:0{width}d}'.format(width=8,number=num)
desiredNum = "-1"
desiredNum = validateNum(number)
if (desiredNum == -1):
print number," does not satisfy all "
continue
else:
print "The number that satisfies all contition is ",number
break
You can go further than to simply say that digits of 8 or 9 are impossible.
Can the last digit ever be greater than 0? The answer is no. If the last digit was 1, this means there is one 7 somewhere else. However, if there is a 7, it means that the same number has occurred 7 times. This is clearly impossible. Thus the last digit has to be 0.
So we have xxxxxxx0.
What about the second to last digit?
If xxxxxx10, then there has to be at least one 6, which means the same number occurred 6 times. We can try 60000010, but this is incorrect, because there is a 1, which should be reflected in the second digit. The second to last digit can't be higher than 1 because 2 means there are 2 sixes, which in turn means one number occurred six times while another number also occurred 6 times, which is impossible.
So we have xxxxxx00.
If xxxxx100, then there has to be at least one 5, which means the same number occurred 5 times. Let us start with 51000100. Almost, but there are now 2 1s. So it should be 52000100. But wait, there are now one 1. and one 2. So we try 52100100. But now we only have 4 0s. We can't have xxxxx200 because this means there are 2 5s, which is impossible as explained above.
So we have xxxxx000.
If xxxx1000, we can try 40001000, nope, 41001000, nope, 42101000.
Ah there it is. 42101000.
Even if you iterate over all 8 digit numbers with no 8s or 9s in them, there's not many possibilities (actually, 8^8 = 1<<24 ~= 17 million).
Here's a naive program that tries them all:
import itertools
for digs in itertools.product(range(8), repeat=8):
counts = [0] * 8
for d in digs:
counts[d] += 1
if counts == list(digs):
print digs
It completes (with exactly one solution) in 15 seconds on my machine.
To make it faster, you can only consider 8-digit numbers whose digits add up to 8. Here's the same code as before, but now it uses sum_k to produce the possibilities. (sum_k(n, k) generates all n-digit tuples where all the digits are less than 8 which sum to k).
def sum_k(n, k):
if k < 0 or n * 7 < k: return
if n == 1:
yield k,
return
for d in xrange(8):
for s in sum_k(n-1, k-d):
yield (d,) + s
for digs in sum_k(8, 8):
counts = [0] * 8
for d in digs:
counts[d] += 1
if counts == list(digs):
print digs
This code completes in 0.022 seconds on my machine.
Adapting the code to solve the general case produces these solutions:
1210
2020
21200
3211000
42101000
521001000
6210001000
72100001000
821000001000
9210000001000
Related
I need to make a program in Python that do this:
Write a program that, for a given sequence of digits, prints the number of different three-digit even numbers that can be formed from the given digits. When forming each three-digit even number, each element of the sequence of digits can be used at most once.
The first line of the standard input contains the number of digits N, such that 3≤N≤50000. In the second row is N digits separated by one space.
Print only one number to the standard output, the requested number of three-digit numbers.
n=int(input())
num=[]
for i in range (n):
num.append ()
Input
4
2 4 2 2
Output
4
Explanation
From the digits 2, 4, 2, 2, 4 different three-digit even numbers can be formed, namely 222, 224, 242, 422.
This is a general solution that checks all permutations of these digits and print even numbers out of them:
from itertools import permutations
k = 3
c = 0
n = int(input())
num = input().strip().split(" ")
perms = set(permutations(num, k))
for perm in perms:
t = int("".join(perm))
if t % 2 == 0 and len(str(t)) == k:
print(t)
c += 1
print(c)
This is another solution if you don't want to use this generalized approach and just want to solve it for 3 digits:
c = 0
n = int(input())
num = [int(x) for x in input().strip().split(" ")]
r = set()
for i in range(n):
for j in range(n):
for k in range(n):
if i == j or i == k or j == k:
continue
t = num[i] * 100 + num[j] * 10 + num[k]
if t % 2 == 0 and len(str(t)) == 3:
r.add(t)
print(r)
print(len(r))
First You should declare which user input u expect and how to handle false input.
Then the inputString is split into a list of Strings aka inputList. Now You can loop through each of those inputItem and check if they fit your expectations (is int and smaller then 10 ). Since You still deal with String Items You can try to cast ( convert them) into Int. That can fail and a unhandled failure could cripple Your script so it has to happen in an try- catch-block. If the casting works You wanna make sure to check your matchList if You allready added a simular number before You add the new Number to Your matchList.You do so again by looping through each item. If there is mo such number yet there is a last check for if the number is uneven or 0. In that case there is one possible combination less for each number that is 0 or uneven so they are counted in the variable minusOneCombi. That will be substrated from the maximum amount of combinations which is the amount of numbers in you matchList multiplied with itself (pow(2)). Be very careful with the Indentations. In Python they are determining the ends of if blocks and loops.
InputString=(input("Enter your number stream eg 1 0 0 5 ( non numeric signs and numbers greater 9 will be ignored): "))
inputList= inputString.split(‘ ’)
matchList=[]
minusOneCombi= 0
for inputItem in inputList:
try:
anInt= int(inputItem)
except ValueError:
# Handle the exception
print(“item is not an integer and therefore ignored”)
NotYetinMatchList= True
for MatchItem in MatchList:
If matchItem == inputItem:
notYetinMatchList= False
Break
If notYetinMatchList:
matchList.append(anInt)
if ((anInt % 2) != 0) OR (anInt ==0):
minusOneCombi++
NumofMatches=matchList.count()
NumOfMatchesPow= pow(NumofMatches,2)
Result=NumOfMatchesPow -minusOneCombi
Print(Result)
I am writing code to solve the following codewars question: https://www.codewars.com/kata/5f79b90c5acfd3003364a337/train/python
My idea is to take all the integers from 1 to n, and take the last digit of each of these integers (bar 0), multiply them together, and return the 'last' non-zero digit of the result:
def last_digit(n):
factorials = []
factorials_n = 1
for i in range(1,n + 1):
i = str(i)
i = i[::-1]
for j in i:
if j == "0":
break
factorials.append(j)
break
# at this point factorials contains the first non-zero integers of each integer in reverse
for i in factorials:
factorials_n = factorials_n * int(i)
factorials_n = str(factorials_n)
factorials_n = factorials_n[::-1]
for i in factorials_n:
if i != "0":
return int(i)
The code passes a number of tests, but fails for 387 (returns 6, should be 2) and 1673 (returns 2 should be 4). I've tried doing print statements as debug but the code seems fine, perhaps it's the logic that fails at some point- any ideas?
The problem here is with the logic. Since you are dropping all the cases where the number ends in 0, we do not arrive at the correct answer.
Consider 2 x 8 x 30. To get the last digit of the factorial, multiplying last digits would suffice, but to find the last non zero digit, you have to evaluate 2 x 8 x 3
instead.
Using this solution as a reference, here's what you can do:
def last_digit(n):
# factorials = []
# factorials_n = 1
last = 1
d2 = 0
for i in range(1,n + 1):
ii = i
print(ii)
while(ii%2==0):
d2 +=1
ii = ii/2
while(ii%5==0):
d2 -=1
ii = ii/5
print(d2)
last = (last * ii)%10
print(last)
for i in range(0,d2):
last = (last *2)%10
return int(last)
Your code passes the test cases for numbers uptill 24, it fails when the non-zero digit from 25! gives an incorrect answer which get propogated forward for the numbers after it.
And also we can simply use the modulo operator to get the very last digit instead of converting it into a string
Example: 1234 % 10 equals 4 (which is the last digit)
My solution:
def last_digit(n):
factorial = 1
for i in range(1, n + 1):
# compute the factorial
prod = factorial * i
# keep dividing the product by 10 until the last digit is a !0 digit
while prod % 10 == 0:
prod = prod // 10
# only store the last 3 digits of the computed product.
# You can keep more digits to get accurate results for
# when the numbers are higher than 10000
factorial = prod % 1000
# return the last digit
return factorial % 10
As i said earlier, when the last !0 digit from 24! (6) is multiplied with 25, it outputs 150 which after removing the 0 gives 5 but it instead should be 4. Hence, in order to solve this we keep at least the last 3 digits instead of only the last digit.
Example: 6 * 25 = 150 => 5 (last !0 digit)
936 * 25 = 23400 => 4 (last !0 digit)
PS: !0 = non-zero
I tried to do the codewars Sum of Digits/Digital Root problem, where you have to:
Given n, take the sum of the digits of n. If that value has more than one digit, continue reducing in this way until a single-digit number is produced. The input will be a non-negative integer.
So passing through 52 would return 7, as 5 + 2 is 7 and passing through 942 would return 6, as 9 + 4 + 2 = 15 and then 1 + 5 = 6.
I came up with this code:
def digital_root(n):
n_str = str(n)
digit_total = 0
while len(n_str) != 1:
for digit in n_str:
digit_total += int(digit)
n_str = str(digit_total)
return(n_str)
But it only works for 2 digit numbers and it won't work for higher digit numbers, it just endlessly runs. This code is probably a bad way to do it and I've looked over other people's answers and I get their solution but I just don't get why this won't work for higher digit numbers.
You have got your program almost right. The only challenge I see is with resetting the variable digit_total = 0 after each iteration.
def digital_root(n):
n_str = str(n)
while len(n_str) != 1:
digit_total = 0 #move this inside the while loop
for digit in n_str:
digit_total += int(digit)
n_str = str(digit_total)
return(n_str)
print (digital_root(23485))
The output for print (digital_root(23485)) is 4
2 + 3 + 4 + 8 + 5 = 22
2 + 2 = 4
If the digit_total = 0 is not inside the while loop, then it keeps getting added and you get a never ending loop.
While you have a lot of code, you can do this in a single line.
def sum_digits(n):
while len(str(n)) > 1: n = sum(int(i) for i in str(n))
return n
print (sum_digits(23485))
You don't need to create too many variables and get lost in keeping track of them.
Alex,
running a recursive function would always be better than a while loop in such scenarios.
Try this :
def digital_root(n):
n=sum([int(i) for i in str(n)])
if len(str(n))==1:
print(n)
else:
digital_root(n)
As a problem, we're tasked to write up a recursive backtracking program that prints all numbers with P digits such that every 3 consecutive digit of that number sums up to S.
I cannot formulate a recursive backtracking approach yet, but I was able to make one with simple loops and complete search.
def count(P, S):
if P >= 3:
for number in range(10**(P-1), (10**P)):
string = str(number) # I converted it to string to easily access every digit of the number.
isEqual = True
for digit in range(0, len(str(i))-2):
if int(string[digit]) + int(string[digit + 1]) + int(string[digit + 2]) != S:
isEqual = False
break
if isEqual: print(i)
How is it done recursively?
This is a simple and unoptimized version:
max_digits = 5
tot_sum = 12
max_digit = 9
min_digit = 0
digits = {x for x in range(min_digit, max_digit + 1)}
def print_valid_number(cur_digit_i, max_digits, tot_sum, last_2sum, digits, cur_num):
if cur_digit_i == max_digits:
print(''.join(map(str, cur_num)))
return
cur_digits = set(digits)
if cur_digit_i == 0 and 0 in cur_digits:
cur_digits.remove(0)
for d in cur_digits:
if last_2sum + d == tot_sum or cur_digit_i == 0 or cur_digit_i == 1:
cur_num.append(d)
next_last_2sum = d + (0 if cur_digit_i == 0 else cur_num[cur_digit_i - 1])
print_valid_number(cur_digit_i + 1, max_digits, tot_sum, next_last_2sum, digits, cur_num)
cur_num.pop()
print_valid_number(0, max_digits, tot_sum, 0, digits, [])
You basically pass the sum of the last 2 digits (last_2sum) on each recursive step and, for each digit, check if last_2sum + current_digit == S. The only exception are the first 2 indexes where you just loop all 9/10 digits.
Code should not be hard to understand, but from the brief description, it is clear that you have many doable optimizations. Here few of them:
You could limit the range of possible digits. For instance, if S == 20, in the final number you are definitely not going to find the digit 1. Conversely, if S == 8, the highest digit is going to be 8.
You can reduce the number of recursions by optimizing the first 2 indexes (it is almost unremarkable)
If you run this code, you will find that from the 4th digits, the first 3 ones are repeating. This is a huge optimization.
I am trying to implement Luhn algorithm in Python. Here is my code
def validate(n):
if len(str(n)) > 16:
return False
else:
if len(str(n)) % 2 == 0:
for i in str(n[0::2]):
digit = int(str(n[i])) * 2
while digit > 9:
digit = sum(map(int, str(digit)))
dig_sum = sum(map(int, str(n)))
return True if dig_sum % 10 == 0 else False
elif len(str(n)) % 2 != 0:
for i in str(n[1::2]):
digit = int(str(n[i])) * 2
while digit > 9:
digit = sum(map(int, str(digit)))
dig_sum = sum(map(int, str(n)))
return True if dig_sum % 10 == 0 else False
I keep getting the error
TypeError: 'int' object has no attribute '__getitem__
Following is python implementation of Lunh Algorith to detect a valid credit card number. Function takes a number as string and return whether its valid credit card or not.
Its based on the steps mentioned in the following link: https://www.codeproject.com/Tips/515367/Validate-credit-card-number-with-Mod-algorithm
Step 1 - Starting with the check digit double the value of every other digit (right to left every 2nd digit)
Step 2 - If doubling of a number results in a two digits number, add up the digits to get a single digit number. This will results in eight single digit numbers.
Step 3 - Now add the un-doubled digits to the odd places
Step 4 - Add up all the digits in this number
If the final sum is divisible by 10, then the credit card number is valid. If it is not divisible by 10, the number is invalid.
def luhn(ccn):
c = [int(x) for x in ccn[::-2]]
u2 = [(2*int(y))//10+(2*int(y))%10 for y in ccn[-2::-2]]
return sum(c+u2)%10 == 0
#Test
print(luhn("49927398716"))
It is hard to tell without the complete error message, but it is likely because you confused in some places where you put the indexing and where you put the string conversion, for example: for i in str(**n[1::2]**) and digit = int(str(**n[i]**)) * 2
A good way to handle it is to just create a temporary variable n_str = str(n), and use it instead of str(n) over and over again.