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\$

2 Answers 2

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\$
5
  • \$\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\$ Sep 21, 2015 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\$ Sep 22, 2015 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\$ Sep 22, 2015 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\$ Sep 22, 2015 at 3:16
  • \$\begingroup\$ The second version is slower with large n, because joining a large number of strings is slow. \$\endgroup\$ Sep 22, 2015 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 and acknowledge you have read our privacy policy.

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