Using a for loop to add sum of numbers from a .txt file - for-loop

I'm trying to add the sum of all numbers from a text file and print out all numbers that were added.
Text file includes 9,5,9,7,11. The numbers are on separate lines. The total is 41, but my code keeps printing 52.
The output should look like:
9 5 9 7 11. Your total is: 41
def main():
# Open a file for reading.
infile = open('numbers.txt', 'r')
total = 0
for line in infile:
amount = int(line)
total += amount
total += int(line.strip())
infile.close()
print(line)
print('Your total is:',total)
main()

infile = open('numbers.txt', 'r')
total = 0
for line in infile:
amount = int(line)
total += amount
infile.close()
print(line)
print('Your total is:',total)
No need of using this line
total += int(line.strip())
Now your program works correctly.

Related

why 'float' object is not iterable

I am a beginner, so i try to practice as much as i can. In below code, i have to extract numbers from a text file with hundred lines and sum numbers. I wrote below code and the ouput message is : float object are not iterable.
I will appreciate help and advises.
fname = 'mbox-short.txt'
fh = open(fname,"r")
count = 0
for line in fh :
line = line.rstrip()
if not line.startswith('X-DSPAM-Confidence:') : continue
count = count + 1
#print(count)
colonn_pos = line.find(':')
fnum = line[colonn_pos+1:]
numbers = float(fnum)
#print(numbers)
total = 0
for values in numbers :
if values < 1 :
total = total + values
print(total)
Here below numbers output to sum :
0.8475
0.6178
0.6961
0.7565
0.7626
0.7556
0.7002
0.7615
0.7601
You're setting numbers to a single float object, which is not iterable.
If you want to iterate over all of the floats that are generated by the first loop, you should create a list called "numbers" and append() every individual float to it.
numbers = []
count = 0
for line in fh :
line = line.rstrip()
...
numbers.append(float(fnum))
total = 0
for value in numbers:
...
I would also point out that iterating over a list to generate a list that you iterate over again is redundant, so I'd actually change it to this:
count = 0
total = 0.0
for line in fh :
line = line.rstrip()
...
num = float(fnum)
if num < 1:
total += num
print(total)

Writing a text file in new format

I have a text file like this:
1 0.1278000E-01 0.000000 0.000000
259 0.1172645E-01-0.5057909E-02 0.000000
260 0.7262609E-02-0.1052830E-01 0.000000
It has 4 columns and 3 rows. The numbers in the last column are always zero. If the number in the third column is not zero (row 2,3) this number is attached to the number in the second column.
I want to add something to this file and change its format to:
Point(1) = {0.1174800E-01, 0, 0};
Point(259) = {0.1172645E-01, -0.5057909E-02, 0};
Point(260) = {0.7262609E-02, -0.1052830E-01, 0};
Does anybody know how I can do it?
Thanks!
A solution to this problem in Python 3.6:
lines = [line.rstrip('\n') for line in open('input.txt')]
output = open('output.txt', 'w')
for line in lines:
line = line.split()
if len(line) == 3:
line[1], line[2] = line[1][:line[1].find("E") + 4],
line[1][line[1].find("E") + 4:]
output.write('Point({}) = {{{}, {}, 0}};\n'.format(line[0], line[1], line[2]
if float(line[2]) != 0 else '0'))
output.close()
EDIT: It's a bit hard coded now that the values are not separated by spaces, but it works fine. I think you could improve it with regex, I'll take a look.

Can this be modified to run faster?

