loop finding "bouncy" numbers - python

Consider the following definitions of positive numbers:
A number is nondecreasing if its digits never get smaller as you go from left to right. For example, 12345
and 3388 are nondecreasing.
A number is nonincreasing if its digits never larger as you go from left to right. For example, 987542 and
881 are nonincreasing.
A number is bouncy if it is neither nondecreasing nor nonincreasing. For example, 12134 and 98462 are
bouncy.
Write a Python function bouncy that consumes a positive natural number (called n) and produces the
percentage of numbers between 1 and n, inclusive, which are bouncy. The result should be produced as a
natural number between 0 and 100, inclusive. Use round to convert the floating point percentage to an
integer.
def bouncy(input):
list1 = [0 for i in range(input)]
list1[0] = 0
for x in range(1, input-1):
if x < 100:
list1[x] = list1[x - 1]
else:
n=x
a = [0 for i in range(x)]
i = 0
while n > 0:
a[i]=n % 10
n/= 10
i+=1
flag = 1
for k in range(1, len(a) - 2):
if not ((a[k - 1] < a[k] < a[k + 1]) or (a[k - 1] > a[k] > a[k + 1])):
flag = 0
break
if flag == 0:
list1[x]==list[x-1]+ 1
return list1[input-1]
when i ran my code, it displays builtins.IndexError: list assignment index out of range.
Anyone got an idea?

You don't have to do any of that. Just turn the number into a string. If it's sorted it's nondecreasing, if it's reverse sorted it's nonincreasing, otherwise it's bouncy.
def bouncy(n):
return round(sum(list(i) not in (sorted(i), sorted(i, reverse=True)) for i in map(str, range(1, n+1)))/n*100)
This map()s each number in the range to a string, then checks whether a list() of that string is not found in a sorted() version of that string (either increasing or decreasing). Then it adds together how many numbers match that, divides by n, multiplies by 100, round()s that, and returns it.

Related

Reversing an integer using recursion in Python

