123 to 321 problem giving errors when iterating - python

I made this program trying to solve a problem which is fliping a number. For example, when the number 123 is the number inputed the number 321 should be the output.
#function to swap number positions on the array
def swapPositions(list, pos1, pos2):
i = list[pos1]
list[pos1] = list[pos2]
list[pos2] = i
myList = []
theNum = int(input("enter the value"))
theNumInString = str(theNum)
#loop to separate numbers on the integer into each position of the array
for char in theNum2:
myList.append(char)
#this variable is to know how many times we should swap the positions
numofSwaps = len(myList) % 2
posi1 = 0
posi2 = len(myList) - 1
while numofSwaps != 0:
swapPositions(myList, posi1, posi2)
#I add one and subtract one from the positions so they move further to the middle to swap other positions
posi1 += 1
posi2 -= 1
numofSwaps -= 1
number = "".join(myList)
print(number)
what happens when I run the code and try for example 123 it returns 321 as expected
BUT here comes the problem... when I input 12345 the output is 52341 which only swaps the outer two numbers.

this can be done without converting the number to a string, for example
# note: this example works for positive numbers only
def reverseNum(x):
y = 0
while x > 0:
y = y*10 + x%10
x //= 10
return y
>>> reverseNum(3124)
4213

Related

sum of every other digit and doubling the rest

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)

Count the dice throws to get to file 5 100 times(board is 0-5)

I'm trying to find out how many times you have to throw the dice to get on file 5 100 times(board is played from 0 to 5). This is how I tried(I know the answer is 690 but I don't know what I'm doing wrong).
from random import *
seed(8)
five = 0
count = 0
add = 0
while five < 100:
count = count + 1
print(randint(1,6))
add = add + randint(1,6)
if add % 5 == 0 :
five = five + 1
else: add = add + randint(1,6)
print(count)
This is the code I think you were trying to write. This does average about 600. Is it possible your "answer" came from Python 2? The random seed algorithm is quite likely different.
from random import *
seed(8)
five = 0
count = 0
add = 0
while five < 100:
count += 1
r = randint(0,5)
if r == 5:
five += 1
else:
add += r
print(count, add)
You're adding a second dice throw every time you don't get on 5, this makes the probability distribution irregular (i.e. advancing by 7 will be more probable (1/6) than any other value, e.g. 1/9 for 5) so your result will not be the same as counting single throws.
BTW there is no fixed result for this, just a higher probability around a given number of throws. However, given that you seeded the random number generator with a constant, every run should give the same result. And it should be the right one if you don't double throw the dice.
Here is an example of the process that arrives at 690:
import random
random.seed(8)
fiveCount = 0
throwCount = 0
position = 0
while fiveCount < 100:
position = (position + random.randint(1,6)) % 6
throwCount += 1
fiveCount += position == 5
print(throwCount) # 690
Other observations:
Updating the position wraps around using modulo 6 (there are 6 positions from 0 to 5 inclusively)
Your check of add%5 == 0 does not reflect this. It should have been add%6 == 5 instead but it is always preferable to model the computation as close as possible to the real world process (so keep the position in the 0...5 range)

How do I get the shortest repitition of something in an array?

