Is there a way to make this code more "Neat"? - python

The user inserts multiple values and the program determines how many positive values, negative values, zero values, even values, odd values, and the min, max, average, and total of those values. The code works, however it's quite messy.
negative=0
zero=0
positive=0
even=0
odd=0
max=0
min=0
a=int(input('Number of values:'))
b=int(input('First value:'))
if b==0:
zero=1
if b<0:
negative=1
if b>0:
positive=1
if b%2==0:
even=1
else:
odd=1
if b>max:
max=b
total=b
for x in range(a-1):
b=int(input('Next value:'))
total+=b
if b==0:
zero+=1
if b==0:
zero+=1
if b<0:
negative+=1
if b>0:
positive+=1
if b%2==0:
even+=1
else:
odd+=1
if b>max:
max=b
if b<max:
min=b
print('Negative values:',negative)
print('Zero values:',zero)
print('Positive values:',positive)
print('Even values:',even)
print('Odd values:',odd)
print('Total:',total)
print('Minimum:',min)
print('Maximum:',max)
print('Average:',total/a)

There's two parts of the script essentially doing the same thing, except that you're asking the user "First Value" instead of "Next value". So I would just merge them together in a loop and determine what msg to use.
There's also a lack of white space everywhere which makes it harder to read. Check out Python's PEP 8 guide to standard conventions.
You can also use more descriptive variable names so it's more readable at a glance.
Also be careful naming your variables min and max. Those are already built-in methods in Python that you're overriding.
negative = 0
zero = 0
positive = 0
even = 0
odd = 0
maxVal = 0
minVal = 0
total = 0
count = int(input('Number of values:'))
for i in range(count):
if i == 0:
msg = 'First value:'
else:
msg = 'Next value:'
val = int(input(msg))
total += val
if val == 0:
zero += 1
if val < 0:
negative += 1
if val > 0:
positive += 1
if val % 2 == 0:
even += 1
else:
odd += 1
if val > maxVal:
maxVal = b
if val <= minVal <= val and val < maxVal:
minVal = val
print('Negative values:', negative)
print('Zero values:', zero)
print('Positive values:', positive)
print('Even values:', even)
print('Odd values:', odd)
print('Total:', total)
print('Minimum:', minVal)
print('Maximum:', maxVal)
print('Average:', total / count)

I made a rendition of your code that in my mind is neater, this way you aren't just storing values you have a Counter that remembers all the values put in and the number of times they were used. Also fixed your whitespace and times_to_run is more descriptive than a and value is more descriptive than b. I also just used the iteration number you're on as the n'th number being input
from collections import Counter
total = 0
all_numbers = Counter()
times_to_run = int(input('Number of values: '))
for x in range(times_to_run):
value = int(input(f'Value {x + 1}: '))
total += value
all_numbers[value] += 1
negative = sum(all_numbers[n] for n in all_numbers if n < 0)
zero = all_numbers[0]
positive = sum(all_numbers[n] for n in all_numbers if n > 0)
even = sum(all_numbers[n] for n in all_numbers if abs(n) % 2)
odd = sum(all_numbers[n] for n in all_numbers if not abs(n) % 2)
max = max(all_numbers)
min = min(all_numbers)
print()
print('Negative values:',negative)
print('Zero values:',zero)
print('Positive values:',positive)
print('Even values:',even)
print('Odd values:',odd)
print('Total:',total)
print('Minimum:',min)
print('Maximum:',max)
print('Average:',total / times_to_run)
To test:
Number of values: 10
Value 1: -1
Value 2: -1
Value 3: 5
Value 4: 2
Value 5: 0
Value 6: 3
Value 7: 55
Value 8: 8
Value 9: 10
Value 10 :4
Negative values: 2
Zero values: 1
Positive values: 7
Even values: 5
Odd values: 5
Total: 85
Minimum: -1
Maximum: 55
Average: 8.5

Related

Count how many times can a number be divided by 2

