Help! I'm a Python beginner given the assignment of displaying the Collatz Sequence from a user-inputted integer, and displaying the contents in columns and rows. As you may know, the results could be 10 numbers, 30, or 100. I'm supposed to use '\t'. I've tried many variations, but at best, only get a single column. e.g.
def sequence(number):
if number % 2 == 0:
return number // 2
else:
result = number * 3 + 1
return result
n = int(input('Enter any positive integer to see Collatz Sequence:\n'))
while sequence != 1:
n = sequence(int(n))
print('%s\t' % n)
if n == 1:
print('\nThank you! The number 1 is the end of the Collatz Sequence')
break
Which yields a single vertical column, rather than the results being displayed horizontally. Ideally, I'd like to display 10 results left to right, and then go to another line. Thanks for any ideas!
Something like this maybe:
def get_collatz(n):
return [n // 2, n * 3 + 1][n % 2]
while True:
user_input = input("Enter a positive integer: ")
try:
n = int(user_input)
assert n > 1
except (ValueError, AssertionError):
continue
else:
break
sequence = [n]
while True:
last_item = sequence[-1]
if last_item == 1:
break
sequence.append(get_collatz(last_item))
print(*sequence, sep="\t")
Output:
Enter a positive integer: 12
12 6 3 10 5 16 8 4 2 1
>>>
EDIT Trying to keep it similar to your code:
I would change your sequence function to something like this:
def get_collatz(n):
if n % 2 == 0:
return n // 2
return n * 3 + 1
I called it get_collatz because I think that is more descriptive than sequence, it's still not a great name though - if you wanted to be super explicit maybe get_collatz_at_n or something.
Notice, I took the else branch out entirely, since it's not required. If n % 2 == 0, then we return from the function, so either you return in the body of the if or you return one line below - no else necessary.
For the rest, maybe:
last_number = int(input("Enter a positive integer: "))
while last_number != 1:
print(last_number, end="\t")
last_number = get_collatz(last_number)
In Python, print has an optional keyword parameter named end, which by default is \n. It signifies which character should be printed at the very end of a print-statement. By simply changing it to \t, you can print all elements of the sequence on one line, separated by tabs (since each number in the sequence invokes a separate print-statement).
With this approach, however, you'll have to make sure to print the trailing 1 after the while loop has ended, since the loop will terminate as soon as last_number becomes 1, which means the loop won't have a chance to print it.
Another way of printing the sequence (with separating tabs), would be to store the sequence in a list, and then use str.join to create a string out of the list, where each element is separated by some string or character. Of course this requires that all elements in the list are strings to begin with - in this case I'm using map to convert the integers to strings:
result = "\t".join(map(str, [12, 6, 3, 10, 5, 16, 8, 4, 2, 1]))
print(result)
Output:
12 6 3 10 5 16 8 4 2 1
>>>
Related
I'm working on a card number check code, for now I created a function that asks for the card number and checks if it is 8 digits or not (it has to be 8) and then calls another function that will do the math and check if the card is valid. For this function:
Starting from the rightmost digit, form the sum of every other digit. For example, if the card number is 1234 5678, then you form the sum 8 + 6 + 4 + 2 = 20
Double each of the digits that were not included in the preview step and then add all digits of the resulting numbers. For example, the digits that were not included are 7 5 3 1, we double the, 14 10 6 2, and then we sum each digit, 1 + 4 + 1 + 0 + 6 + 2 = 14
Add the sums of the two steps, 20 + 14 = 34, if the last digit is 0 then the card is valid, otherwise it is not valid (which is our case)
My problem is that I don't know how to iterate and get the sum of every other digit or double the other number which were not included in step 2. My thought was to use a while loop but then what?
EDIT: since some answers used lists... we didn't study lists yet, so I should not use it, we are only allowed to use sample stuff, loops, functions, etc.. even sum(map()) we didn't study
That is my code for now (its not much but just thought put it anyway)
def getCard():
CardInput = int(input("Enter your 8 digit credit card number: "))
if len(CardInput) == 8:
CardCheck(CardInput)
else:
print("Invalid Input: Should be exactly 8 digits!")
getCard()
def CardCheck(CardNumber):
Position = 0
Sum = 0
DoubleSum = 0
FinalSum = 0
while CardNumber >= 0:
Position += 1
So, the ugly way of doing is, you can write a for loop and use indexing for access specific elements
for i in range(len(CardInput)):
# it will iterate from 0 to 7
print(CardInput[i]) # here you get ith element
if i % 2 == 1:
print("I am other!") # you can sum your things here into another variable
Or with while:
while position < len(CardInput):
print(CardInput[position])
position += 1
It assumes CardInput is str, so I recommend to not convert it earlier.
However pythonic way would be
sum(map(int, CardInput[1::2])))
CardInput[1::2] returns list of every second element starting from second (0 is first).
map converts every element to in.
sum sums elements.
prompt = "Enter the eight-digit number: "
while True:
number = input(prompt)
if len(number) == 8 and number.isdigit():
break
prompt = "Oops, try again: "
first_digits = number[1::2] # If the user entered '12345678', this will be the substring '2468'
first_sum = sum(map(int, first_digits)) # Take each digit (character), map it to a single-digit integer, and take the sum of all single-digit integers
second_digits = number[0::2] # If the user entered '12345678', this will be the substring '1357'
doubled_ints = [int(char) * 2 for char in second_digits] # Take each digit (character), turn it into an integer, double it, and put it in a list.
second_sum = sum(map(int, "".join(map(str, doubled_ints)))) # Merge all integers in 'doubled_ints' into a single string, take each character, map it to a single digit integer, and take the sum of all integers.
total_sum = first_sum + second_sum
total_sum_last_digit = str(total_sum)[-1]
is_valid_card = (total_sum_last_digit == '0')
if is_valid_card:
print("Your card is valid (total sum: {})".format(total_sum))
else:
print("Your card is NOT valid (total sum: {})".format(total_sum))
def getCard():
CardInput = input("Enter your 8 digit credit card number: ")
if len(CardInput) == 8:
CardCheck(CardInput)
else:
print("Invalid Input: Should be exactly 8 digits!")
getCard()
def CardCheck(CardNumber):
list_CardNumber = [x for x in "25424334"]
Sum = sum(int(x) for x in list_CardNumber[1:8:-2])
DoubleSum = 2*sum(int(x) for x in list_CardNumber[0:8:-2])
FinalSum = Sum + DoubleSum
if str(FinalSum)[-1] == "0":
print("Valid Input")
else:
print("Invalid Input")
To get you started, you should check out enumerate(), it'll simplify things if you're just going to use loops by giving you easy access to both the index and value every loop.
step1 = 0
for i, x in enumerate(number):
if i % 2:
print('index: '+ str(i), 'value: '+ x)
step1 += int(x)
print('step 1: ', step1)
Output:
index: 1 value: 2
index: 3 value: 4
index: 5 value: 6
index: 7 value: 8
step 1: 20
You can use:
# lets say
CardNumber = '12345678'
# as mentioned by kosciej16
# get every other digit starting from the second one
# convert them to integers and sum
part1 = sum(map(int, CardNumber[1::2]))
# get every other digit starting from the first one
# convert them to integers and double them
# join all the digits into a string then sum all the digits
part2 = sum(map(int,''.join(list(map(lambda x: str(int(x)*2), CardNumber[0::2])))))
result = part1 + part2
print(result)
Output:
34
Edit:
Only with loops you can use:
# lets say
CardNumber = '12345678'
total_sum = 0
for idx, digit in enumerate(CardNumber):
if idx % 2 == 1:
total_sum += int(digit)
else:
number = str(int(digit)*2)
for d in number:
total_sum += int(d)
print(total_sum)
output:
34
Since you need to iterate over the digits, it's actually easier IMO if you leave it as a string, rather than converting the input to an int; that way you can just iterate over the digits and convert them to int individuall to do math on them.
Given an 8-digit long string card, it might look like this, broken into steps:
even_sum = sum(int(n) for n in card[1::2])
double_odds = (2 * int(n) for n in card[0::2])
double_odd_sum = sum(int(c) for do in double_odds for c in str(do))
All together with some logic to loop while the input is invalid:
def get_card() -> str:
"""Returns a valid card number, or raises ValueError."""
card = input("Enter your 8 digit credit card number: ")
if len(card) != 8 or not card.isdecimal():
raise ValueError("Invalid input: Should be exactly 8 digits!")
card_check(card)
return card
def card_check(card: str) -> None:
"""Raises ValueError if card checksum fails, otherwise returns None."""
even_sum = sum(int(n) for n in card[1::2])
double_odds = (2 * int(n) for n in card[::2])
double_odd_sum = sum(int(c) for do in double_odds for c in str(do))
if (even_sum + double_odd_sum) % 10:
raise ValueError("Card checksum failed!")
while True:
try:
print(f"{get_card()} is a valid card number!")
except ValueError as e:
print(e)
Trying to use superset to see if a number has all 10 digits. This code should complete in 10 lines however it does not. Why is this the case? I am a beginner.
n = 1234567880
d = 1234567890
A = set(str(n))
C = set(str(d))
complete = True
print(A.issuperset(C))
while complete==True:
if A.issuperset(C) == True:
print(n)
complete = False
else:
n = n + 1
print(n)
else:
print("completed") ```
You have to reset A each iteration:
while complete:
A = set(str(n)) # n has changed!
if A == C:
# ...
Also, while-else does probably not do what you expect it to. Since you never break the while loop manually, the else will always trigger. You could shorten your code:
import string
n = 1234567880
C = set(string.digits)
while True:
print(n)
if set(str(n)) == C:
break
n += 1
print("completed")
Why not simply use set(str(n)).issuperset("0123456789") as the while condition?
The issuperset() method returns True or False so it can be used as a condition directly (no need for == True)
n = 1234567880
while not set(str(n)).issuperset("0123456789"):
print(n)
n += 1
print(n)
print("completed")
1234567880
1234567881
1234567882
1234567883
1234567884
1234567885
1234567886
1234567887
1234567888
1234567889
1234567890
completed
Note that you may not want to print inside the loop depending on the numbers you're going to start from because that could take a very long while to reach completion (could be more than a billion iterations)
If what you're really looking for is a function to find the next number that has all digits, starting from n, iterating sequentially through all possible numbers will take much too long.
You would need to replace the smallest number of trailing digits with the missing digits while ensuring that the resulting number will be larger. For this, the leftmost digit that you replace has to get a larger one and the rest only needs to be in increasing order (filling with extra zeros as needed):
For example:
def nextAllDigits(n):
if n<=1023456789: return 1023456789 # n < 1st ==> 1st with all 10
digits = str(n) # digits as string
missing = set("0123456789")-set(digits) # missing digits
if not missing: return n # none missing, n is good
digits = "0"+digits # room for an extra 1
for i,d in enumerate(digits[::-1],1): # backward through digits
if d not in digits[1:-i]: # d will be replaced
missing.add(d) # and will be missing
if i>len(missing) and d<'9' \
or i==len(missing) and d<max(missing): # enough room and can increase
if i>len(missing):
missing.add(str(int(d)+1)) # use d+1 if extra room
m = min(m for m in missing if m>d) # replacement for d (greater)
missing.discard(m) # no longer missing
zeroFill = "0"*(i-len(missing)-1) # zeros in extra space
return int(digits[:-i]+m+zeroFill+"".join(sorted(missing)))
print(nextAllDigits(9980659999)) # 10023456789
print(nextAllDigits(12345687989)) # 12345687990
Question:
Without using any string methods, try to print the following:
123...n
Note that "..." represents the consecutive values in between.
Example
n=5
Prints 12345.
my solution
n = int(input())
sum=0
i=n
while i>0:
sum=sum + i*(10**{n-i})
i -= 1
print(sum)
First: {n-i} will evaluate to {-1} if n=0 since {x} is way to express a set in python
Second: you're asking for method to print numeric string, but no string operation (so all concatenation should be done in addition between two integers). Here I'm assuming that the accepted input can only be positive number
e.g.:
input 5, output=12345
input 12, output=123456789101112
When learning to solve such 'challenge' problem, it's better to do it test driven: write a simple program that just work, then compare/assert with generated expected result
this is the correct but not acceptable way to generate the output (with string operation):
inp = int(input())
expected = ""
for i in range(1, inp+1):
expected = expected + str(i)
print(expected)
Then try to solve it gradually: assume single digit input only. Here we got the idea that in order to place a number beside other number, we need to multiply first number by 10, then next number by 1. So your solution for making it multiplied by power of ten is already on correct track
now we can write:
inp = int(input())
result = 0
for i in range(1, inp+1):
power_of_ten = 10**(inp-i)
print("pot", power_of_ten)
result = result + (i*power_of_ten)
print("r", result)
print(result)
output:
5
pot 10000
r 10000
pot 1000
r 12000
pot 100
r 12300
pot 10
r 12340
pot 1
r 12345
12345
at this point, we can try to assert if our output is the same with our generated output (the one that use string operation):
inp = int(input())
result = 0
for i in range(1, inp+1):
power_of_ten = 10**(inp-i)
result = result + (i*power_of_ten)
print(result)
expected = ""
for i in range(1, inp+1):
expected = expected + str(i)
print(expected)
assert(result == int(expected))
print("assertion passed")
output:
5
12345
12345
assertion passed
but if we use two digit input, the output will no longer be correct:
12
123456790122
123456789101112
Traceback (most recent call last):
File "/tmp/c.py", line 14, in <module>
assert(result == int(expected))
AssertionError
so, if we have to output 123456789101112 when we input 12, then we need a mathematical function (not a string function) that can count the number of digit in a number:
output 2 if we input 12, 40, 99, 80 (two digit number)
output 1 if we input 1, 5, 2 (one digit number)
etc.
such function is called logarithm function: e.g.:
math.floor(math.log(i, 10)) + 1
first we try to logarithm the input to base 10, then we floor the result (so that the result is not a decimal/fractional number); then we add 1
here is the code that incorporate that: note that for simplicity, we're looping backward (e.g.: 12,11,10,9..1)
import math
inp = int(input())
result = 0
pad = 0
for i in range(inp, 0, -1):
result = result + i*10**pad
pad = pad + math.floor(math.log(i, 10)) + 1
print(result)
expected = ""
for i in range(1, inp+1):
expected = expected + str(i)
print(expected)
assert(result == int(expected))
print("assertion passed")
here I added a variable pad that will contain the number of pad to be added on next iteration, e.g.: input=5
iteration=1 i=5 pad=1 result=5 (so next number, i.e: 4, will be multiplied with 10^1)
iteration=2 i=4 pad=2 result=45 (so next number, i.e: 3, will be multiplied with 10^2)
iteration=3 i=3 pad=3 result=345
iteration=4 i=2 pad=4 result=2345
iteration=5 i=1 pad=5 result=12345
when input=12
iteration=1 i=12 pad=2 result=12
iteration=2 i=11 pad=4 result=1112
iteration=3 i=10 pad=6 result=101112
iteration=4 i=9 pad=7 result=9101112
iteration=5 i=8 pad=8 result=89101112
iteration=6 i=7 pad=9 result=789101112
iteration=7 i=6 pad=10 result=6789101112
iteration=8 i=5 pad=11 result=56789101112
iteration=9 i=4 pad=12 result=456789101112
iteration=10 i=3 pad=13 result=3456789101112
iteration=11 i=2 pad=14 result=23456789101112
iteration=12 i=1 pad=15 result=123456789101112
output:
$ python3 /tmp/a.py
5
12345
12345
assertion passed
$ python3 /tmp/a.py
12
123456789101112
123456789101112
assertion passed
so the final code is:
import math
inp = int(input())
result = 0
pad = 0
for i in range(inp, 0, -1):
result = result + i*10**pad
pad = pad + math.floor(math.log(i, 10)) + 1
print(result)
I have a 2-D 6x6 array, A.
I want its values to be input by the user in the following format or example:
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
where the 0's indicate the places where the user would write their values.
This is my code. It returns an error in split().
def arr_input(x):
for i in range(6):
for j in range(6):
n = int(input().split(' '))
if n>=-9 and n<=9:
x[i][j] = n
print "\n"
I don't want input in a single line. Please help!
EDIT 1
The code I needed was already provided :D. Nevertheless, I learned something new and helpful. Here is the existing code to do the task I wanted:
arr = []
for arr_i in xrange(6):
arr_temp = map(int,raw_input().strip().split(' '))
arr.append(arr_temp)
First of all, you are using input() which returns int when you enter numbers in terminal. You should use raw_input() and get it line by line.
Second, you are trying to convert a list to integer, you should loop through the list values, convert and insert on the resulting list.
Fixed code:
def arr_input(x):
for i in range(6):
num_list = raw_input().split(' ')
for j, str_num in enumerate(num_list):
n = int(str_num)
if n >= -9 and n <= 9:
x[i][j] = n
print "\n"
Here, I used enumerate() to loop though the number list by getting its index each iteration.
There's an inconsistency in how you're treating the input. In python 2.7, the input() function is designed to read one, and only one, argument from stdin.
I'm not exactly sure which way you're trying to read the input in. The nested for loop suggests that you're trying to read the values in one by one, but the split suggests that you're doing it line by line. To cover all bases, I'll explain both cases. At least one of them will be relevant.
Case 1:
Let's say you've been inputting the values one by one, i.e.
1
4
9
4
...
In this case, what's happening is that the input() function is automatically parsing the inputs as integers, and when you try running split() on an integer there's a type error. Python is expecting a string and you're providing an int. That's going to break. There's an easy solution--this can be fixed by simply replacing that line with
n = input()
Case 2: Let's say you're inputing the numbers line by line, as strings. By this, I mean something like:
"1 3 4 5 7 9"
"4 1 8 2 5 1"
...
What's occurring here is that int(...) is trying to cast a list of strings into an integer. That will clearly break the code. A possible solution would be to restructure the code by gett rid of the inner for loop. Something like this should work:
def arr_input(arr):
for i in range(6):
s = input()
nums_s = s.split(' ')
nums = [int(x) for x in nums_s]
arr.append(nums)
print "\n"
return arr
# Usage
a = []
print(a)
a = arr_input(a)
print(a)
Give this one-liner a try:
def arr_input(N=6):
print 'Enter %d by %d array, one row per line (elements separated by blanks)' % (N, N)
return [[n if abs(n)<=9 else 0 for n in map(int, raw_input().split())] for i in range(N)]
The following interactive session demonstrates its usage:
>>> A = arr_input(3)
Enter 3 by 3 array, one row per line (elements separated by blanks)
1 2 -3
4 5 -6
8 9 10
>>> A
[[1, 2, -3], [4, 5, -6], [8, 9, 0]]
I'm trying to print the sum of a list generated through raw_input.
The numbers in the list must be between 1 and 1000, inclusive. The length of the list must be below 1000.
here is my code thus far:
initial_list = raw_input()
integer= initial_list.split(' ')
if len(integer) <= 1000:
for i in integer:
if i >= 1 and i<=1000:
actual_integer = map( int, integer)
print sum(actual_integer)
This does not print anything. Any suggestions and/or alternatives?
If I understand your objective correctly, you've got all the right ideas, you just need to re-order your logic a little and make sure you are clear in your head about when you're dealing with a list of values and when you're dealing with a single value.
You may wish to consider your variable naming, too, as good names can help you keep track of whether the variable has a type with multiple values or single values. I've updated your code with that in mind
initial_list = raw_input().split() # split(' ') works, but you don't actually need the ' ',
# split() on its own does the same job here
if len(initial_list) <= 1000:
actual_integers = map(int, initial_list) #Moved to here. Note that
#actual_integers is a list
#so for the following comparison
#you just want to look at the max
#and min (individual values)
if min(actual_integers) >= 1 and max(actual_integers) <= 1000:
print sum(actual_integers)
else: #Just added two nice messages to the user if it doesn't print out.
print 'integers must be in range 1-1000 inclusive'
else:
print 'your list must have 1000 integers or fewer'
This code here does what you need but there is no error checking.
initial_list = raw_input() # there should be some prompt text
# no error checking
integer = initial_list.split(' ')
# no output for lists > 1000
if len(integer) <= 1000:
print sum(filter(lambda i: 0 < i <= 1000, map(int, integer)))
The output
$ python test.py
1 2 3 1500 0
6
If I understand your question correctly, this maybe what you're looking for.
This code will prompt the input and append the input to the list lst until lst will have 1000 elements. It will only take an input if the input is a number between 1 and 1000 and it will give you the sum after every input.
lst = []
while len(lst) <= 999:
initial_list = raw_input('Input numbers between 1 and 1000:')
if initial_list.isdigit() and int(initial_list) <= 1000 and int(initial_list) >= 1:
lst.append(int(initial_list))
print 'List:', lst #prints the list
total = sum(lst)
print 'List Sum:', total #prints the list sum
else:
print 'Input must be numbers between 1 and 1000'
Output:
Input numbers between 1 and 1000:12
List: [12]
List Sum: 12
Input numbers between 1 and 1000:45
List: [12, 45]
List Sum: 57
Input numbers between 1 and 1000:156
List: [12, 45, 156]
List Sum: 213
Input numbers between 1 and 1000:256
List: [12, 45, 156, 256]
List Sum: 469
Input numbers between 1 and 1000: