Python Histogram - python

I'm trying to create a histogram in python as a part of my python class
It is supposed to look like this:
However, I can't figure out the histogram. This is my code so far:
sumValues = []
print("Enter 10 integers")
for i in range( 10 ):
newValue = int( input("Enter integer %d: " % (i + 1) ))
sumValues.append(newValue)
print("\nCreating a histogram from values: ")
print("%s %10s %10s" %("Element", "Value", "Histogram"))
How do I create the actual histogram?

Some hints:
New-style Python formatting allows this:
In [1]: stars = '*' * 4 # '****'
In [2]: '{:<10s}'.format(stars)
Out[3]: '**** '
That is, you can take a string of 4 stars (formed by repetition of '*' four times) and place it in a string of length 10 characters, aligned to the left (<) and padded to the right with whitespace.
(If you don't need the histogram to have the same number of characters (stars or spaces), just print the stars; no need to format)

Just like this:
# fake data
sumValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
...
# calculate how long is the list and adjust the padding for 'Element'
padding = max(len(sumValues), len('Element'))
# now the padding for 'Value'
padding1 = max(len(str(max(sumValues))), len('Value'))
print("\nCreating a histogram from values: ")
print("%s %10s %10s" %("Element", "Value", "Histogram"))
# use enumerate to loop your list and giving the index started from 1
for i,n in enumerate(sumValues, start=1):
print '{0} {1} {2}'.format( # print each line with its elements
str(i).ljust(padding), # print with space using str.ljust
str(i).rjust(padding1), # print with space using str.rjust
'*'*n) # '*' * n = '*' multiply by 'n' times
Creating a histogram from values:
Element Value Histogram
1 1 *
2 2 **
3 3 ***
4 4 ****
5 5 *****
6 6 ******
7 7 *******
8 8 ********
9 9 *********
10 10 **********

Related

How to get inverse of integer?

I am not sure of inverse is the proper name, but I think it is.
This example will clarify what I need:
I have a max height, 5 for example, and so height can range from 0 to 4. In this case we're talking integers, so the options are: 0, 1, 2, 3, 4.
What I need, given an input ranging from 0 up to (and including) 4, is to get the inverse number.
Example:
input: 3
output: 1
visual:
0 1 2 3 4
4 3 2 1 0
I know I can do it like this:
position_list = list(range(5))
index_list = position_list[::-1]
index = index_list[3]
But this will probably use unnecessary memory, and probably unnecessary cpu usage creating two lists. The lists will be deleted after these lines of code, and will recreated every time the code is ran (within method). I'd rather find a way not needing the lists at all.
What is an efficient way to achieve the same? (while still keeping the code readable for someone new to the code)
Isn't it just max - in...?
>>> MAX=4
>>> def calc(in_val):
... out_val = MAX - in_val
... print('%s -> %s' % ( in_val, out_val ))
...
>>> calc(3)
3 -> 1
>>> calc(1)
1 -> 3
You just need to subtract from the max:
def return_inverse(n, mx):
return mx - n
For the proposed example:
position_list = list(range(5))
mx = max(position_list)
[return_inverse(i, mx) for i in position_list]
# [4, 3, 2, 1, 0]
You have maximum heigth, let's call it max_h.
Your numbers are counted from 0, so they are in [0; max_h - 1]
You want to find the complementation number that becomes max_h in sum with input number
It is max_h - 1 - your_number:
max_height = 5
input_number = 2
for input_number in range(5):
print('IN:', input_number, 'OUT:', max_height - input_number - 1)
IN: 1 OUT: 3
IN: 2 OUT: 2
IN: 3 OUT: 1
IN: 4 OUT: 0
Simply compute the reverse index and then directly access the corresponding element.
n = 5
inp = 3
position_list = list(range(n))
position_list[n-1-inp]
# 1
You can just derive the index from the list's length and the desired position, to arrive at the "inverse":
position_list = list(range(5))
position = 3
inverse = position_list[len(position_list)-1-position]
And:
for i in position_list:
print(i, position_list[len(position_list)-1-i])
In this case, you can just have the output = 4-input. If it's just increments of 1 up to some number a simple operation like that should be enough. For example, if the max was 10 and the min was 5, then you could just do 9-input+5. The 9 can be replaced by the max-1 and the 5 can be replaced with the min.
So max-1-input+min

for loop create a list around "x" based on "n"

Basically trying to figure out how to create a for loop that generates a range around a the main number "x" based on "n"
x = 10 # x = Actual
n = 5
because
Actual = input("What's the Actual") # Enter 10
Target = input("What's the Target") # Enter 15
n = Target - Actual # 5 = 15 - 10
Since Actual is 10
I would like to see..
5, 6, 7, 8, 9 , 10, 11, 12, 13, 14, 15
The code is:
n = 2
def price(sprice):
for i in range(n*2):
sprice = sprice + 1
print(sprice)
price(200)
This code shows 201,202,203,204 and the actual is 200.
I want to see 198,199,200,201,202 because n = 2 and when multiply by 2 = 4 which shows a range of 4 values around 200
According to the docs, range can accept two argument that specify the start (inclusive) and end (exclusive) of the interval. So you can get an interval in the form [start, stop).
You would like to create the interval [Actual - n, Actual + n], so just translate it almost literally to Python, bearing in mind that range excludes the second argument from that range, so you should add one to it:
>>> list(range(Actual - n, Actual + n + 1))
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
ForceBru has already shown a pythonic solution to your problem. I only want to add that your original code works as intended after some minor tweaks:
n = 2
def price(sprice):
sprice -= n # short way to say: sprice = sprice - n
for i in range(n*2+1): # +1 required as in 1-argument range it is exclusive
sprice = sprice + 1
print(sprice)
price(200)
Output:
199
200
201
202
203
Note that Python recognizes * is to be executed before + independently from its order. Hence you might write 1+n*2 in place of n*2+1.

Memory efficient way to read an array of integers from single line of input in python2.7

I want to read a single line of input containing integers separated by spaces.
Currently I use the following.
A = map(int, raw_input().split())
But now the N is around 10^5 and I don't need the whole array of integers, I just need to read them 1 at a time, in the same sequence as the input.
Can you suggest an efficient way to do this in Python2.7
Use generators:
numbers = '1 2 5 18 10 12 16 17 22 50'
gen = (int(x) for x in numbers.split())
for g in gen:
print g
1
5
6
8
10
12
68
13
the generator object would use one item at a time, and won't construct a whole list.
You could parse the data a character at a time, this would reduce memory usage:
data = "1 50 30 1000 20 4 1 2"
number = []
numbers = []
for c in data:
if c == ' ':
if number:
numbers.append(int(''.join(number)))
number = []
else:
number.append(c)
if number:
numbers.append(int(''.join(number)))
print numbers
Giving you:
[1, 50, 30, 1000, 20, 4, 1, 2]
Probably quite a bit slower though.
Alternatively, you could use itertools.groupby() to read groups of digits as follows:
from itertools import groupby
data = "1 50 30 1000 20 4 1 2"
numbers = []
for k, g in groupby(data, lambda c: c.isdigit()):
if k:
numbers.append(int(''.join(g)))
print numbers
If you're able to destroy the original string, split accepts a parameter for the maximum number of breaks.
See docs for more details and examples.

Creating a Pattern with Python

With Python editor I am trying to recreate this specific line pattern over here:
666666
6 6
6 6
6 6
66
6
This is the Code that I have created:
steps=6
for s in range(steps):
print('6' + (' ' * r) + '6')
However the output that I get instead is:
66
6 6
6 6
6 6
6 6
6 6
Thus as you can see it almost does the opposite operation to what I wanted in the opening output above. If there is a way to reverse this output I have to what I want please share.
You can use the built-in reversed function that returns an iterator that goes through the range in reverse.
steps=6
for r in reversed(range(steps)):
print('#' + (' ' * r) + '#')
Or you can use list splicing to revers the list like so:
steps=6
for r in range(steps)[::-1]:
print('#' + (' ' * r) + '#')
Aside from Martijn's comment on considering what kind of pattern you need to follow, i.e. how the number of spaces evolves from one line to the next, you may want to look into the documentation of the command range at PythonDocs on range(). Currently you are only providing one argument:
range(stop)
Python will then use default values for the remaining arguments: start=0 and step=1. However, you can provide these explicitly. The 'step' argument is where you can put in reversed counting:
range(start, stop[, step])
Let us start with building it in ascending order, that is like the diagram below
6
66
6 6
6 6
66666
There is a series to the number of spaces depending after height = 1, that is from height = 2 the number of spaces have the series 0,1,2 and so on, therefore if height is n then the series begins at 2 where the space = 0 and ends at n - 1 where the number of spaces is equal to n - 3, and at height = n the number of 6s is equal to n - 2.
The code for this would be
def print6(height):
... print 6
... for s in range(0, height - 2):
... print str(6) + ' '*s + str(6)
... print str(6)*2+str(6)*(height-2)
To reverse this
def print6(height):
... print str(6)*2+str(6)*(height-2)
... for s in range(0, height - 2):
... print str(6) + ' '*(height-3-s) + str(6)
... print 6

Asterisk Pyramid Not Spaced Correctly

Here is my code but I'm having trouble getting the pyramid to be spaced correctly like a pyramid and also to only have odd number of asterisks per line.
Output when you enter 7 for the base should be
*
***
*****
*******
This is my code:
base = int(input( 'enter an odd number for the base : ' ) )
for i in range( 0, base ):
print '*' * i
You could use str.center():
for i in range(1, base + 1, 2):
print ('*' * i).center(base)
but do use a step size of 2, and adjust your range. The first line starts with 1 star always, and range() doesn't include the last value.
For 7, that means you want to print 1, 3, 5 and 7 stars, incrementing by 2 each iteration.
There are some errors in your code:
since you're using print '...' instead of function print, you may be in python2, where raw_input is needed instead of input;
range(1, base+1, 2) is needed instead, for your sample output.
Demo:
In [6]: base = int(raw_input( 'enter an odd number for the base : ' ) )
...: for i in range(1, base+1, 2):
...: print ('*' * i).center(base)
enter an odd number for the base : 7
*
***
*****
*******

Categories