Let's say you have a list which only has two types of values and goes something like ['t','r','r','r','t','t','r','r','t'] and you want to find the length of the smallest sequence number of 'r's which have 't's at both ends.
In this case the smallest sequence of 'r' has a length of 2, because there is first t,r,r,r,t and then t,r,r,t, and the latter has the smallest number of 'r's in a row surrounded by 't' and the number of 'r's is 2.
How would I code for finding that number?
This is from a problem of trying of going to a play with your friend, and you want to sit as close as possible with your friend, so you are trying to find the smallest amount of taken seats in between two free seats at a play. "#" is a taken seat and a "." is a free seat. you are given the amount of seats, and the seating arrangement (free seats and taken seats), and they are all in one line.
An example of an input is:
5
#.##.
where there are two taken seats(##) in between two free seats.
Here is my code which is not working for inputs that I don't know, but working for inputs I throw at it.
import sys
seats = int(input())
configuration = input()
seatsArray = []
betweenSeats = 1
betweenSeatsMin = 1
checked = 0
theArray = []
dotCount = 0
for i in configuration:
seatsArray.append(i)
for i in range(len(seatsArray)):
if i == len(seatsArray) - 1:
break
if seatsArray[i] == "." and seatsArray[i+1] == ".":
print(0)
sys.exit()
for i in range(0,len(seatsArray)):
if i > 0:
if checked == seats:
break
checked += 1
if seatsArray[i] == "#":
if i > 0:
if seatsArray[i-1] == "#":
betweenSeats += 1
if seatsArray[i] == ".":
dotCount += 1
if dotCount > 1:
theArray.append(betweenSeats)
betweenSeats = 1
theArray = sorted(theArray)
if theArray.count(1) > 0:
theArray.remove(1)
theArray = list(dict.fromkeys(theArray))
print(theArray[0])
This is a noob and a !optimal approach to your problem using a counter for the minimum and maximum sequence where ew compare both and return the minimum.
''' create a funciton that
will find min sequence
of target char
in a list'''
def finder(a, target):
max_counter = 0
min_counter = 0
''' iterate through our list
and if the element is the target
increase our max counter by 1
'''
for i in x:
if i == target:
max_counter += 1
'''min here is 0
so it will always be less
so we overwrite it's value
with the value of max_counter'''
if min_counter < max_counter:
min_counter = max_counter
'''at last iteration max counter will be less than min counter
so we overwrite it'''
if max_counter < min_counter:
min_counter = max_counter
else:
max_counter = 0
return min_counter
x = ['t','r','r','r','t','t','r','r','t','t','t','r','t']
y = 'r'
print(finder(x,y))
Create a string from list and then search for pattern required and then count r in the found matches and then take min of it
Code:
import re
lst = ['t','r','r','r','t','t','r','r','t']
text = ''.join(lst)
pattern = '(?<=t)r+(?=t)'
smallest_r_seq = min(match.group().count('r') for match in re.finditer(pattern, text))
print(smallest_r_seq)
Output:
2

running a program over x amount of times

I'm trying to write a function that calls a function (roll die() which rolls a die 1000 times and counts on a list [1,2,3,4,5,6] so an outcome might be [100,200,100,300,200,100]) and tells it to run it x amount of times. It seems my code is printing it over and over again x times
#simulate rolling a six-sided die multiple tiems, and tabulate the results using a list
import random #import from the library random so you can generate a random int
def rollDie():
#have 6 variables and set the counter that equals 0
one = 0
two = 0
three = 0
four = 0
five = 0
six = 0
#use a for loop to code how many times you want it to run
for i in range(0,1000):
#generate a random integer between 1 and 6
flip = int(random.randint(1,6))
# the flip variable is the the number you rolled each time
#Every number has its own counter
#if the flip is equal to the corresponding number, add one
if flip == 1:
one = one + 1
elif flip == 2:
two = two + 1
elif flip == 3:
three = three + 1
elif flip == 4:
four = four + 1
elif flip == 5:
five = five + 1
elif flip == 6:
six = six + 1
#return the new variables as a list
return [one,two,three,four,five,six]
the new function that I am having problems with is:
def simulateRolls(value):
multipleGames = rollDie() * value
return multipleGames
I would like to see a result like this if you typed in 4 for value
[100,300,200,100,100,200]
[200,300,200,100,100,100]
[100,100,100,300,200,200]
[100,100,200,300,200,100]
Can someone guide me in the right direction?
You can get what you want like this:
def simulateRolls(value):
multipleGames = [rollDie() for _ in range(value)]
return multipleGames
By the way, your original function seems to work perfectly fine, but if you're interested, you can remove some redundancy like this:
def rollDie():
#have 6 variables and set the counter that equals 0
results = [0] * 6
#use a for loop to code how many times you want it to run
for i in range(0,1000):
#generate a random integer between 1 and 6
flip = int(random.randint(1,6))
# the flip variable is the the number you rolled each time
results[flip - 1] += 1
return results
The line
multipleGames = rollDie() * value
will evaluate rollDie() once and multiply the result by value.
To instead repeat the call value times do this.
return [rollDie() for i in xrange(value)]
You can also simplify your rollDie function by working with a list throughout
import random #import from the library random so you can generate a random int
def rollDie():
result = [0] * 6
for i in range(0,1000):
result[random.randint(0,5)] += 1
return result

python - print squares of numbers which are palindromes : improve efficiency

I have an assignment to do. The problem is something like this. You give a number, say x. The program calculates the square of the numbers starting from 1 and prints it only if it's a palindrome. The program continues to print such numbers till it reaches the number x provided by you.
I have solved the problem. It works fine for uptil x = 10000000. Works fine as in executes in a reasonable amount of time. I want to improve upon the efficiency of my code. I am open to changing the entire code, if required. My aim is to make a program that could execute 10^20 within around 5 mins.
limit = int(input("Enter a number"))
def palindrome(limit):
count = 1
base = 1
while count < limit:
base = base * base #square the number
base = list(str(base)) #convert the number into a list of strings
rbase = base[:] #make a copy of the number
rbase.reverse() #reverse this copy
if len(base) > 1:
i = 0
flag = 1
while i < len(base) and flag == 1:
if base[i] == rbase[i]: #compare the values at the indices
flag = 1
else:
flag = 0
i += 1
if flag == 1:
print(''.join(base)) #print if values match
base = ''.join(base)
base = int(base)
base = count + 1
count = count + 1
palindrome(limit)
He're my version:
import sys
def palindrome(limit):
for i in range(limit):
istring = str(i*i)
if istring == istring[::-1]:
print(istring,end=" ")
print()
palindrome(int(sys.argv[1]))
Timings for your version on my machine:
pu#pumbair: ~/Projects/Stackexchange time python3 palin1.py 100000
121 484 676 10201 12321 14641 40804 44944 69696 94249 698896 1002001 1234321
4008004 5221225 6948496 100020001 102030201 104060401 121242121 123454321 125686521
400080004 404090404 522808225 617323716 942060249
real 0m0.457s
user 0m0.437s
sys 0m0.012s
and for mine:
pu#pumbair: ~/Projects/Stackexchange time python3 palin2.py 100000
0 1 4 9
121 484 676 10201 12321 14641 40804 44944 69696 94249 698896 1002001 1234321
4008004 5221225 6948496 100020001 102030201 104060401 121242121 123454321 125686521
400080004 404090404 522808225 617323716 942060249
real 0m0.122s
user 0m0.104s
sys 0m0.010s
BTW, my version gives more results (0, 1, 4, 9).
Surely something like this will perform better (avoiding the unnecessary extra list operations) and is more readable:
def palindrome(limit):
base = 1
while base < limit:
squared = str(base * base)
reversed = squared[::-1]
if squared == reversed:
print(squared)
base += 1
limit = int(input("Enter a number: "))
palindrome(limit)
I think we can do it a little bit easier.
def palindrome(limit):
count = 1
while count < limit:
base = count * count # square the number
base = str(base) # convert the number into a string
rbase = base[::-1] # make a reverse of the string
if base == rbase:
print(base) #print if values match
count += 1
limit = int(input("Enter a number: "))
palindrome(limit)
String into number and number into string conversions were unnecessary. Strings can be compared, this is why you shouldn't make a loop.
You can keep a list of square palindromes upto a certain limit(say L) in memory.If the Input number x is less than sqrt(L) ,you can simply iterate over the list of palindromes and print them.This way you wont have to iterate over every number and check if its square is palindrome .
You can find a list of square palindromes here : http://www.fengyuan.com/palindrome.html
OK, here's my program. It caches valid suffixes for squares (i.e. the values of n^2 mod 10^k for a fixed k), and then searches for squares which have both that suffix and start with the suffix reversed. This program is very fast: in 24 seconds, it lists all the palindromic squares up to 10^24.
from collections import defaultdict
# algorithm will print palindromic squares x**2 up to x = 10**n.
# efficiency is O(max(10**k, n*10**(n-k)))
n = 16
k = 6
cache = defaultdict(list)
print 0, 0 # special case
# Calculate everything up to 10**k; these will be the prefix/suffix pairs we use later
tail = 10**k
for i in xrange(tail):
if i % 10 == 0: # can't end with 0 and still be a palindrome
continue
sq = i*i
s = str(sq)
if s == s[::-1]:
print i, s
prefix = int(str(sq % tail).zfill(k)[::-1])
cache[prefix].append(i)
prefixes = sorted(cache)
# Loop through the rest, but only consider matching prefix/suffix pairs
for l in xrange(k*2+1, n*2+1):
for p in prefixes:
low = (p * 10**(l-k))**.5
high = ((p+1) * 10**(l-k))**.5
low = int(low / tail) * tail
high = (int(high / tail) + 1) * tail
for n in xrange(low, high, tail):
for suf in cache[p]:
x = n + suf
s = str(x*x)
if s == s[::-1]:
print x, s
Sample output:
0 0
1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
<snip>
111010010111 12323222344844322232321
111100001111 12343210246864201234321
111283619361 12384043938083934048321
112247658961 12599536942224963599521
128817084669 16593841302620314839561
200000000002 40000000000800000000004

Categories

Resources