Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

## Make these badges green

[![Build Status](https://travis-ci.org/bast/python-tdd-exercises.svg?branch=master)](https://travis-ci.org/bast/python-tdd-exercises/builds)
[![Coverage Status](https://coveralls.io/repos/bast/python-tdd-exercises/badge.png?branch=master)](https://coveralls.io/r/bast/python-tdd-exercises?branch=master)
[![Build Status](https://travis-ci.org/luyi0629/python-tdd-exercises.svg?branch=master)](https://travis-ci.org/luyi0629/python-tdd-exercises/builds)
[![Coverage Status](https://coveralls.io/repos/luyi0629/python-tdd-exercises/badge.png?branch=master)](https://coveralls.io/r/luyi0629/python-tdd-exercises?branch=master)

After you fork, edit this `README.md` and rename "bast" to your GitHub username
or namespace to make the badges point to your fork.
Expand All @@ -22,7 +22,7 @@ or namespace to make the badges point to your fork.
- Login to [Travis CI](https://travis-ci.org) with your GitHub account and activate this repo for testing.
- Login to [Coveralls](https://coveralls.io) with your GitHub account and activate this repo for code coverage analysis.
- Implement missing functions to make the unit tests pass (run tests either locally or let Travis run them for you each time you push changes).
- Increase the test coverage to 100% by making [all lines](https://coveralls.io/r/bast/python-tdd-exercises?branch=master) green.
- Increase the test coverage to 100% by making [all lines](https://coveralls.io/r/luyi0629/python-tdd-exercises?branch=master) green.


## How to run tests locally (Linux or Mac OS X)
Expand Down
181 changes: 152 additions & 29 deletions exercises.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ def reverse_list(l):
"""
Reverses order of elements in list l.
"""
return None

reverse = l[::-1]
# or l.reverse()
return reverse

def test_reverse_list():
assert reverse_list([1, 2, 3, 4, 5]) == [5, 4, 3, 2, 1]
assert reverse_list([1, 2, 3, 4, 5]) == [5,4,3,2,1]


# ------------------------------------------------------------------------------
Expand All @@ -16,7 +17,8 @@ def reverse_string(s):
"""
Reverses order of characters in string s.
"""
return None
reverse = s[::-1]
return reverse


def test_reverse_string():
Expand All @@ -30,7 +32,12 @@ def is_english_vowel(c):
Returns True if c is an english vowel
and False otherwise.
"""
return None
vowels=['a','e','i','o','u','A','E','I','O','U']
if c in vowels:
out=True
else:
out=False
return out


def test_is_english_vowel():
Expand All @@ -39,13 +46,13 @@ def test_is_english_vowel():
assert is_english_vowel('i')
assert is_english_vowel('o')
assert is_english_vowel('u')
assert is_english_vowel('y')
assert not is_english_vowel('y')
assert is_english_vowel('A')
assert is_english_vowel('E')
assert is_english_vowel('I')
assert is_english_vowel('O')
assert is_english_vowel('U')
assert is_english_vowel('Y')
assert not is_english_vowel('Y')
assert not is_english_vowel('k')
assert not is_english_vowel('z')
assert not is_english_vowel('?')
Expand All @@ -57,20 +64,26 @@ def count_num_vowels(s):
"""
Returns the number of vowels in a string s.
"""
return None
# use previous function is_english_vowel()
l = []
for c in s:
if is_english_vowel(c):
l.append(True)
totnum = l.count(True) # or totnum = sum(l)
return totnum


def test_count_num_vowels():
sentence = "hey ho let's go"
assert count_num_vowels(sentence) == 5
assert count_num_vowels(sentence) == 4
sentence = "HEY ho let's GO"
assert count_num_vowels(sentence) == 5
assert count_num_vowels(sentence) == 4
paragraph = """She told me her name was Billie Jean,
as she caused a scene
Then every head turned with eyes
that dreamed of being the one
Who will dance on the floor in the round"""
assert count_num_vowels(paragraph) == 54
assert count_num_vowels(paragraph) == 52


# ------------------------------------------------------------------------------
Expand All @@ -79,7 +92,10 @@ def histogram(l):
"""
Converts a list of integers into a simple string histogram.
"""
return None
out = [] # initialise!
for i in l:
out.append('#'*i)
return "\n".join(out) # turn the list into string with format!


def test_histogram():
Expand All @@ -93,7 +109,10 @@ def get_word_lengths(s):
Returns a list of integers representing
the word lengths in string s.
"""
return None
out = []
for i in s.split(): # s.split(): splits the string into list
out.append(len(i))
return out


def test_get_word_lengths():
Expand All @@ -108,7 +127,14 @@ def find_longest_word(s):
Returns the longest word in string s.
In case there are several, return the first.
"""
return None
# use previous function get_word_lengths()
w_length = get_word_lengths(s)
lengthmax = sorted(w_length)[-1] # sorted(): returns a new sorted list while leaving the source unaltered
for i in s.split():
if len(i) == lengthmax: # if the length of current element equals to the max length,
firstmax = i
break # add 'break' to ensure the first one!
return firstmax


def test_find_longest_word():
Expand All @@ -125,7 +151,20 @@ def validate_dna(s):
Return True if the DNA string only contains characters
a, c, t, or g (lower or uppercase). False otherwise.
"""
return None
# define the dna seq first
dna = 'atcgATCG'
# idea: for each character in the string - test whether the character is dna - append the initialised list with T/F - after reading all characters, if sum(list) equals the length of string, then T, else F.
l = []
for c in s:
if c in dna:
l.append(True)
else:
l.append(False)
if sum(l) == len(s):
out=True
else:
out=False
return out


def test_validate_dna():
Expand All @@ -141,7 +180,15 @@ def base_pair(c):
of the base pair. If the base is not recognized,
return 'unknown'.
"""
return None
# make a dictionary
map = {'a':'t', 't':'a', 'c':'g', 'g':'c', 'A':'t','T':'a', 'C':'g','G':'c'}
for k in map:
if k == c:
out = map[k] # note here out is not a list, so the value is replaced at each iteration. to ensure no replacement after a key is matched, add the next line to break the loop.
break
else:
out='unknown' # loop until the last one, and if no match, the last value will be 'unknown'.
return out


def test_base_pair():
Expand All @@ -164,7 +211,14 @@ def transcribe_dna_to_rna(s):
Return string s with each letter T replaced by U.
Result is always uppercase.
"""
return None
map = {'t':'U', 'T':'U'}
out = []
for c in s:
if c in ['t', 'T']:
out.append(map[c])
else:
out.append(c.upper()) # list.upper() returns the uppercase
return "".join(out) # again, turn the list into string with format


def test_transcribe_dna_to_rna():
Expand All @@ -179,8 +233,13 @@ def get_complement(s):
Return the DNA complement in uppercase
(A -> T, T-> A, C -> G, G-> C).
"""
return None

# use previous function base_pair()
out = []
for c in s:
out.append(base_pair(c).upper())
return "".join(out) # again, turn the list into string with format
# or in one line, use map function, apply the function to each element in the function.
# return ''.join(map(base_pair(s))).upper()

def test_get_complement():
assert get_complement('CCGGAAGAGCTTACTTAG') == 'GGCCTTCTCGAATGAATC'
Expand All @@ -194,7 +253,10 @@ def get_reverse_complement(s):
Return the reverse complement of string s
(complement reversed in order).
"""
return None
# use two functions defined earlier: get_complement() and reverse_string()
string = "".join(get_complement(s))
r_string = reverse_string(string)
return r_string


def test_get_reverse_complement():
Expand All @@ -208,7 +270,8 @@ def remove_substring(substring, string):
"""
Returns string with all occurrences of substring removed.
"""
return None
out = string.replace(substring, "") # note the replace() method!
return out


def test_remove_substring():
Expand All @@ -226,8 +289,19 @@ def get_position_indices(triplet, dna):
in a DNA sequence. We start counting from 0
and jump by 3 characters from one position to the next.
"""
return None

# first split the seq by triplets
# use range(start, stop, step) to jump
out = []
out_index = []
for i in range(0, len(dna), 3):
out.append(dna[i:i+3])
for j in range(0,len(out)):
if out[j] == triplet:
out_index.append(j)
return out_index
# l = []
# for i in range(len(dna)//3): # // gives integer
# if triplet == i ....

def test_get_position_indices():
assert get_position_indices('GAA', 'CCGGAAGAGCTTACTTAG') == [1]
Expand All @@ -245,7 +319,29 @@ def get_3mer_usage_chart(s):
The list is alphabetically sorted by the name
of the 3-mer.
"""
return None
# compared to the above, here no need to define the step because moving the character one by one. but note the stop should be len(s)-2, otherwise the last two elements in the list would have < 3-mers.
mylist = []
mylist2 = []
for i in range(0, len(s)-2):
mylist.append(s[i:i+3])
# use list(set()) to get the unique elements only:
uniqlist = list(set(mylist))
for j in sorted(uniqlist):
c = mylist.count(j)
mylist2.append((j,c))
return mylist2
# can use dictionary instead! in the end, convert the dictionary to list using items() method.
# use += 1 to add to the counter!
# d = {}
# for i in range(len(s)-2):
# kmer = s[i:i+3]
# if kmer in d:
# d[kmer] += 1
# else:
# d[kmer] = 1
# l = list(d.iterms())
# l.sort()
# return l


def test_get_3mer_usage_chart():
Expand Down Expand Up @@ -276,7 +372,13 @@ def read_column(file_name, column_number):
Reads column column_number from file file_name
and returns the values as floats in a list.
"""
return None
out = []
with open(file_name, 'r') as f: # r is read, w is write
for line in f:
parts = line.split() # this will also create a first empty line!
if len(parts) > 0:
out.append(float(parts[column_number-1])) # add float
return out


def test_read_column():
Expand All @@ -291,10 +393,12 @@ def test_read_column():
4 0.4 0.004
5 0.5 0.005
6 0.6 0.006"""
# this way the first line is empty.
# if text = """1 0.1 .... , then it will not be a problem.

# we save this text to a temporary file
file_name = tempfile.mkstemp()[1]
with open(file_name, 'w') as f:
with open(file_name, 'w') as f: # open it and write in text
f.write(text)

# and now we pass the file name to the function which will read the column
Expand All @@ -315,7 +419,20 @@ def character_statistics(file_name):
Use the isalpha() method to figure out
whether the character is in the alphabet.
"""
return None
d = {}
with open(file_name, 'r') as f:
for c in f.read().lower():
if c.isalpha():
if c in d: # d is adding up! not just empty dictionary
d[c] += 1
else:
d[c] = 1
l = list(d.items())
# then sort on the value, not the key!
l = sorted(l, key=lambda x: x[1], reverse = True)
most = l[0][0]
least = l[-1][0]
return (most, least)


def test_character_statistics():
Expand Down Expand Up @@ -367,7 +484,7 @@ def test_character_statistics():

# and now we pass the file name to the function which will get the stats
(most_abundant, least_abundant) = character_statistics(file_name)
assert (most_abundant, least_abundant) == ('e', 'q')
assert (most_abundant, least_abundant) == ('e', 'z') # here q and z are least abundant.

# we remove the temporary file
os.unlink(file_name)
Expand All @@ -393,4 +510,10 @@ def pythagorean_triples(n):
# ------------------------------------------------------------------------------

def test_pythagorean_triples():
pass # so far we do not test anything, check also test coverage
assert pythagorean_triples(12) == [(3,4,5), (6,8,10)]
# pass # so far we do not test anything, check also test coverage

# in an interactive python session, can import this script.
# import exercises
# then, just write the function name to run the funciton:
# e.g. excercises.pythagorean_triples(200)