While practicing recursion I came across a question to reverse an integer using recursion. I tried to do the question without converting the integer into a string.
I was able to solve the question partially but the output would always come without any of the zeroes from the original input. Below is the code I came up with:
def reverseNumber(n):
if (n//10) == 0:
return n
lastDigit = n%10
ans = reverseNumber(n//10)
nod = 0
for i in str(ans):
nod += 1
return (10**nod)*lastDigit + ans
Upon inspection I could see that this was happening because when lastDigit is 0 it only returned the reversed integer from the recursive call i.e input 4230 will give 324.
But this also meant that all zeroes between the original input would also get removed as we went deeper in the recursive calls.
So please tell me how to modify this code so that zeroes in the original input are not removed while reversing.
You probably need just this:
def rev(n):
if n>0:
return str(n%10)+rev(n//10)
else:
return ''
reverseNumber should return an int and accept positive and negative numbers.
The simplest way to fix your code, without handling negative numbers, is:
def reverseNumber(n):
if n == 0:
return 0
lastDigit = n%10
n //= 10
return int(str(lastDigit) + str(reverseNumber(n))) if n else lastDigit
for test in (0, 123, 120):
print(test, reverseNumber(test))
Prints:
0 0
123 321
120 21
Yes! The reverse of 120 is 21 when you are dealing with int types as opposed to str types.
Another implementation that does handle negative numbers takes a whole different approach:
I have broken this out into two functions. Function rev is a generator function that assumes that it is being called with a positive, non-negative number and will recursively yield successive digits of the number in reverse. reverseNumber will join these numbers, convert to an int, adjust the sign and return the final result.
def reverseNumber(n):
def rev(n):
assert n >= 0
yield str(n % 10)
n //= 10
if n != 0:
yield from rev(n)
if n == 0: return 0 # special case
x = int(''.join(rev(abs(n))))
return x if n >= 0 else -x
tests = [0, 132, -132, 120]
for test in tests:
print(test, reverseNumber(test))
Prints:
0 0
132 231
-132 -231
120 21
For all non-negative n, when n < 10 it is a single digit and already the same as its reverse -
def reverse(n = 0):
if n < 10:
return str(n)
else
return str(n%10) + rev(n//10)
you can also try the following Python3 code. It will cover positive and negative integers to be reversed as integers - not as strings ...
x = int(input("What integer shall be reversed? "))
n = abs(x) # ... to handle negative integers
r = 0 # ... will hold the reversed int.
while n > 0: # Recursion part reversing int.
r = (r * 10) + (n % 10) # using '%' modulo
n = int(n / 10) # and a 'dirty way' to floor
if x < 0: # Turn result neg. if x was neg.
return (r * -1)
else:
return r # Keep result pos. if x was pos.
This approach will leave your zeros in the middle of the integer intact, though it will make any zero at the end of the initial number vanish - rightfully so as integers do not start with a zero. ;))

Python if problem with analyzing numbers if number before is positive or negative?

so my goal is to make program that scans numbers and if number before zero is negative and number after zero is positive it prints "Zero is positive" and if opposite "Zero is negative". Problem is that every time i enter numbers it always prints only "Zero is negative" for now program should only work with 1 zero and 2 numbers but i will later expend. Here is my code:
number = input("Enter Numbers: ")
lists = []
lists = number.split()
print(lists)
z = 0
y = 0
x = 0
indexes = [index for index, element in enumerate(lists) if element == "0"]
print(indexes)
pos = indexes[0] - 1
neg = indexes[0] + 1
zero = indexes[0]
if(int(neg) < zero and zero > int(pos)):
print("Zero is postive")
else:
print("Zero is negative")
As already been told, you should compare the values in the list not the index numbers.
Also, there is a logical error in this statement if(int(neg) < zero and zero > int(pos)):, it actually checks if both neg and both are less that zero.
And perhaps is more clear if neg points the previous to zero value and pos the next one.
I modified a bit your code and I think it works correctly:
number = input("Enter Numbers: ")
lists = []
lists = number.split()
print(lists)
z = 0
y = 0
x = 0
indexes = [index for index, element in enumerate(lists) if element == "0"]
print(indexes)
neg = int(indexes[0] - 1)
pos = int(indexes[0] + 1)
zero = int(indexes[0])
if lists[neg] < lists[zero] < lists[pos]:
print("Zero is postive")
else:
print("Zero is negative")
If I'm understanding the problem statement correctly, you need to compare the list elements at the indexes but are comparing the indexes. So the condition in if should be changed from:
if(int(neg) < zero and zero > int(pos)):
to something like this (note that you don't need braces in python's if):
if list[neg] > list[zero] > list[pos]:

counting sort - negative integers

I'm trying to do a counting_sort on negative numbers, the following code only seems to work on positive integers. Any pointers on how I can fix it to work on negative numbers?
def count_sort(l):
output = [0] * len(l)
low = min(l)
if low >= 0:
low = 0
high = max(l)
working = [0 for i in range(low, high+1)]
for i in l:
workng[i] += 1
for j in range(1, len(working)):
working[j] += working[j-1]
for k in reversed(ul):
output[working[k] - 1] = k
working[k] -= 1
return output
Counting sort can work for any bounded range of integers, they don't all need to be positive. To make your code work for negative values (and work without wasting lots of memory for positive values that are all far from zero, e.g. [1e10, 1e10+1, 1e10+2]), just offset your indexes into count_array by the minimum value in the input:
def counting_sort(unsorted):
result = [0] * len(unsorted)
low = min(unsorted) # we don't care if this is positive or negative any more!
high = max(unsorted)
count_array = [0 for i in range(low, high+1)]
for i in unsorted:
count_array[i-low] += 1 # use an offset index
for j in range(1, len(count_array)):
count_array[j] += count_array[j-1]
for k in reversed(unsorted):
result[count_array[k-low] - 1] = k # here too
count_array[k-low] -= 1 # and here
return result
When you index count_array with negative elements, your algorithm doesn't work. Python will interpret count_array[-1] as the last element of count_array
So you can either change the code to take that into account or shift all elements before sorting
unsorted = [e - low for e in unsorted]
and at the end change it back
result = [e + low for e in result]

Why are these lines of code in python only outputting the same answer?

I'm trying to get this program to return all possible multiples of 3 and 5 below 1001 and then add them all together and print it but for some reason these lines of code only seem to be printing one number and that number is the number 2 which is obviously wrong. Can someone point me in the right direction to why this code is grossly wrong?
n = 0
x = n<1001
while (n < 1001):
s = x%3 + x%5
print s
You've got a few mistakes:
x is a boolean type
Your loop never ends
adding values to mimic lists?
Edit
Didn't see the part where you wanted sum, so you could employ a for-in loop or just a simple one like so:
sum = 0
for i in range(1001):
if(i % 3 == 0 or i % 5):
sum += i
print(sum)
(Python 3)
You need to stop while at some point by incrementing n. Here is some code:
nums = []
n = 0
while (n < 1001):
# in here you check for the multiples
# then append using nums.append()
n += 1
This creates a loop and a list that accounts for every number in 0 to 1000. In the body, check for either condition and append to the list, then print out the values in the list.
num is a list where you are going to store all the values that apply, (those numbers who are divisible by 3 and 5, which you calculate with modulo). You append to that list when a condition is met. Here is some code:
nums = []
n = 0
while (n < 1001):
if(n % 3 == 0 or n % 5 ==0):
nums.append(n)
n += 1
print(n) #or for loop for each value
Explanation: a list of numbers called num stores the numbers that are divisible by 3 or 5. The loop starts at zero and goes to 1000, and for all the values that are divisible by 3 or 5, they will be added to the list. Then it prints the list.
Of course there is a simpler approach with a range:
for i in range(1001):
if(i % 3 == 0 or i % 5 == 0):
print(i)
This will print out all the values one by one. It is 1001 because the upper limit is exclusive.
true=1
false=0
so:
x = n<1001
we have x=1 because 0<1001 is true
s = x%3 + x%5
the remainder of 1/3 is 1 and 1/5 is 1
In your code:
1. x=n<1001 - generates a boolean value; on which we can't perform a mathematical operation.
In while loop:
your variable n,x are not changing; they are constant to same value for all the iterations.
Solution 1:
Below code will help you out.
s=0
for i in range(1,1002):
if( i%3 == 0 or i%5 == 0):
s = s + i
print(s)
Solution: 2
There is one more approach you can use.
var = [i for i in range(1,1002) if i%3==0 or i%5 ==0]
print(sum(var))

Finding minimal value with condition python

a = []
for i in range(3):
a.append(input())
j = 0
for i in a:
if i % 10 != 7:
j = min(a)
print j
I need an algorithm which finds the smallest positive number in list, which decimal representation does not end with the number 7. It is guaranteed that the list has at least one positive element, which decimal representation does not end with the number 7. I tried this, but condition doesn't work. For example: it says that 7 is smallest in [9,8,7].
You are always testing for the minimum number in a, albeit as many times as there are unfiltered numbers in a. Don't add numbers that end in 7 to a in the first place; you probably want to filter on positive numbers too:
a = []
for i in range(3):
value = input()
if i % 10 != 7 and i >= 0:
a.append(value)
print min(a)
Alternatively, filter out values in a generator expression:
a = []
for i in range(3):
a.append(input())
print min(i for i in a if i % 10 != 7 and i >= 0)
EDIT:
Ok I misreaded your code, you were using remainder which i think is better. Although it could work using just plain divisions like this.
if ((i / 10) - int(i / 10)) * 10 != 7:
And also, if you aren't using Python 3, you might need to use this for the above to work:
from __future__ import division
Or casting to floats with float(), but that makes it too messy.

Categories

Resources