-2

I want to add '-' to the last line if the number of lines in my file is not a power of 2, but not more than 64, so that the number of lines becomes the nearest power of two.

This is what i came up with so far, it doesn't work for me, but i am not sure if i may need an whole other function to check the number.

def name():
j=open('file.txt', 'r', encoding='utf-8')
numbers=sum(1 for line in j)
if numbers != 2 or 4 or 8 or 16 or 32 or 64:
   j.append('-')

Any suggestions?

Now I have this, still doesn't work all the way, when it prints i can't see the added lines

def name():
 with open('file.txt', 'r+', encoding='utf-8') as j:
     numbers=sum(1 for line in j)
     if numbers < 64:
        lower2 = round(2**math.log(numbers, 2))
        if numbers > lower2:
            missing = 2*lower2 - numbers
            j.write('-\n' * missing)

j=open('file.txt', 'r', encoding='utf-8')
for i in j.readlines():
    print (i)
    j.close()
  • In the edited version, you copied my code wrong. Instead of `round(2**int(math.log(numbers, 2)))`, you just did `round(2**math.log(numbers, 2))`. For example, given the number `6`, `math.log(6, 2)` is around 2.58, so `int(math.log(6, 2))` is 2 and `round(2**math.log(6, 2))` is `4`, meaning there are 2 missing lines… but `round(2**math.log(6, 2))` is of course just `6`, meaning there are no missing lines. – abarnert Jan 07 '14 at 21:04
  • If you don't understand how logarithms work, you should try to write the math in a way you _do_ understand. (Even if it's a little less efficient or verbose, who cares? Even the most naive algorithm would only take a couple more lines and waste under a microsecond…) Also, you need to learn how to do basic debugging—print out the intermediate values that you're computing to see where things are going wrong, so you have more information to go on than just "it doesn't seem to work". – abarnert Jan 07 '14 at 21:06

1 Answers1

3

There are multiple problems with your code:

  • There's no append method on files. You write to files.
  • You can't write to a file that you explicitly asked to open read-only, with that 'r' mode. Open in a different mode, like 'r+' for read-write.
  • numbers != 2 or 4 or 8 or 16 or 32 or 64 doesn't mean what you think it does. There are dozens of questions on SO explaining this; the short version is that you want numbers not in (2, 4, 8, 16, 32, 64).
  • You never close the file, so even if you did manage to write to it, the new data may never get flushed to disk. The easiest way to fix this is to use a with statement instead of explicit open and close.

So:

def name():
    with open('file.txt', 'r+', encoding='utf-8') as j:
        numbers = sum(1 for line in j)
        if numbers not in (2, 4, 8, 16, 32, 64):
            j.write('-')

See What's going on with my if-else statement and the various linked/related questions of more on why your or doesn't work.

The chapter on Reading and Writing Files in the tutorial will explain everything else.


Also, text files should usually end with a newline unless you have a good reason not to, so you probably want to write '-\n', not just '-'.


Meanwhile, it seems like, even if you implement your algorithm right, it doesn't actually do what you wanted to do:

I want to add '-' to the last line if the number of lines in my file is not a power of 2, but not more than 64, so that the number of lines becomes the nearest power of two.

Adding '-' to the end will add only 1 line (or 0, if the last line didn't end with a newline). So, if you had, say, 61 lines, now you'll have 62, not 64. So, I think you'd need to change your code to something like this:

if numbers < 64:
    while numbers not in (2, 4, 8, 16, 32, 64):
        j.write('-\n')
        numbers += 1

But it may be a lot simpler at this point to just do the math. For example:

if numbers < 64:
    lower2 = round(2**int(math.log(numbers, 2)))
    if numbers > lower2:
        missing = 2*lower2 - numbers
        j.write('-\n' * missing)

Or, if you want to get clever:

if numbers < 64:
    higher2 = 2**numbers.bit_length()
    missing = higher2 - numbers
    j.write('-\n' * missing)
Community
  • 1
  • 1
abarnert
  • 354,177
  • 51
  • 601
  • 671