Implement excel function SUMIFS as a function in python.
SUMIFS(sum_list, criteria_list, condition). Here first argument is the list on
which sum will be performed. Second argument is the list on which condition is
checked, and third argument is condition as a string , as in excel.
possible values of condition are
- < less than
- <= less than or equal to
- > greater than
- >= greater than or equal to
- <> not equal to
- empty means equal
Sample run is shown below. For simplicity assume that all the data consists of integers.
>>> d = [1,2,3,4,5,4,4,5]
>>> a = [10,20,30,40,50,40,40,50]
>>> SUMIFS(d, a, "<40")
6
>>> SUMIFS(d, a, ">=40")
22
>>> SUMIFS(d, a, "40")
12
>>> SUMIFS(d, a, "<>40")
16
You can verify your solution using:
%verify_problem sumifs
# your code here# approach 1def check_cond(n, cond):if cond.startswith("<"): # "<40"return n <int(cond.replace("<",""))elif cond.startswith("<="): # "<=40"return n <=int(cond.replace("<=",""))# complete this....def check_cond_find_indices(condlist, cond):return [i for i, item inenumerate(condlist) if check_cond(item, cond)]def sumifs(sumlist, condlist, cond): indices = check_cond_find_indices(condlist, cond)return sum_based_on_indices(indices , sumlist)# approach 2def sumifs((sumlist, condlist, cond): s =0for x, c inzip(sumlist, condlist):if condition_check(c, cond): s += xreturn s
d = [1,2,3,4,5,4,4,5]a = [10,20,30,40,50,40,40,50]
consider the case “<40” indices which are less than 40 in a are 0, 1, 2 d[0] + d[1] + d[2] 1 + 2 + 3 6
for x, y inzip(a, d):print(x, y)
10 1
20 2
30 3
40 4
50 5
40 4
40 4
50 5
%load_problem paste-cmd
Problem: Paste
Write a program paste.py that takes two files as command-line arguments and contacenates the corresponding lines in those two files with a tab character and prints it.
For example, of the first file files/a.txt has the following contents:
A
B
C
D
and the second file files/b.txt has the following:
1
2
3
4
The output should be:
$ python paste.py files/a.txt files/b.txt
A 1
B 2
C 3
D 4
Note that the first line is "A\t1".
For simplicity, assume that both the files have exactly same number of lines.
Hint:
You can use the strip method on a string to remove the new line character.
>>> "a\n".strip("\n")
"a"
You can verify your solution using:
%verify_problem paste-cmd
%%file paste.py# your code hereimport sysdef paste(filepath1, filepath2):withopen(filepath1) as f1:withopen(filepath2) as f2:for line1, line2 inzip(f1, f2):print(f"{line1}\t{line2}") # Handle new lines in line1 and line2if__name__=="__main__": file1, file2 = sys.argv[1], sys.argv[2] paste(file1, file2)
Writing paste.py
withopen("poem.txt") as f:for line in f:print(line) # line contains extra new line character... #you will have to remove it with strip
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
%load_problem group
Problem: Group
Write a function group that take a list of values and splits into smaller lists of given size.
# your code heredef signature(word):return"".join(sorted(word))def anagrams(words): ana = {}for word in words: sig = signature(word) if sig in ana: ana[sig].append(word) # can you make use setdefault else: ana[sig] = [word]return [v for v in ana.values()]
Write a function reverse_digits which will reverse digits of multi digit number and return new formed integer.
>>> reverse_digits(1234)
4321
You can verify your solution using:
%verify_problem reverse-digits
# your code here
convert to text
use slicing to reverse
convert back to int
%load_problem split
Problem: Split a File
Write a program split.py that splits a large file into multiple smaller files. The program should take a filename and the number of lines as arguments and write multiple small files each containing the specified number of lines (The last one may have smaller number of lines).
Suppose you have a file 100.txt in the current directory. (you can copy it from files/100.txt).
$ cp files/100.txt 100.txt
When you run split.py with that, it should split that into multiple small files.
Write a python script tail.py which mimics unix command tail.
The command will show last few lines of a file. It takes filename as argument
and optional argument -n to specify how many lines to display. By default it
displays last 5 lines of the file.
$ python tail.py --help
usage: tail.py [-h] [-n LINES] filename
positional arguments:
filename path to the file
options:
-h, --help show this help message and exit
-n LINES, --lines LINES
Number of lines to display
$ python tail.py files/ten.txt
6
7
8
9
10
$ python tail.py -n 3 files/ten.txt
8
9
10
$ python tail.py zen.txt
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
You can verify your solution using:
%verify_problem tail
%%file tail.py# your code here
import collections
d = collections.deque(maxlen=5)
d.append(1)
d.append(2)
d
deque([1, 2], maxlen=5)
d.append(3)
d.append(4)
d.append(5)
d
deque([1, 2, 3, 4, 5], maxlen=5)
d.append(10)
d
deque([2, 3, 4, 5, 10], maxlen=5)
create a deque of size n
open a file
keep reading the lines and keep appending to the deque
after all the reading is over deque will have required last lines put a a loop and print it