Python: Splitting numbers and factor them to 2 - python

This code is to identify if the number factored to 2 for the 4th time, would get 1 or not.
a = int(input())
terms = 4
result = list(map(lambda x: a ** x, range(terms)))
for i in range(terms):
print(a, "^2 = ", result[i])
if result == 1:
print('True')
else:
print('False')
If I input 14, this is the result:
14 ^2 = 1
14 ^2 = 14
14 ^2 = 196
14 ^2 = 2744
False
But I want it to be like this.
1^2 + 4^2 = 17
1^2 + 7^2 = 50
5^2 + 0^2 = 25
2^2 + 5^2 = 29
False

Try this:
a = str(int(input()))
def split_and_print(a):
x = [int(y) for y in list(str(a))]
return sum([y**2 for y in x])
def split_sum_print(a):
a_split = list(str(a))
print(' + '.join([x+'^2' for x in a])+ ' = '+str(split_and_print(a)))
return str(split_and_print(a))
n = 4
for i in range(n):
a = split_sum_print(a)
if a == '1':
print(True)
else:
print(False)
Output:
14
1^2 + 4^2 = 17
1^2 + 7^2 = 50
5^2 + 0^2 = 25
2^2 + 5^2 = 29
False
I made two functions, one responsible for calculation, the other for printing. Then combined them and used a for loop. Change n for different number of iterations.

First of all, a = str(int(input())) seems quite unnecessary, as input() returns string by itself.
Second, you then cast it to string ... in str(a): once again (again unnecessary).
And third of all, you are iterating over some string (a in this case), which would product a stream of single characters, but your code is written as if you expected tuples instead...?
For example
for char in "abc":
print(char)
... would print
a
b
c
What you essentially have
for a, b in "abc":
print(a, b)
... what should happen here?
What do you expect to happen with your code, exactly? 🤔

Related

How to increment alphanumeric number in python?