n = int(input())
counter = 0
while n > 0:
if (n // 2) > 1:
counter = counter +1
print (counter)
Hi,
I am a python learner and I am having problems with this homework I was given.
Read a natural number from the input.
Find out how many times in a row this number can be divided by two
(e.g. 80 -> 40 -> 20 -> 10 -> 5, the answer is 4 times)
And I should use while loop to do it.
Any Ideas, because I really don't have any idea how to do it.
This is my best try
You are not changing n. I would write it like this:
while (n % 2) == 0:
n //= 2
counter += 1
Try this, we take the value from "n" and check whether it is divisible by two or not. If it is divisible by two, we increment the counter and then divide that number by 2. If not, it will print the output.
n = int(input("Input your number: "))
counter = 0
while n % 2 != 1:
counter = counter + 1
n = n/2
print(counter)
Your while loop condition is wrong.
While the number is evenly divisible by 2, divide it by 2 and increment counter
num = int(input('Enter a number: '))
counter = 0
while num % 2 == 0 and num != 0:
num = num / 2
counter = counter + 1
print(counter)
The code above will not work as intended. The intended functionality is to take an input natural number and find out how many times in a row the number can be divided by 2. However, the code will only divide the number by 2 once.
To fix this, you can change the code to the following:
n = int(input())
counter = 0
while n > 0:
if (n % 2) == 0:
counter = counter +1
n = n // 2
print (counter)
You need to test whether a number is divisible by 2. You can do this in one of two ways...
x % 2 == 0 # will be True if it's divisible by 2
x & 1 == 0 # will be True if it's divisible by 2
So, you need a loop where you test for divisibility by 2, if True divide your original value by 2 (changing its value) and increment a counter
N = int(input())
counter = 0
if N != 0:
while N % 2 == 0:
counter += 1
N //= 2
print(counter)
Or, if you prefer more esoteric programming, then how about this:
N = int(input())
b = bin(N)
print(0 if (o := b.rfind('1')) < 0 else b[o:].count('0'))

Why does the list index not reset after I remove a block?

The question reads as follows:
Every maximal block of k consecutive digits with k>1 scores 10**(k-2) points for that block. A block of two digits thus scores one point, three digits score ten points, four digits score a hundred points, and so on. However, a special rule is in effect saying that whenever a block of digits lies at the lowest end of the number, that block scores double the points it would score in any other position. This function should compute the meaningfulness score of the given positive integer n as the sum of its individual block scores.
def duplicate_digit_bonus(n):
num = str(n)
if len(num) == 1:
return 0
digit = num[0]
new_len, old_len, score = len(num), len(num), 0
while new_len != 0:
block_len = 0
for i in range(len(num)):
if num[i] != digit:
digit = num[i]
new_len = old_len - block_len
old_len = new_len
num = num[block_len:]
if block_len >= 2:
score = score + 10**(block_len - 2)
else:
block_len += 1
return score
While I haven't addressed the duplicate points at the end, how do I make sure the index resets when i read through the new_block. It continues from the previous loop.
Honestly I don't get the idea of your algorithm.
Maybe you can get some value from this approach:
def f (n):
scores = []
length = 1
for i in range (1, len(n)):
if n[i-1] < n[i]:
length += 1
else:
scores.append (length)
length = 1
scores.append (length)
return sum([10 ** (k - 2) for k in scores if k >= 2])
print ( f ([1,2,3,4,1,2]) )
Result:
101

how to find how many factorial numbers are within a file

i have a problem when i try to find if a number is factorial
this is what I've done so far:
i = 1
count = 0
while n>1:
if n % i == 0:
n /= i
else:
break
i+=1
if n<=1:
count += 1
return count
but it returns 1 and I don't know how to fix
As written, the value of count in your example code indicates whether or not the number n is a factorial number, for a single n.
If it is, then at some point n <= 1, so count will be incremented, and the value of count returned by the function will be 1. If it is not, then at some point before n <= 1, n % i == 0 will be False, the loop will break, and the returned value of count will be 0.
Note, though, that there is an edge case not covered by your example code as is. Namely, 1 is a factorial number (1! = 1). But if n is 1, the condition on the while loop is never True, so the function immediately returns 0. So, you need to change the condition in the while loop.
E.g.
def isfactorialnumber(n):
i = 1
count = 0
while n >= 1:
if n % i == 0:
n /= i
else:
break
i += 1
if n <= 1:
count += 1
return count
I have 2 further comments about this code.
First, in the context of this new function, the variable name count is misleading. What is it counting? Nothing, really. It can only take 2 values, 1 or 0. It would be better then, to use a boolean variable, and call it result or similar. Even better, get rid of the variable and refactor your code as:
def isfactorialnumber(n):
i = 1
while n >= 1:
if n % i == 0:
n /= i
else:
break
i += 1
if n <= 1:
return True
return False
Which is equivalent but a little better.
Second, a more readable, natural way to solve the problem would be to work from bottom-up. That is, solve the problem by generating the factorial numbers, m that are less than or equal to n, then checking if the last m is equal to n. This leads to more concise and understandable code IMO.
E.g.
def isfactorialnumber(n):
m = 1
i = 1
while m < n:
m *= i
i += 1
return m == n
Finally, assuming each number in your file, is on its own line:
with open('factorials.txt') as infile:
print(len([1 for line in infile if isfactorialnumber(int(line))]))
Will print the number of factorial numbers in the file factorials.txt
count = 0
for n in listOfNumbers:
i = 1
while n>=1:
if n % i == 0:
n /= i
else:
break
i+=1
if n<=1:
count += 1
return count

Counting Consecutive 1s in a Binary Number

This is a HackerRank Day 10 Code Problem (30 Days of Code Challenge)
I have figured out most of the part but I am stuck at the part where you have to count the number of consecutive 1s in a binary representation.
The code works just fine for consecutive 1s in the beginning or in the middle of the whole series,
But for consecutive 1s at the end I can't figure out what to do
cons = 0
def bin_no():
global rem, cons
#Input
n = int(input("Enter Number : "))
rem=[]
#Checking If The Number Is Valid Or Not.
if n < 0:
print("Please Enter A Valid Number : ")
bin_no()
elif n == 0:
print('0000')
#While Loop for Conversion
while n >=1 :
rem.append(n%2)
n = n//2
rem.reverse()
print("Binary Representation ",*rem, sep = '')
#Finding Maximum Consecutive 1s.
maxcon = 0
for x in rem:
if x == 1:
cons += 1
elif x != 1 and cons > maxcon:
maxcon = cons
cons = 0
print(maxcon)
bin_no()
You can see the Maximum Consecutive 1s code block near the end of the code.
I know the error is caused due to the ending of the list doesn't contain any element that is
not equal to 1
Thus the ending elif code block is ignored.
You need to setup a condition to check the maximality after the loop itself incase as you mentioned the maximum-consecutive-1s are towards the end:
#Finding Maximum Consecutive 1s.
maxcon, cons = 0, 0
for x in rem:
if x == 1:
cons += 1
elif x != 1 and cons > maxcon:
maxcon = cons
cons = 0
maxcon = max(maxcon, cons)
^^This should fix it
EDIT
Btw, I come up with a more elegant solution which doesnt require converting the number into its binary format:
N = int(14)
cons, maxcon = 0, 0
while N > 0:
if N & 1:
cons += 1
else:
maxcon = max(cons, maxcon)
cons = 0
N >>= 1
maxcon = max(cons, maxcon)
print(maxcon)
3
Serial Lazer's edit is definitely the way to go, but I just wanted to correct their first answer.
def consec_ones_a(rem):
count, largest = 0, 0
for x in rem:
if x == 1:
count += 1
else:
if count > largest:
largest = count
count = 0
return max(largest, count)
def consec_ones_b(rem):
maxcon, cons = 0, 0
for x in rem:
if x == 1:
cons += 1
elif x != 1 and cons > maxcon:
maxcon = cons
cons = 0
return max(maxcon, cons)
# 4 consecutive 1s
binary = [1,1,1,0,1,0,1,1,1,1]
print(consec_ones_a(binary))
print(consec_ones_b(binary))
outputs
4
5

How can I count numbers in the given range?

So I wrote a code which lists all the numbers that are not divisible by 2 and 3. Now I would like to know how many of those numbers are in rage 1000. After googling a bit I haven't found anything that can help me with my case.
Could you guys give me some tips? Would appreciate it!
for i in range(1, 1000):
if i%2 != 0 and i%3 != 0:
print(i)
The range is already defined, put a count
count = 0
for i in range(1, 1000):
if i%2 != 0 and i%3 != 0:
count += 1
print("The number is {}".format(i))
print("Count: {}".format(count))
OUTPUT:
The number is 1
The number is 5
The number is 7
The number is 11
The number is 13
.
.
.
The number is 991
The number is 995
The number is 997
Count: 333
EDIT:
one-liner
print("Count: {}".format(sum(1 for i in range(1000) if i%2 != 0 and i%3 != 0)))
count=0
for i in range(1, 1000):
if i%2 != 0 and i%3 != 0:
count=count+1
print(i)
just make a count inside a IF block
There are 1000/2 = 500 numbers divisible by 2 and 1000/3 = 333 divisible by 3. Among these, the multiples of 6 appear twice and there are 1000/6 = 165 of them.
Hence 1000 - (500 + 333 - 166) = 333.
Up to a billion billion, you would have 1,000,000,000,000,000,000 - (500,000,000,000,000,000 - 333,333,333,333,333,333 - 166,666,666,666,666,666) = 333,333,333,333,333,333 of them, which is just a third.
The simplest solution is to put a count variable in your loop and increment it.
count = 0
for i in range(1, 1000):
if i%2 != 0 and i%3 != 0:
count+=1
print(i)
print(count)
Another solution might be:
count = len([x for x in range(1,1000) if x%2!=0 and x%3!=0])
def number_of_not_divisible(a, b, myrange):
result = 0
least_common_multiple = a * b
while myrange % least_common_multiple != 0:
if myrange % a != 0 and myrange % b != 0:
result += 1
myrange -= 1
partial_result_inside_one_range = 0
for i in range(least_common_multiple):
if i % a != 0 and i % b != 0:
partial_result_inside_one_range += 1
result += partial_result_inside_one_range * (myrange / least_common_multiple)
print(result)
number_of_not_divisible(2, 3, 1000)
You can make it easier and general. You can see that in every interval with size of least common multiple of the two numbers, the number of searched elements are the same. So you just have to count in the first interval, and have to multiple it, and after just count, the numbers in the range%least common multiple. I think it have to work general, but tell me if you get a mistake.

Categories