I'm creating a word list using python that hits every combination of of characters which is a monster of a calculation past 944. Before you ask where I'm getting 94, 94 covers ASCII characters 32 to 127. Understandably this function runs super slow, I'm curious if there's a way to make it more efficient.
This is the meat and potatoes of the my code.
def CreateTable(name,ASCIIList,size):
f = open(name + '.txt','w')
combo = itertools.product(ASCIIList, repeat = size)
for x in combo:
passwords = ''.join(x)
f.write(str(passwords) + '\n')
f.close()
I'm using this so that I can make lists to use in a brute force where I don't know the length of the passwords or what characters the password contains. Using a list like this I hit every possible combination of words so I'm sure to hit the right one eventually. Having stated earlier that this is a slow program this also slow to read in and will not my first choice for a brute force, this more or less for a last ditch effort.
To give you an idea of how long that piece of code runs. I was creating all the combinations of size 5 and ran for 3 hours ending at a little over 50GB.
Warning : I have not tested this code.
I would convert combo to a list: combo_list = list(combo)
I would then break it into chunks:
# https://stackoverflow.com/a/312464/596841
def get_chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
# Change 1000 to whatever works.
chunks = get_chunks(combo_list, 1000)
Next, I would use multithreading to process each chunk:
class myThread (threading.Thread):
def __init__(self, chunk_id, chunk):
threading.Thread.__init__(self)
self.chunk_id = chunk_id
self.chunk = chunk
def run(self):
print ("Starting " + self.chunk_id)
process_data(self.chunk)
print ("Exiting " + self.chunk_id)
def process_data():
f = open(self.chunk_id + '.txt','w')
for item in self.chunk:
passwords = ''.join(item)
f.write(str(passwords) + '\n')
f.close()
I would then do something like this:
threads = []
for i, chunk in enumerate(chunks):
thread = myThread(i, chunk)
thread.start()
threads.append(thread)
# Wait for all threads to complete
for t in threads:
t.join()
You could then write another script to merge all the output files, if you need.
I did some testing on this, and I think the main problem is that you're writing in text mode.
Binary mode is faster, and you're only dealing with ASCII, so you might as well just spit out bytes rather than strings.
Here's my code:
import itertools
import time
def CreateTable(name,ASCIIList,size):
f = open(name + '.txt','w')
combo = itertools.product(ASCIIList, repeat = size)
for x in combo:
passwords = ''.join(x)
f.write(str(passwords) + '\n')
f.close()
def CreateTableBinary(name,ASCIIList,size):
f = open(name + '.txt', 'wb')
combo = itertools.product(ASCIIList, repeat = size)
for x in combo:
passwords = bytes(x)
f.write(passwords)
f.write(b'\n')
f.close()
def CreateTableBinaryFast(name,first,last,size):
f = open(name + '.txt', 'wb')
x = bytearray(chr(first) * size, 'ASCII')
while True:
f.write(x)
f.write(b'\n')
i = size - 1
while (x[i] == last) and (i > 0):
x[i] = first
i -= 1
if i == 0 and x[i] == last:
break
x[i] += 1
f.close()
def CreateTableTheoreticalMax(name,ASCIIList,size):
f = open(name + '.txt', 'wb')
combo = range(0, len(ASCIIList)**size)
passwords = b'A' * size
for x in combo:
f.write(passwords)
f.write(b'\n')
f.close()
print("writing real file in text mode")
start = time.time()
chars = [chr(x) for x in range(32, 126)]
CreateTable("c:/temp/output", chars, 4)
print("that took ", time.time() - start, "seconds.")
print("writing real file in binary mode")
start = time.time()
chars = bytes(range(32, 126))
CreateTableBinary("c:/temp/output", chars, 4)
print("that took ", time.time() - start, "seconds.")
print("writing real file in fast binary mode")
start = time.time()
CreateTableBinaryFast("c:/temp/output", 32, 125, size)
print("that took ", time.time() - start, "seconds.")
print("writing fake file at max speed")
start = time.time()
chars = [chr(x) for x in range(32, 126)]
CreateTableTheoreticalMax("c:/temp/output", chars, 4)
print("that took ", time.time() - start, "seconds.")
Output:
writing real file in text mode
that took 101.5869083404541 seconds.
writing real file in binary mode
that took 40.960529804229736 seconds.
writing real file in fast binary mode
that took 35.54869604110718 seconds.
writing fake file at max speed
that took 26.43029284477234 seconds.
So you can see a pretty big improvement just by switching to binary mode.
Also, there still seems to be some slack to take up, since omitting the itertools.product and writing hard-coded bytes is even faster. Maybe you could write your own version of product that directly output bytes-like objects. Not sure about that.
Edit: I had a go at a manual itertools.product working directly on a bytearray. It's a bit faster - see "fast binary mode" in the code.

How to use "column" to center a chart?

I was wondering what the best way to sort a chart using the column command to center each column instead of the default left aligned column was. I have been using the column -t filename command.
Current Output:
Label1 label2
Anotherlabel label2442
label152 label42242
label78765 label373737737
Desired Output: Something like this
Label1 label2
Anotherlabel label2442
label152 label42242
label78765 label373737737
Basically, I want it to be centered instead of left aligned.
Here is an awk solution:
# Collect all lines in "data", keep track of maximum width for each field
{
data[NR] = $0
for (i = 1; i <= NF; ++i)
max[i] = length($i) > max[i] ? length($i) : max[i]
}
END {
for (i = 1; i <= NR; ++i) {
# Split record into array "arr"
split(data[i], arr)
# Loop over array
for (j = 1; j <= NF; ++j) {
# Calculate amount of padding required
pad = max[j] - length(arr[j])
# Print field with appropriate padding, see below
printf "%*s%*s%s", length(arr[j]) + int(pad/2), arr[j], \
pad % 2 == 0 ? pad/2 : int(pad/2) + 1, "", \
j == NF ? "" : " "
}
# Newline at end of record
print ""
}
}
Called like this:
$ awk -f centre.awk infile
Label1 label2
Anotherlabel label2442
label152 label42242
label78765 label373737737
The printf statement uses padding with dynamic widths:
The first %*s takes care of left padding and the data itself: arr[j] gets printed and padded to a total width of length(arr[j]) + int(pad/2).
The second %*s prints the empty string, left padded to half of the total padding required. pad % 2 == 0 ? pad/2 : int(pad/2) + 1 checks if the total padding was an even number, and if not, adds an extra space.
The last %s prints j == NF ? "" : " ", i.e., two spaces, unless we're at the last field.
Some older awks don't support the %*s syntax, but the formatting string can be assembled like width = 5; "%" width "s" in that case.
Here's a Python program to do what you want. It's probably too hard to do in bash, so you'll need to use a custom program or awk script. Basic algorithm:
count number of columns
[optional] make sure each line has the same number of columns
figure out the maximum length of data for each column
print each line using the max lengths
.
#!/usr/bin/env python3
import sys
def column():
# Read file and split each line into fields (by whitespace)
with open(sys.argv[1]) as f:
lines = [line.split() for line in f]
# Check that each line has the same number of fields
num_fields = len(lines[0])
for n, line in enumerate(lines):
if len(line) != num_fields:
print('Line {} has wrong number of columns: expected {}, got {}'.format(n, num_fields, len(line)))
sys.exit(1)
# Calculate the maximum length of each field
max_column_widths = [0] * num_fields
for line in lines:
line_widths = (len(field) for field in line)
max_column_widths = [max(z) for z in zip(max_column_widths, line_widths)]
# Now print them centered using the max_column_widths
spacing = 4
format_spec = (' ' * spacing).join('{:^' + str(n) + '}' for n in max_column_widths)
for line in lines:
print(format_spec.format(*line))
if __name__ == '__main__':
column()

