Python Exercises: Solutions
Solutions of most of the exercises of this collection of programming examples and problems in Python.
ciao!
(download link: ciao.py)
#!/usr/bin/python3 print('ciao!')
minmax
(download link: minmax.py)
#!/usr/bin/python3 # # This program reads a sequence of numbers from the standard input, # with one or more numbers per line, and prints the minimum and the # maximum values in the list. # import sys A = [] for line in sys.stdin: for a in line.split(): A.append(int(a)) minimum = None maximum = None for a in A: if minimum == None or minimum > a: minimum = a if maximum == None or maximum < a: maximum = a print('min =',minimum) print('max =',maximum)
flipline
(download link: flip_line.py)
#!/usr/bin/python3 # # This program reads a line from the standard input, and outputs that # line flipped right-to-left. # l = input() i = len(l) while i > 0: i = i - 1 print(l[i], end='') print()
pi
(download link: pi.py)
#!/usr/bin/python3 # # A program that takes an integer N > 0 as a command-line parameter, # and prints the values of \pi(i) for all i <= N, where \pi(k) is the # number of prime numbers between 1 and k # import sys def pi(n): # we implement the sieve of Eratosthenes # S = [True]*(n + 1) S[0] = False S[1] = False p = 2 while p * p <= n: if S[p]: i = p * p while i <= n: S[i] = False i = i + p p = p + 1 count = 0 i = 1 while i <= n: if S[i]: count = count + 1 print (i, count) i = i + 1 try: pi(int(sys.argv[1])) except: print('usage:', sys.argv[0], '<n>')
histogram
(download link: histogram.py)
#!/usr/bin/python3 # # This program reads a list of numbers from the standard input, with # one number per line, and prints a histogram corresponding to those # numbers. In this histogram, each number N is represented by a # line of N characters "#" # import sys if len(sys.argv) > 1: file = open(sys.argv[1], 'r') else: file = sys.stdin for line in file: for i in range(int(line)): sys.stdout.write('#') sys.stdout.write('\n')
vertical histogram
(download link: vertical_histogram.py)
#!/usr/bin/python3 # # This program reads a list of numbers from the standard input, with # one or more numbers per line, and prints a vertical histogram # corresponding to those numbers. In this histogram, each number N is # represented by a column of N characters "#" starting from a # base-line of N dash characters "-" representing value 0. Positive # numbers are represented by a column above zero while negative # numbers are represented with a column below zero. # def v_histogram(A): top = 0 bottom = 0 for a in A: if a > top: top = a elif a < bottom: bottom = a i = top while i > 0: for a in A: if a >= i: print('#',end='') else: print(' ',end='') print() i = i - 1 for a in A: print('-',end='') print() while i > bottom: i = i - 1 for a in A: if a <= i: print('#',end='') else: print(' ',end='') print() import sys X = [] f = open(sys.argv[1]) for l in f: for n in l.split(): X.append(int(n)) v_histogram(X)
compress
(download link: compress.py)
# The general idea is to scan the given sequence $A$ looking for # subsequences of identical consecutive elements. If the subsequence # consists of one or two elements, then we simply print those element # one by one, otherwise we print the element followed by the count. We # can do this with a linear scan of $A$. # Tactically, we can proceed in a number of ways. One simple and quite # elegant way of doing that is to use two position indexes, $i$ and $j$, # with $i<j$, where position $i$ indicates the /first/ element of the # sequence, and $j$ indicates the last element. In fact, it is even # more convenient to use $j$ to indicate the the first element /past/ # the sequence, meaning the first element that differs from the elements # of the sequence and therefore that terminates the sequence. # Notice that $j$ can be the position of an element, or it can be the # first position past the last element of the whole sequence. def compress(A): i = 0 while i < len(A): j = i + 1 while j < len(A) and A[j] == A[i]: j = j + 1 if j - i <= 2: for _ in range(j - i): print(A[i]) else: print(A[i],'*',j - i) i = j import sys A = [] for l in sys.stdin: for a in l.strip().split(): A.append(a) compress(A)
longest identical sequence
(download link: longest_identical.py)
#!/usr/bin/python3 import sys A = [] for l in sys.stdin: for a in l.split(): A.append(int(a)) if len(A) >= 1: i = 0 j = 1 best = A[0] best_len = 1 while j < len(A): if A[i] != A[j]: i = j j = j + 1 if j - i > best_len: best = A[i] best_len = j - i print(best)
commonword
(download link: commonword.py)
#!/usr/bin/python3 # # This program reads a text file from the standard input, and prints # the most common word in the input. The words in the input are the # maximal-length sequences of alphabetic characters (e.g., a-z). So, # a word does not include spaces or punctuation characters. # import sys def line_to_words(line): words = [] w = '' for c in line: if c.isalpha(): w += c else: if not w == '': words.append(w) w = '' if not w == '': words.append(w) return words D = {} for l in sys.stdin: for w in line_to_words(l): if w in D: D[w] += 1 else: D[w] = 1 most_common = None max_freq = 0 for w in D: if D[w] > max_freq: most_common = w max_freq = D[w] print(most_common)
character frequencies
(download link: character_freq.py)
#!/usr/bin/python3 # # This program reads a text file from the standard input, and prints # the list of all characters present in the input followed by the # number of times the character appears in the input. # import sys freq = {} for line in sys.stdin: for c in line: if c in freq: freq[c] = freq[c] + 1 else: freq[c] = 1 for c, f in freq.items(): print(c, f)
character frequencies 2
(download link: character_freq2.py)
#!/usr/bin/python3 # # This program reads a text file from the standard input, and prints # the list of all characters present in the input followed by the # number of times the character appears in the input. The output is # sorted in reverse order of frequency, from the highest to the lowest # frequency count. # import sys freq = {} for line in sys.stdin: for c in line: if c in freq: freq[c] = freq[c] + 1 else: freq[c] = 1 sorted_freq = list(freq.items()) for i in range(1,len(sorted_freq)): j = i while j > 0 and sorted_freq[j][1] > sorted_freq[j-1][1]: sorted_freq[j], sorted_freq[j-1] = sorted_freq[j-1], sorted_freq[j] j = j - 1 for c, f in sorted_freq: print(c, f)
word frequencies
(download link: word_freqs.py)
#!/usr/bin/python3 # # This program reads a text file from the standard input and prints # the list of all the words in the text file, each followed by the # number of times the word occurs in the text. Words in the input are # the maximal-length sequences of alphabetic characters (e.g., a-z). # So, a word does not include spaces or punctuation characters. # import sys import string def line_to_words(line): words = [] w = '' for c in line: if c.isalpha(): w += c else: if not w == '': words.append(w) w = '' if not w == '': words.append(w) return words freqs = {} for line in sys.stdin: for word in line_to_words(line): if word in freqs: freqs[word] = freqs[word] + 1 else: freqs[word] = 1 for c, f in freqs.items(): print(c, f)
shortest least common word
(download link: shortest_least_frequent_word.py)
#!/usr/bin/python3 # # A program that reads a list of words from the standard input, with # one word per line, and prints any one of the shortest words that # appear least often. # import sys D = {} for w in sys.stdin: w = w.strip() if w in D: D[w] += 1 else: D[w] = 1 min_v = None min_len_w = None for k,v in D.items(): if min_v == None: min_v = v min_len_w = k elif v < min_v: min_v = v min_len_w = k elif v == min_v and len(k) < len(min_len_w): min_len_w = k print(min_len_w)
largest cluster
(download link: largest_cluster.py)
#!/usr/bin/python3 # # this program reads a list of numbers from the standard input, with # one or more numbers per line separated by spaces on each line, and # prints the largest cluster of extension D. The parameter D is a # number that may be given as the first command-line argument. If the # parameter is not specified, the default value is D=10. A cluster of # extension D is a list of all the elements taken from the input list # that are within a distance of at most D from each other. For # example, if the input sequence is 12, 2, 34, 7, 21, 24, 50, 45, -9, # 7, 45, and if D=10, then the output should contain the numbers 12, # 2, 7, 7 because those numbers form a cluster of extension 10, and no # other cluster of extension 10 contains more than 4 elements. # import sys A = [] for l in sys.stdin: for n in l.split(' '): A.append(int(n.strip())) try: D = int(sys.argv[1]) except: D = 10 max_c = [] for a in A: c = [] for b in A: if b >= a and b - a <= D: c.append(b) if len(c) > len(max_c): max_c = c for x in max_c: print(x, end=' ') print()
count inversions
(download link: count_inversions.py)
#!/usr/bin/python3 # # import sys def count_inversions_trivial(A): x = 0 for i in range(1,len(A)): for j in range(i): if A[j] > A[i]: x += 1 return x def count_inversions(A): if len(A) < 2: return 0 m = len(A)//2 Aleft = A[:m] # O(n) Aright = A[m:] # O(n) count = count_inversions(Aleft) + count_inversions(Aright) i = 0 j = 0 k = 0 while i < len(Aleft) or j < len(Aright): if i >= len(Aleft) or (j < len(Aright) and Aright[j] < Aleft[i]): A[k] = Aright[j] j += 1 k += 1 count += len(Aleft)-i else: A[k] = Aleft[i] i += 1 k += 1 return count A = [] for l in sys.stdin: for n in l.split(): A.append(int(n)) print(count_inversions(A))
roman numeral
(download link: roman_numeral.py)
#!/usr/bin/python3 # # This program that takes a number N (a positive integer) in decimal # notation from the console, and prints its value as a roman numeral. # ten_zero = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'] ten_one = ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'] ten_two = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'] n = int(input('input a number: ')) r = '' while n >= 1000: r = r + 'M' n = n - 1000 c = n // 100 r = r + ten_two[c] n = n - c*100 d = n // 10 r = r + ten_one[d] n = n - d*10 r = r + ten_zero[n] print(r)
prime factors
(download link: prime_factors.py)
#!/usr/bin/python3 import sys if len(sys.argv) > 1: n = int(sys.argv[1]) else: n = int(input('give me a number: ')) i = 2 while i * i <= n: if n % i == 0: c = 1 n = n // i while n % i == 0: c += 1 n = n // i if c > 1: sys.stdout.write(str(i) + '^' + str(c) + ' ') else: sys.stdout.write(str(i) + ' ') i += 1 if n > 1: sys.stdout.write(str(n)) sys.stdout.write('\n')
check sudoku
(download link: check_sudoku.py)
#!/usr/bin/python3 # import sys # checks whether V contains a permutation of the integers between 1 # and 9. For example, V = [ 3, 2, 1, 4, 5, 6, 9, 8, 7 ] => True but # V = [ 3, 2, 1, 4, 5, 6, 9, 2, 7 ] => False def perm9(V): F = [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] for x in V: if x < 1 or x > 9 or F[x-1] != 0: return False else: F[x-1] = 1 for x in F: if x == 0: return False return True # returns a list of the elements of the 3-by-3 submatrix of S whose # upper-left corner is at position (x,y) within S def submatrix(S, x, y): return S[x][y:y+3] + S[x+1][y:y+3] + S[x+2][y:y+3] # returns the column at position X within S def column(S, x): c = [] for row in S: c.append(row[x]) return c def row(S, x): return S[x] S = [] for line in sys.stdin: l = [] for x in line.split(): l.append(int(x)) S.append(l) for i in range(9): if not perm9(row(S,i)): print("Wrong") print("row", i) sys.exit(1) for i in range(9): if not perm9(column(S,i)): print("Wrong") print("column", i) sys.exit(1) for i in range(0,9,3): for j in range(0,9,3): if not perm9(submatrix(S,i,j)): print("Wrong") print("submatrix", i, j) sys.exit(1) print("Correct")
maze
Random Maze
(download link: random_maze.py)
#!/usr/bin/python3 import sys import random # MazeChars='\u2572\u2571' MazeChars = '\\/' for j in range(0, 20): for i in range(0, 60): sys.stdout.write(random.choice(MazeChars)) sys.stdout.write('\n')
Maze Solver
(download link: maze_solver.py)
#!/usr/bin/python3 import sys import random NW='\\' NE='/' L = [] Width=-1 for line in sys.stdin: sys.stdout.write(line) line = line.strip() L.append(line) if Width == -1: Width = len(line) elif Width != len(line): sys.stdout.write(' bad line length!\n') Height = len(L) WalkRules = { 'S' : { NE : 'W', NW : 'E' }, 'N' : { NE : 'E', NW : 'W' }, 'E' : { NE : 'N', NW : 'S' }, 'W' : { NE : 'S', NW : 'N' } } for x in range(0,Width): y = 0 dir = 'S' path=[(x,y)] while x >= 0 and x < Width and y >= 0 and y < Height: wall = L[y][x] dir = WalkRules[dir][wall] if dir == 'N': y = y - 1 elif dir == 'S': y = y + 1 elif dir == 'E': x = x + 1 elif dir == 'W': x = x - 1 path.append((x,y)) if (y == Height): break; if (y == Height): sys.stdout.write('Solution:\n') for j in range(0, Height): for i in range(0, Width): if (i,j) in path: sys.stdout.write(L[j][i]) else: sys.stdout.write(' ') sys.stdout.write('\n') else: sys.stdout.write('No solution!\n')
partition
(download link: partition_simple.py)
#!/usr/bin/python3 # this program takes a number N as a command-line parameter and # prints all the *partitions* of N # # a partition of a positive number N is a set of positive numbers that # add up to N. For example, { 3, 2, 2 } is a partition of 7. # Also, for example, all the partitions of N=4 are: # # 4 # 3 1 # 2 2 # 2 1 1 # 1 1 1 1 # # P contains a lists of numbers and represents a previously computed # partition, say of a number X. n is the value of which we want to # find all partitions. For each one of these partitions Q, the # function partition() adds Q to P and prints the list, that is, a # partition of n+X. # # The key idea to partition n is to compose a non-increasing list of # numbers, which is intended to avoid repeating the same partition. # # Thus partition(n, limit, P) partitions n in parts that are not # greater than limit. # def partition(n, limit, P): # ASSERT(n >= limit) while limit > 0: P.append(limit) remainder = n - limit if remainder > limit: partition(remainder, limit, P) else: if remainder == 0: for n in P: print(n,end=' ') print() else: partition(remainder, remainder, P) del P[-1] limit -= 1 import sys if len(sys.argv) != 2: sys.stderr.write('usage: ' + sys.argv[0] + ' <num>\n') exit(1) N = int(sys.argv[1]) partition(N, N, [])
fifteen
(download link: fifteen.py)
#!/usr/bin/python3 import random initial_position = [ ' 1', ' 2', ' 3', ' 4', ' 5', ' 6', ' 7', ' 8', ' 9', '10', '11', '12', '13', '14', '15', ' ' ] def display(cells): for i in range(0,16): if i % 4 == 0: print('+--+--+--+--+') print('|' + cells[i] + '|' + cells[i+1] + '|' + cells[i+2] + '|' + cells[i+3] + '|') print('+--+--+--+--+') def find(cells, s): for i in range(0, 16): if cells[i].strip() == s.strip(): return i return -1 def nsew_pos(pos): res = [] x = pos % 4 y = pos // 4 if x > 0: res.append(pos - 1) if x < 3: res.append(pos + 1) if y > 0: res.append(pos - 4) if y < 3: res.append(pos + 4) return res def equal_to_initial_position(cells): for i in range(0, 16): if cells[i] != initial_position[i]: return False return True def switch(cells, pos): x = find(cells,pos) if x < 0: print('invalid cell') else: y = find(cells,' ') if y in nsew_pos(x): cells[x], cells[y] = cells[y], cells[x] cells = [] # initialize the state of the game cells += initial_position random.shuffle(cells) # shuffle while not equal_to_initial_position(cells): display(cells) pos = input('switch? ') switch(cells,pos)
tree
(download link: tree.py)
#!/usr/bin/python3 import sys import random RootPrefix="•" Vertical="│" LeafWithOther="├" SingleLeaf="└" WithChildren="┬" WithoutChildren="─" class Node: def __init__(self, name): self.name = name self.parent = None self.children = set() def set_parent(self, parent): if self.parent != None: self.parent.children.remove(self) self.parent = parent self.parent.children.add(self) def print_indentation(self, prefix): sys.stdout.write(prefix + self.name + '\n') for c in self.children: c.print_indentation(prefix + ' ') def print_simple(self, prefix): sys.stdout.write(prefix[0:-1] + '+-' + self.name + '\n') l = list(self.children) for i in range(0, len(l)): if i < len(l) - 1: l[i].print_simple(prefix + ' |') else: l[i].print_simple(prefix + ' ') def print_pretty(self, prefix, prefix2): l = list(self.children) if len(l) == 0: sys.stdout.write(prefix + prefix2 + WithoutChildren + self.name + '\n') else: sys.stdout.write(prefix + prefix2 + WithChildren + self.name + '\n') if prefix2 == LeafWithOther: new_prefix = prefix + Vertical else: new_prefix = prefix + ' ' for i in range(0, len(l)-1): l[i].print_pretty(new_prefix, LeafWithOther) if (len(l) > 0): l[-1].print_pretty(new_prefix, SingleLeaf) def print_tree(self, format): if format == 'indentation': self.print_indentation('') elif format == 'simple': self.print_simple('') else: self.print_pretty('', RootPrefix) def read_tree_from_child_parent_list(): nodes = {} roots = Node("") for line in sys.stdin: child_name, parent_name = line.split() if parent_name not in nodes: parent = Node(parent_name) nodes[parent_name] = parent parent.set_parent(roots) else: parent = nodes[parent_name] if child_name not in nodes: child = Node(child_name) nodes[child_name] = child else: child = nodes[child_name] child.set_parent(parent) return roots def read_file_system_tree(): nodes = {} roots = Node("") for child_name in sys.stdin: child_name = child_name.rstrip('\n') parent_name, separator, basename = child_name.rpartition('/') # print(child_name + '(' + basename + ') -> ' + parent_name) if parent_name not in nodes: parent_basename = parent_name.rpartition('/')[2] parent = Node(parent_basename) nodes[parent_name] = parent parent.set_parent(roots) else: parent = nodes[parent_name] if child_name not in nodes: child = Node(basename) nodes[child_name] = child else: child = nodes[line] child.set_parent(parent) return roots # R = read_tree_from_child_parent_list() R = read_file_system_tree() formats = sys.argv[1:] if formats == []: formats = [ 'indentation', 'simple', 'pretty' ] for f in formats: for r in R.children: r.print_tree(f)
maxlines
(download link: maxlines.py)
#!/usr/bin/python3 import sys M = [] maxlen = 0 for l in sys.stdin: if len(l) > maxlen: maxlen = len(l) M = [ l ] elif len(l) == maxlen: M.append(l) for l in M: sys.stdout.write(l)
program-x
(download link: find_a_square.py)
#!/usr/bin/python3 import sys P = [] for l in sys.stdin: point_str = l.split(' ') x = int(point_str[0]) y = int(point_str[1]) P.append((x, y)) def points_lt(p,q): return (p[0] < q[0] or (p[0] == q[0] and p[1] < q[1])) def points_le(p,q): return (p[0] < q[0] or (p[0] == q[0] and p[1] <= q[1])) def partition(A, begin, end): pivot = A[end - 1] q = begin for i in range(begin+1, end-1): if points_le(A[i], pivot): A[i], A[q] = A[q], A[i] q += 1 A[end-1], A[q] = A[q], A[end-1] return q def quick_sort_r(A, begin, end): if (end > begin + 1): # if we are looking at more than one element q = partition(A, begin, end) quick_sort_r(A, begin, q) quick_sort_r(A, q+1, end) def quick_sort(A): quick_sort_r(A, 0, len(A)) def binary_search(A, k, begin, end): while begin < end: middle = (end + begin - 1) // 2 if A[middle] == k: return True elif points_lt(A[middle], k): begin = middle + 1 else: end = middle return False quick_sort(P) def vec_diff(x,y): return (x[0]-y[0], x[1]-y[1]) def vec_rot_90(x): return (x[1],-x[0]) N = len(P) for i in range(1,N): for j in range(i): p = P[i] q = P[j] pq = vec_diff(q,p) if pq[0] < 0 and pq[1] >= 0 or pq[0] >= 0 and pq[1] < 0: continue if pq[0] < 0 and pq[1] < 0: p, q = q, p pq = vec_diff(q,p) # must be pq[0] >= 0 and pq[1] >= 0 ort = vec_rot_90(pq) r = vec_diff(p, ort) s = vec_diff(q, ort) if binary_search(P, r, 0, N) and binary_search(P, s, 0, N): print(p, q, r, s)
tst
(download link: tst.py)
#!/usr/bin/python3 # # this program reads a set of words from the standard input, then it # inserts them into a ternary search trie (TST) and then prints the # TST # # For example, with this input: # # lugano # ciao # lunatic # cappero # algorithms # algo # altro # altrove # allegro # ciaa # math # matrix # # the output should be: # # /a=l=g=o*r=i=t=h=m=s* # / \ /l=e=g=r=o* # / \t=r=o*v=e* # / /a=p=p=e=r=o* # / / /a* # /c=i=a=o* # l=u=g=a=n=o* # \ \n=a=t=i=c* # \m=a=t=h* # \r=i=x* # import sys class TSTNode: """represents a node in a ternary search trie""" def __init__(self,c): self.c = c self.is_key = False self.equal = None self.left = None self.right = None def tst_chain(k, pos): prev = None res = None for i in range(pos, len(k)): n = TSTNode(k[i]) if prev != None: prev.equal = n prev = n if res == None: res = n n.is_key = True return res def tst_insert(t,k): if t == None: return tst_chain(k,0) root = t i = 0 while True: if k[i] > t.c: if t.right == None: t.right = tst_chain(k,i) return root else: t = t.right elif k[i] < t.c: if t.left == None: t.left = tst_chain(k,i) return root else: t = t.left else: if i >= len(k)-1: t.is_key = True return root if t.equal == None: t.equal = tst_chain(k,i+1) return root else: i = i + 1 t = t.equal def tst_add_from_file(t,f): for l in f: k = l.strip() if k != '': t = tst_insert(t, k) return t def tst_print_left(prefix,t): if t == None: return if t.left != None: prefix = prefix + ' /' tst_print(prefix, t.left) else: prefix = prefix + ' ' if t.equal != None: tst_print_left(prefix, t.equal) def tst_print_equal_right(prefix,t): if t == None: return sys.stdout.write(t.c) if (t.is_key): sys.stdout.write('*') else: sys.stdout.write('=') if t.right != None: prefix = prefix + ' \\' else: prefix = prefix + ' ' if t.equal != None: tst_print_equal_right(prefix, t.equal) else: sys.stdout.write('\n') if t.right != None: tst_print(prefix, t.right) def tst_print(prefix, t): if t == None: return if len(prefix) > 1 and prefix[-1:] == '/': tst_print_left(prefix[:-1]+' ',t) else: tst_print_left(prefix,t) sys.stdout.write(prefix) if len(prefix) > 1 and prefix[-1:] == '\\': tst_print_equal_right(prefix[:-1]+' ',t) else: tst_print_equal_right(prefix,t) T = None T = tst_add_from_file(T, sys.stdin) tst_print('',T)
plusminus
(download link: plusminus.py)
#!/usr/bin/python3 # # This program reads a string of digits S as a command-line argument, # and inserts plus (+) and minus signs (-) in the sequence of digits # so as to create an expression that evaluates to zero. The program # should output a resulting expression, if one such expression exists, # or "None" if no such expression exists. # # For example, if S is "201015900001", then the program could output # "+2+0+10+1-5-9+0+0+0+0+1". Instead, if S is "200015800001", then the # program should output "None". # # This program tends to produce long expressions (with many operands). # import sys def solve_puzzle(s, n): v = int(s) if v == n: return '+' + s if v == -n: return '-' + s if v < abs(n): return None for i in range(1,len(s)): front = s[0:i] back = s[i:] target = int(front) back_solution = solve_puzzle(back,n-target) if back_solution != None: return '+' + front + back_solution back_solution = solve_puzzle(back,n+target) if back_solution != None: return '-' + front + back_solution return None print(solve_puzzle(sys.argv[1],0))