I am creating a passkey of 16 alphanumeric characters where I am generating starting 4 digits with A001, A002, A003 till A999. Once it goes till A999, the alphabet will auto increase to B and digits will again start with 001. And the same process will go till Z999. Once the A-Z series will over, then it will start with AA01 and so on. How to do this thing in python? As I am new in python so I tried it on my own and also tried some examples but I am unable to make the increment of characters.
Any ideas or thoughts would be greatly appreciated.
Many thanks
rec=0
new_list16 = []
def autoIncrement():
global rec
first = 'A'
i = chr(ord(first))
new_list16.append(i)
while True:
pStart = 1 #adjust start value, if req'd
pInterval = 1 #adjust interval value, if req'd
if (rec == 0):
rec += pStart
else:
rec = rec + pInterval
return str(rec).zfill(3)
#print(autoIncrement())
new_list16.append(autoIncrement())
print(*new_list16, sep = '')
Going from A999 to B001 instead of B000 really messes things up a bit, but you can still use this for the A-Z part, and a simple modulo operation for the numbers.
def excel_format(num):
# see https://stackoverflow.com/a/182924/1639625
res = ""
while num:
mod = (num - 1) % 26
res = chr(65 + mod) + res
num = (num - mod) // 26
return res
def full_format(num, d=3):
chars = num // (10**d-1) + 1 # this becomes A..ZZZ
digit = num % (10**d-1) + 1 # this becomes 001..999
return excel_format(chars) + "{:0{}d}".format(digit, d)
for i in range(10000):
print(i, full_format(i, d=2))
Number of digits in the numeric part is controlled with the optional d parameter. I'll use 2 for purpose of demonstration, but 3 works just as well.
0 A01
...
98 A99
99 B01
...
2573 Z99
2574 AA01
...
9998 CW99
9999 CX01
def auto_increment(number):
if number == 'ZZZZ':
return 'ZZZZ'
digits = "".join([i for i in number if i.isdigit()])
chars = "".join([i for i in number if not i.isdigit()])
if int(digits) == int('9' * len(digits)):
digits = "000"
new_char = [ord(i) for i in chars]
if new_char[-1] % ord('Z') == 0:
new_char = "".join([chr(i) for i in new_char]) + 'A'
else:
new_char[-1] = new_char[-1] + 1
new_char = "".join([chr(i) for i in new_char])
else:
new_char = chars
new_digit = int(digits) + 1
l = len(new_char)
ll = len(str(new_digit))
new_digit = (("0" * (3-ll)) + str(new_digit))[(l-1):]
return f"{new_char}{new_digit}"
This function return you the next number, given any number.
for example: A999 will return AB01.
you can now just use this function in a loop.
This probably needs to be tested and refactored more, but here's a start for you:
def leadingZeros(number, digits):
numberString = str(number)
for digit in range(1, digits):
if number < 10**digit:
numberString = '0' + numberString
return numberString
def autoIncrement(oldNumber):
order = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!'
lastDigitOrder = order.find(oldNumber[3])
newNumber = ''
if order.find(oldNumber[1]) <= 9:
# 3 digit number
number = int(oldNumber[1:]) + 1
letter = oldNumber[0]
if 1000 == number:
letterOrder = order.find(oldNumber[0])
letter = order[letterOrder + 1]
newNumber = letter + leadingZeros(number % 1000, 3)
elif order.find(oldNumber[2]) <= 9:
# 2 digit number
number = int(oldNumber[2:]) + 1
letters = oldNumber[0:2]
if 100 == number:
letterOrder = order.find(oldNumber[1])
letter = order[letterOrder + 1]
letters = oldNumber[0] + letter
newNumber = letters + leadingZeros(number % 100, 2)
elif order.find(oldNumber[3]) <= 9:
# 1 digit number
number = int(oldNumber[3]) + 1
letters = oldNumber[0:3]
if 10 == number:
letterOrder = order.find(oldNumber[2])
letter = order[letterOrder + 1]
letters = oldNumber[0:2] + letter
newNumber = letters + leadingZeros(number % 10, 1)
else:
# just letters
print(oldNumber)
letterOrder = order.find(oldNumber[3])
letter = order[letterOrder + 1]
newNumber = oldNumber[0:3] + letter
# if one of the digits has gone past Z then we need to update the letters
if '!' == newNumber[3]:
# past Z in 4th digit
letterOrder = order.find(oldNumber[2])
newNumber = newNumber[0:2] + order[letterOrder + 1] + 'A'
if '!' == newNumber[2]:
# past Z in 3rd digit
letterOrder = order.find(oldNumber[1])
newNumber = newNumber[0:1] + order[letterOrder + 1] + 'A' + newNumber[3]
if '!' == newNumber[1]:
# past Z in 2nd digit
letterOrder = order.find(oldNumber[0])
newNumber = order[letterOrder + 1] + 'A' + newNumber[2:]
return newNumber
print(autoIncrement('A999'))
print(autoIncrement('AA99'))
print(autoIncrement('AAA9'))
print(autoIncrement('AAAA'))
print(autoIncrement('AZZ9'))
This is not quite what you are asking for, but if your requirement is for 4-character "sequential" strings, let me suggest a far more simpler approach. Why not simply used base 36 numbers? That is, have your numbers go from 0, 1, 2, ... A, B, C, ... Z, 10, 11, 12, ... 1Z, ... Then to convert one of the base 36 strings to an int it is simply:
n = int('12AV', 36)
And to convert an int to a base n string:
def baseN(num, base, numerals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
return ((num == 0) and numerals[0]) or (baseN(num // base, base, numerals).lstrip(numerals[0]) + numerals[num % base])
Putting it all together:
n = int('12AV', 36)
s = baseN(n + 1, 36)
print(s)
Prints:
12AW
You can, of course, start with 'A001' if you need to. You will then go to A00Z after 35 iterations. You will end up generating the same numbers as in your original method, just in a different order.
Thank you for the solutions you had provided. But I tried something exactly which I want for my question. Please check it and give your comments on it.
def full_format(i):
# limit of first range is 26 letters (A-Z) times 999 numbers (001-999)
if i < 26 * 999:
c,n = divmod(i,999) # quotient c is index of letter 0-25, remainder n is 0-998
c = chr(ord('A') + c) # compute letter
n += 1
return f'{c}{n:03}'
# After first range, second range is 26 letters times 26 letters * 99 numbers (01-99)
elif i < 26*999 + 26*26*99:
i -= 26*999 # remove first range offset
cc,n = divmod(i,99) # remainder n is 0-98, use quotient cc to compute two letters
c1,c2 = divmod(cc,26) # c1 is index of first letter, c2 is index of second letter
c1 = chr(ord('A') + c1) # compute first letter
c2 = chr(ord('A') + c2) # compute second letter
n += 1
return f'{c1}{c2}{n:02}'
else:
raise OverflowError(f'limit is {26*999+26*26*99}')
for i in range(92880, 92898):
print(full_format(i))

sequence of repeated values in a list

I have problems with a program, I hope someone can help me to fix this. Basically I have a random generated list with 20 values, and I want to place between brackets the values that are repeated (for example if the list is [1,2,2,4,5] it should display 1 ( 2 2 ) 4 5 )
Now here's my code that works only if there is no repeated value in the end, because the list index goes out of range. How can I fix this?
from random import randint
lanci = []
for i in range(20):
x = randint(1,6)
lanci.append(x)
print(lanci)
i=0
while i < len(lanci)-1):
if lanci[i] == lanci[i+1]:
print("(",end=" ")
print(lanci[i],end=" ")
while lanci[i]==lanci[i+1]:
i = i + 1
print(lanci[i],end=" ")
print(")",end=" ")
else:
print(lanci[i],end=" ")
i = i + 1
Alternatively to your more manual approach, you could use itertools.groupby to group equal values in the list and then enclose those in parens:
>>> import random, itertools
>>> lst = [random.randint(1, 5) for _ in range(20)]
>>> tmp = [list(map(str, g)) for k, g in itertools.groupby(lst)]
>>> ' '.join(g[0] if len(g) == 1 else "(" + " ".join(g) + ")" for g in tmp)
'5 4 1 2 1 4 (5 5) 4 5 1 5 4 3 (5 5) 3 (5 5 5)'
Not the pretiest but will do it:
from random import randint
from itertools import groupby
lanci = [randint(1,6) for _ in range(20)]
result = [tuple(v) for _, v in groupby(lanci)]
print(*[i[0] if len(i) == 1 else '('+' '.join(map(str, i))+')' for i in result], sep=' ')
#(2 2) 3 5 3 1 5 4 6 2 1 4 6 4 (5 5) 3 6 3 4
Just check for "last element" before your inner while loop.
from random import randint
lanci = []
for i in range(20):
x = randint(1,6)
lanci.append(x)
print(lanci)
i=0
while i < len(lanci)-1):
if lanci[i] == lanci[i+1]:
print("(",end=" ")
print(lanci[i],end=" ")
while (i+1 < len(lanci)) and (lanci[i]==lanci[i+1]):
i = i + 1
print(lanci[i],end=" ")
print(")",end=" ")
else:
print(lanci[i],end=" ")
i = i + 1
convert the list of number to a string then you can use this function.
split it if you need the list back again.
def add_brackets(string):
_character, _index = None, 0
_return_string = ''
for i, c in enumerate(string+ ' '):
if _character is None or _character != c :
if len(string[_index:i])>1:
_return_string+='(' + string[_index: i] + ')'
else:
_return_string+=string[_index: i]
_character, _index = c, i
return _return_string
This is another option using just basic list:
def group_consecutives(lst):
res, sub, memo = [None], [], None
lst.append(memo)
for x in lst:
if memo == x:
sub.append(memo)
if res[-1] != sub: res.append(sub)
else:
sub.append(memo)
if memo and not len(sub) > 1: res.append(memo)
memo, sub = x, []
return res[1:]
print(group_consecutives(lanci))

Calculating Sun Angle Code

My goal with this code was to write a code that measures the degree measure of the sun having that at 6:00 the angle is 0 and at 18:00 the angle is 180 degrees. I tried to make the time input a string and then loop through its characters and pick out the integers and put it into the list that way I could avoid the colon. It seems that this is still a problem. Can someone explain to me what's wrong with this code? Why do I keep getting an "unsupported operand type error"?
def sun_angle(time):
lis = []
time = str(time)
for i in time:
if i.isdigit():
lis.append(i)
else:
continue
a = int(lis[0]*10 + lis[1] + ((lis[2] + lis[3])/60))
b = a - 6
if b < 6 or b > 18:
return "I can't see the sun!"
else:
return b * 15
print(sun_angle("12:12"))
Michael's answer is a great explanation for why what you're doing isn't working (need to convert string to int before manipulating with * and +).
However, there are a lot of ways to parse the time that will be easier to work with than what you're doing here. I'd consider splitting and then parsing the two parts, or you could use the datetime library for more complexity:
# option 1
def parse_time_as_hour(time_str):
hour_str, min_str = time_str.split(':')
return int(hour_str) + int(min_str) / 60.0
# option 2
import datetime
def parse_time_as_hour(time_str):
parsed = datetime.datetime.strptime(time_str, '%H:%M')
return parsed.hour + parsed.minute / 60.0
def sun_angle(time):
fractional_hour = parse_time_as_hour(time)
if fractional_hour < 6 or fractional_hour >= 18:
return "I can't see the sun!"
else:
return (fractional_hour - 6) * 15
If you change the above similar line to:
a = int(lis[0]) * 10 + int(lis[1]) + ((int(lis[2]) + int(lis[3]))/60)
then you get a result. The problem on that line is that you're mixing int and str types. And since you're already passing in a string you can change time = str(time) to time = time. Casting time to a string is redundant.
Your error line is:
a = int(lis[0]*10 + lis[1] + ((lis[2] + lis[3])/60))
since time is a string type
def sun_angle(time):
lis = []
time = str(time)
for i in time:
if i.isdigit():
lis.append(int(i)) #cast it to type int
else:
continue
a = int(lis[0]*10 + lis[1] + ((lis[2] + lis[3])/60))
b = a - 6
if b < 0 or b >= 12:
return "I can't see the sun!"
else:
return b * 15
print(sun_angle("12:12"))
output: 90
You need to cast lis[i] to integer when you're calculating the value of a. 07:00 means sun is up, your logic fails and 18:01 means sun is down.
def sun_angle(time_):
lis = []
time_ = str(time_)
for i in time_:
if i.isdigit():
lis.append(i)
else:
continue
a = int(lis[0])*10
a += int(lis[1])
bb = (int(lis[2])*10 + int(lis[3]))
#print a
#print bb
#b = a - 6
if (a < 6 or a > 18) or (a == 18 and bb > 0):
return "I can't see the sun!"
else:
return (float(a)-6.0) * 15.0 + (15.0*float(bb))/60.0

Python Gtin 8 Code not totaling

Hi I have been experimenting for some time to try and total 7 variables at once. I am trying to calculate the 8th number for GTIN 8 codes. I have tried many things and so far I am using float. I Don't know what it does but people say use it. I need to times the 1,3,5,7 number by 3 and 2,4,6 number by 1. Then find the total of all of them added together. I have looked everywhere and I cant find anything. Anything will help. Thanks Ben
code = input ("enter 7 digit code? ")
sum1 = 3 * (code[0] + ',')
sum2 = code[1] + ','
sum3 = 3 * (code[2] + ',')
sum4 = code[3] + ','
sum5 = 3 * (code[4] + ',')
sum6 = code[5] + ','
sum7 = 3 * (code[6] + ',')
checksum_value = sum1 + sum2 + sum3+ sum4 + sum5+ sum6 + sum7
b = str(checksum_value)
print(b)
Quick solution:
x = "1234567"
checksum_value = sum(int(v) * 3 if i in (0,2,4,6) else int(v) for (i, v) in enumerate(x[:7]))
# (1*3) + 2 + (3*3) + 4 + (5*3) + 6 + (7*3)
# ==
# 3 + 2 + 9 + 4 + 15 + 6 + 21
# ==
# sum(int(v) * 3 if i in (0,2,4,6) else int(v) for (i, v) in enumerate(x[:7]))
Explanation:
# Sum the contained items
sum(
# multiply by three if the index is 0,2,4 or 6
int(v) * 3 if i in (0,2,4,6) else int(v)
# grab our index `i` and value `v` from `enumerate()`
for (i, v) in
# Provide a list of (index, value) from the iterable
enumerate(
# use the first 7 elements
x[:7]
)
)
`enter code here`code = input ("enter 7 digit code? ")
sum1 = 3 * (code[0] + ',')
sum2 = code[1] + ','
sum3 = 3 * (code[2] + ',')
sum4 = code[3] + ','
sum5 = 3 * (code[4] + ',')
sum6 = code[5] + ','
sum7 = 3 * (code[6] + ',')
checksum_value = sum1 + sum2 + sum3+ sum4 + sum5+ sum6 + sum7
b = str(checksum_value)
print(b)
GS1 codes come in different lengths, ranging from GTIN-8 (8 digits) to SSCC (2 digit application ID + 18 digits). Here's a simple, general Python formula that works for any length GS1 identifier:
cd = lambda x: -sum(int(v) * [3,1][i%2] for i, v in enumerate(str(x)[::-1])) % 10
Explanation:
Convert input to string, so input can be numeric or string - just a convenience factor.
Reverse the string - simple way to align the 3x/1x pattern with variable-length input.
The weighting factor is selected based on odd and even input character position by calculating i mod 2. The last character in the input string (i=0 after the string has been reversed) gets 3x.
Calculate the negative weighted sum mod 10. Equivalent to the (10 - (sum mod 10)) mod 10 approach you'd get if you follow the GS1 manual calculation outline exactly, but that's ugly.
Test Cases
## GTIN-8
>>> cd(1234567)
0
>>> cd(9505000)
3
## GTIN-12
>>> cd(71941050001)
6
>>> cd('05042833241')
2
## GTIN-13
>>> cd(900223631103)
6
>>> cd(501234567890)
0
## GTIN-14
>>> cd(1038447886180)
4
>>> cd(1001234512345)
7
## SSCC (20 digits incl. application identifier)
>>> cd('0000718908562723189')
6
>>> cd('0037612345000001009')
1

How to reverse an int in python?

I'm creating a python script which prints out the whole song of '99 bottles of beer', but reversed. The only thing I cannot reverse is the numbers, being integers, not strings.
This is my full script,
def reverse(str):
return str[::-1]
def plural(word, b):
if b != 1:
return word + 's'
else:
return word
def line(b, ending):
print b or reverse('No more'), plural(reverse('bottle'), b), reverse(ending)
for i in range(99, 0, -1):
line(i, "of beer on the wall")
line(i, "of beer"
print reverse("Take one down, pass it around")
line(i-1, "of beer on the wall \n")
I understand my reverse function takes a string as an argument, however I do not know how to take in an integer, or , how to reverse the integer later on in the script.
Without converting the number to a string:
def reverse_number(n):
r = 0
while n > 0:
r *= 10
r += n % 10
n /= 10
return r
print(reverse_number(123))
You are approaching this in quite an odd way. You already have a reversing function, so why not make line just build the line the normal way around?
def line(bottles, ending):
return "{0} {1} {2}".format(bottles,
plural("bottle", bottles),
ending)
Which runs like:
>>> line(49, "of beer on the wall")
'49 bottles of beer on the wall'
Then pass the result to reverse:
>>> reverse(line(49, "of beer on the wall"))
'llaw eht no reeb fo selttob 94'
This makes it much easier to test each part of the code separately and see what's going on when you put it all together.
Something like this?
>>> x = 123
>>> str(x)
'123'
>>> str(x)[::-1]
'321'
best way is
x=12345
a=str(x)[::-1]\\ In this process i have create string of inverse of integer (a="54321")
a=int(a) \\ Here i have converted string a in integer
or
one line code is
a=int(str(x)[::-1]))
def reverse(x):
re = 0
negative = x < 0
MAX_BIG = 2 ** 31 -1
MIN_BIG = -2 ** 31
x = abs(x)
while x != 0:
a = int(x % 10)
re = re * 10 + a
x = int(x // 10)
reverse = -1 * re if negative else re
return 0 if reverse < MIN_BIG or reverse > MAX_BIG else reverse
this is for 32 - bit integer ( -2^31 ; 2^31-1 )
def reverse_number(n):
r = 0
while n > 0:
r = (r*10) + (n % 10)
print(r)
r *=10
n //= 10
return r
print(reverse_number(123))
You can cast an integer to string with str(i) and then use your reverse function.
The following line should do what you are looking for:
def line(b, ending):
print reverse(str(b)) or reverse('No more'), plural(reverse('bottle'),reverse(str(b))), reverse(ending)
Original number is taken in a
a = 123
We convert the int to string ,then reverse it and again convert in int and store reversed number in b
b = int("".join(reversed(str(a))))
Print the values of a and b
print(a,b)
def reverse_number(n):
r = 0
while n > 0:
r *= 10
r += n % 10
n /= 10
return r
print(reverse_number(123))
This code will not work if the number ends with zeros, example 100 and 1000 return 1
def reverse(num):
rev = 0
while(num != 0):
reminder = num % 10
rev = (rev * 10 ) + reminder
num = num // 10
print ("Reverse number is : " , rev )
num=input("enter number : ")
reverse(int(num))
#/ always results into float
#// division that results into whole number adjusted to the left in the number line
I think the following code should be good to reverse your positive integer.
You can use it as a function in your code.
n = input() # input is always taken as a string
rev = int(str(n)[::-1])
If you are having n as integer then you need to specify it as str here as shown. This is the quickest way to reverse a positive integer
import math
def Function(inputt):
a = 1
input2 = inputt
while(input2 > 9):
input2 = input2/10
a = a + 1
print("There are ", a, " numbers ")
N = 10
m = 1
print(" THe reverse numbers are: ")
for i in range(a):
l = (inputt%N)/m
print(math.floor(l), end = '')
N = N*10
m = m*10
print(" \n")
return 0
enter = int(input("Enter the number: "))
print(Function(enter))
More robust solution to handle negative numbers:
def reverse_integer(num):
sign = [1,-1][num < 0]
output = sign * int(str(abs(num))[::-1])
An easy and fast way to do it is as follows:
def reverse(x: int|str) -> int:
reverse_x = int(''.join([dgt for dgt in reversed(num:=str(x)) if dgt != '-']))
if '-' in num:
reverse_x = -reverse_x'
return reverse_x
First we create a list (using list comprehension) of the digits in reverse order. However, we must exclude the sign (otherwise the number would turn out like [3, 2, 1, -]). We now turn the list into a string using the ''.join() method.
Next we check if the original number had a negative sign in it. If it did, we would add a negative sign to reverse_x.
Easily you can write this class:
class reverse_number:
def __init__(self,rvs_num):
self.rvs_num = rvs_num
rvs_ed = int(str(rvs_num)[::-1])
print(rvs_ed)
You can use it by writing:
reverse_number(your number)
I have written it in a different way, but it works
def isPalindrome(x: int) -> bool:
if x<0:
return False
elif x<10:
return True
else:
rev=0
rem = x%10
quot = x//10
rev = rev*10+rem
while (quot>=10):
rem = quot%10
quot = quot//10
rev = rev*10+rem
rev = rev*10+quot
if rev==x:
return True
else:
return False
res=isPalindrome(1221)

Categories

Resources