How do I describe all integers in Ruby

I'm trying to write a basic program that spits out the English version of a number when the user inputs a numeral:
input = 44
output = fourty four
Is there a way to describe all integers?
Basically I want the execution to look something like:
number = gets.chomp
if number != (whatever the nomenclature is for integer)
puts 'Please enter a positive number'
or something to that effect.
You can do that with the numbers_and_words gem:
https://github.com/kslazarev/numbers_and_words
It supports languages other than english as well.
For example:
21.to_words
=> "twenty-one"
44.to_words
=> "forty-four"
I modified the Fixnum class and added a method in_words. What I did is I broke each number up into groups of three, so 100000 turns into [100, 000] and 123456789 turns into [123, 456, 789] or 1543 turns into [1, 453] then I went element by element and named every number in the element and added the appropriate word, like hundred and thousand. If you have any questions I am happy to explain!
class Fixnum
LOW = %w(zero one two three four five six seven
eight nine ten eleven twelve thirteen fourteen
fifteen sixteen seventeen eighteen nineteen)
TWO_DIGIT = %w(ten twenty thirty forty fifty sixty seventy eighty ninety)
BIG_NUMS = %w(hundred thousand million billion trillion)
def in_words
# Break up number into bytes with three bits each
# Then turn each byte into words
# Break into bytes
number = self.to_s.reverse
bytes = []
num_bytes = (number.length.to_f / 3.0).ceil()
num_bytes.times { |x| bytes << number[(x*3)..(x*3)+2].reverse }
#puts bytes.reverse.join(",")
# Turn bytes into words bit by bit
word = []
text = ""
bytes.each_with_index do |byte, i|
text = ""
# First bit
text = LOW[byte[0].to_i] if (byte.length == 3 && byte[0].to_i != 0) || byte.length == 1
# Add hundred if 3 bits
text += " hundred" if byte.length == 3 && byte[0].to_i != 0
# Second bit
if byte.length == 3 # Three bits
if byte[1].to_i > 1 # Second bit greater than teens
text += " " + TWO_DIGIT[byte[1].to_i + (-1)]
elsif byte[1].to_i != 0 # Second bit not zero
text += " " + LOW[byte[1..2].to_i]
end
elsif byte.length == 2 # Two bits
if byte[0].to_i > 1 # Greater than teens
text += " " + TWO_DIGIT[byte[0].to_i + (-1)]
text += " " + LOW[byte[1].to_i] if byte[1].to_i != 0
else # Less than twenty
text += LOW[byte[0..1].to_i]
end
end
# Third bit if three bytes and second bit > teens and third bit nonzero
text += " " + LOW[byte[2].to_i] if byte[1].to_i != 1 && byte[2].to_i > 0 && byte.length > 2
# Add trillion/billion/million/thousand
text += " " + BIG_NUMS[i] if i != 0 && byte.to_i != 0
word << text.strip if text.strip != ""
end
word.reverse.join(" ")
end
end
Because I modified the Fixnum object, you can call this from any Fixnum e.g. 44.in_words
EDIT: It looks like you might be trying to check input for integers. I would recommend making a function to handle that:
def check_input(i)
if !(i =~ /^[0-9]+$/)
puts "Sorry, that is an invalid input! Please try again"
i = check_input(gets.chomp)
end
i.to_i
end
I think the best way to handle that is with regex (pattern matching). Basically your function checks if the input isn't a number, then it asks for input again. If it is a number, then the function returns the number. /^[0-9]+$/ is the regex. ^ means start of the line and $ means end of the line. [0-9] matches any digit zero through nine (as the Tin Man commented, you can also use \d to represent any digit and it is equivalent), and + means match the previous thing (any digit) at least once.

Resources