Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need advice with making a histogram

Tags:

python

So I need to make a histogram. My current print looks like this, coming from my code at the bottom of the post. There are a few issues, as can be seen when comparing the my output to the example output.

Issue 1: The amount of stars only corresponds to the numbers inputted. So if I typed 100, 50, 20, 1 it would print a 100 stars, 50 stars, 20 stars, and a single star, with the smallest 4 ranges available.

Issue 2: In addition to the ranges not being taken into consideration, empty ranges need to be visible like they are in the example.

I've been thinking about this for some time, but just simply can't find any good solutions. I'm also rather new to python...so...Help?

What my histogram looks like right now:

Enter energy consumption data.
End by entering an empty line.

Enter energy consumption (kWh): 5
Enter energy consumption (kWh): 3
Enter energy consumption (kWh): 2
Enter energy consumption (kWh): 1
Enter energy consumption (kWh): 
      0-9: *****
    10-99: ***
  100-999: **
1000-9999: *

And this is what it should look like...

Enter energy consumption data.
End by entering an empty line.

Enter energy consumption (kWh): 91
Enter energy consumption (kWh): 10
Enter energy consumption (kWh): 1001
Enter energy consumption (kWh): 5005
Enter energy consumption (kWh): 22
Enter energy consumption (kWh): 6
Enter energy consumption (kWh):
      0-9: *
    10-99: ***
  100-999: 
1000-9999: **

My code:

def user_input():
    list1 = []
    value = input("Enter energy consumption (kWh): ")
    while value != "":
        value = int(value)
        if value >= 0:
            list1.append(value)
        else:
            print(f"You entered: {value}. Enter non-negative numbers only!")
        value = input("Enter energy consumption (kWh): ")
    return list1



def determine_class(value):
    class_number = 1
    while True:
        if class_minimum_value(class_number) <= value <= class_maximum_value(
                class_number):
            return class_number
        class_number += 1

def class_minimum_value(class_number):
    smallest_value = 10 ** class_number // 100 * 10
    return smallest_value

def class_maximum_value(class_number):
    largest_value = 10 ** class_number - 1
    return largest_value

def class_listing(list1):
    number_of_categories = determine_class(max(list1))
    category_list = [0] * number_of_categories

    for value in list1:
        category = determine_class(value)
        category_list[category-1] += 1
    return category_list

def print_histogram(class_listing):

    for i in range(len(class_listing)):
        print_single_histogram_line(i+1, class_listing[i], len(class_listing))


def main():
    print("Enter energy consumption data.")
    print("End by entering an empty line.")
    print()

    input_data = user_input()
    if len(input_data) == 0:
        print("Nothing to print. Done.")
        return
    class_different = class_listing(input_data)
    print_histogram(input_data)


def print_single_histogram_line(class_number, count, largest_class_number):

    min_value = class_minimum_value(class_number)
    max_value = class_maximum_value(class_number)
    range_string = f"{min_value}-{max_value}"



    largest_width = 2 * largest_class_number + 1


    print(f"{range_string:>{largest_width}}: {'*' * count}")


if __name__ == "__main__":
    main()
like image 857
questionasker1109 Avatar asked Dec 10 '25 02:12

questionasker1109


1 Answers

It was a bit hard to navigate in your code, but as I see it, your main issue is with collecting an printing the histogram as you want, so only for that part you can see the code below which receive list of items (corresponded to your m_input variable), transfer it to histogram and print is formatted as you want:

def alternative_histogram(input_data):
    max_bucket_power = len(str(max(input_data)))
    m_histogram = {}
    for power in range(max_bucket_power):
        m_histogram[power] = len([item for item in input_data if 10**(power)-1<item<10**(power+1)])
    max_length_bucket = len(f'{10**(max_bucket_power-1)} - {10**(max_bucket_power)-1}')
    for iter, (bucket,count) in enumerate(m_histogram.items()):
        if iter == 0:
            print(f'0 - 9'.rjust(max_length_bucket) + f': {"*"*count}')
        else:
            print(f'{10**(bucket)} - {10**(bucket+1)-1}'.rjust(max_length_bucket) + f': {"*" * count}')
            
m_input1 = [1,19,942,489]
m_input2 = [1,2,3,4,5,12,13,14,15,100,101,102,1001,1002,100002]
print("histogram 1:")
alternative_histogram(m_input1)

output:

histogram 1:
    0 - 9: *
  10 - 99: *
100 - 999: **
histogram 2:
          0 - 9: *****
        10 - 99: ****
      100 - 999: ***
    1000 - 9999: **
  10000 - 99999: 
100000 - 999999: *

Exactly as I was expected it to be, is that match your required?

Edited to perform rjust on the histogram print, to match exactly the expected output

like image 194
Yossi Levi Avatar answered Dec 11 '25 17:12

Yossi Levi