5
\$\begingroup\$

Given a number, for example, \$6\$, this Python function should print hashes in the following format:

     #
    ##
   ###
  ####
 #####
######

This is the function used to accomplish this:

def hash_print(number):
    for i in range(number):
        hashes='#' *(i+1)
        spaces=' '*(number -(i+1))
        print("%s%s") %(spaces,hashes)

Is there any way that this can be improved?

\$\endgroup\$
4
\$\begingroup\$

Python's str has justifying functions. The relevant one here would be rjust(). So we could just use that directly:

def hash_print(number):
    for i in range(number):
        hashes = '#' * (i+1)
        print hashes.rjust(number)

This is also \$O(n^2)\$ to build up hashes over time, so on the off chance that performance becomes a consideration, we could build it up as we go:

def hash_print(number):
    hashes = [' '] * number
    for i in range(number):
        hashes[number - i - 1] = '#'
        print ''.join(hashes)
\$\endgroup\$
  • \$\begingroup\$ The O(n2) part that you mentioned. Would you be able to direct me to a place where I can learn about that? Thanks for the answer! \$\endgroup\$ – adele dazim Sep 21 '15 at 19:10
  • \$\begingroup\$ @adeledazim: IDK if either of these links help. Either too broad and mathy: en.wikipedia.org/wiki/Computational_complexity_theory, or too specific: bigocheatsheet.com. Basically, look at how your run time will behave as problem-size approaches infinity, discarding any constant factors and smaller terms. e.g. O(3 * n^2 + 2 * nlog n) = O(n^2) complexity class. \$\endgroup\$ – Peter Cordes Sep 22 '15 at 3:09
  • \$\begingroup\$ In real life, you're almost always working with fixed-width ints, but a list of the first n consecutive integers takes log2 n bits to represent. This is the biggest source of debate about complexity-class analysis of algorithms on stackoverflow. Usually it's most useful to look at limit = 2^32 or 2^64, not actually infinity with arbitrary precision mathematical integers. So to keep everyone happy, just make it clear you're analysing under the assumption of bounded sizes of integer, even if your list length goes to infinity. \$\endgroup\$ – Peter Cordes Sep 22 '15 at 3:12
  • \$\begingroup\$ @Barry: Fair point about optimizing for large n, but print has at least a small O(n) component. You have to print n characters n times, so you can't beat $O(n^2)$. Modifying just one character of the array each time reduces the constant-factor, though. \$\endgroup\$ – Peter Cordes Sep 22 '15 at 3:16
  • \$\begingroup\$ The second version is slower with large n, because joining a large number of strings is slow. \$\endgroup\$ – Janne Karila Sep 22 '15 at 6:35
1
\$\begingroup\$

You could do this on one line with join and a generator expression.

def hash_print(number):
    print ('\n'.join(('#' * (i + 1)).rjust(number) for i in range(number)))

A generator expression is like a for loop collapsed into a one line expression. It will loop over range(number) and create right justified strings of hashes, joining them together with newline characters in between them.

Also to note about some of your usages, you should put spaces between each operator, as it's easier to read. Changing this:

hashes='#' *(i+1)

to this:

hashes = '#' * (i + 1)

Also you should use str.format, not the % syntax for passing parameters to a string. str.format has a lot of useful formatting and is the accepted form nowadays. % is just older syntax. You can read about the usefulness of str.format here.

Though in your case they're both strings so you can just use string concatenation with the + operator:

    print( spaces + hashes )
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.