updated from Atlas repo

This commit is contained in:
Luciano Ramalho
2014-12-14 01:26:42 -02:00
parent dcd59eef31
commit 33d65dc590
21 changed files with 359 additions and 299 deletions

View File

@@ -8,9 +8,9 @@ Arithmetic progression class
""" """
import array
from collections import abc from collections import abc
class ArithmeticProgression: class ArithmeticProgression:
def __init__(self, begin, step, end): def __init__(self, begin, step, end):
@@ -29,7 +29,8 @@ class ArithmeticProgressionIterator(abc.Iterator):
self._index = 0 self._index = 0
def __next__(self): def __next__(self):
result = self._ap.begin + self._ap.step * self._index first = type(self._ap.begin + self._ap.step)(self._ap.begin)
result = first + self._ap.step * self._index
if result < self._ap.end: if result < self._ap.end:
self._index += 1 self._index += 1
return result return result

View File

@@ -0,0 +1,35 @@
"""
Arithmetic progression generator function.
This is almost correct. The only problem is that the first
item in the series may not be of the same type as the rest,
an this may be important to the user::
>>> ap = aritprog_gen(1, .5, 3)
>>> list(ap)
[1, 1.5, 2.0, 2.5]
>>> ap = aritprog_gen(0, 1/3, 1)
>>> list(ap)
[0, 0.3333333333333333, 0.6666666666666666]
>>> from fractions import Fraction
>>> ap = aritprog_gen(0, Fraction(1, 3), 1)
>>> list(ap)
[0, Fraction(1, 3), Fraction(2, 3)]
>>> from decimal import Decimal
>>> ap = aritprog_gen(0, Decimal('.1'), .3)
>>> list(ap)
[0, Decimal('0.1'), Decimal('0.2')]
"""
# BEGIN ALMOST_ARITPROG_ITERTOOLS
import itertools
def aritprog_gen(begin, step, end=None):
ap_gen = itertools.count(begin, step)
if end is not None:
ap_gen = itertools.takewhile(lambda n: n < end, ap_gen)
return ap_gen
# END ALMOST_ARITPROG_ITERTOOLS

31
iterables/aritprog.rst Normal file
View File

@@ -0,0 +1,31 @@
===========================================
Tests for arithmetic progression generators
===========================================
Tests with built-in numeric types::
>>> ap = aritprog_gen(1, .5, 3)
>>> list(ap)
[1.0, 1.5, 2.0, 2.5]
>>> ap = aritprog_gen(0, 1/3, 1)
>>> list(ap)
[0.0, 0.3333333333333333, 0.6666666666666666]
Tests with standard library numeric types::
>>> from fractions import Fraction
>>> ap = aritprog_gen(0, Fraction(1, 3), 1)
>>> list(ap)
[Fraction(0, 1), Fraction(1, 3), Fraction(2, 3)]
>>> from decimal import Decimal
>>> ap = aritprog_gen(0, Decimal('.1'), .3)
>>> list(ap)
[Decimal('0'), Decimal('0.1'), Decimal('0.2')]
Test producing an empty series::
>>> ap = aritprog_gen(0, 1, 0)
>>> list(ap)
[]

View File

@@ -0,0 +1,26 @@
"""
Demonstrate difference between Arithmetic Progression calculated
as a series of increments accumulating errors versus one addition
and one multiplication.
"""
from fractions import Fraction
from aritprog_v0 import ArithmeticProgression as APv0
from aritprog_v1 import ArithmeticProgression as APv1
if __name__ == '__main__':
ap0 = iter(APv0(1, .1))
ap1 = iter(APv1(1, .1))
ap_frac = iter(APv1(Fraction(1, 1), Fraction(1, 10)))
epsilon = 10**-10
iteration = 0
delta = next(ap0) - next(ap1)
frac = next(ap_frac)
while abs(delta) <= epsilon:
delta = next(ap0) - next(ap1)
frac = next(ap_frac)
iteration +=1
print('iteration: {}\tfraction: {}\tepsilon: {}\tdelta: {}'.
format(iteration, frac, epsilon, delta))

View File

@@ -0,0 +1,37 @@
import doctest
import importlib
import glob
TARGET_GLOB = 'aritprog*.py'
TEST_FILE = 'aritprog.rst'
TEST_MSG = '{0:16} {1.attempted:2} tests, {1.failed:2} failed - {2}'
def main(argv):
verbose = '-v' in argv
for module_file_name in sorted(glob.glob(TARGET_GLOB)):
module_name = module_file_name.replace('.py', '')
module = importlib.import_module(module_name)
gen_factory = getattr(module, 'ArithmeticProgression', None)
if gen_factory is None:
gen_factory = getattr(module, 'aritprog_gen', None)
if gen_factory is None:
continue
test(gen_factory, verbose)
def test(gen_factory, verbose=False):
res = doctest.testfile(
TEST_FILE,
globs={'aritprog_gen': gen_factory},
verbose=verbose,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
tag = 'FAIL' if res.failed else 'OK'
print(TEST_MSG.format(gen_factory.__module__, res, tag))
if __name__ == '__main__':
import sys
main(sys.argv)

24
iterables/aritprog_v0.py Normal file
View File

@@ -0,0 +1,24 @@
"""
Arithmetic progression class
>>> ap = ArithmeticProgression(1, .5, 3)
>>> list(ap)
[1.0, 1.5, 2.0, 2.5]
"""
class ArithmeticProgression:
def __init__(self, begin, step, end=None):
self.begin = begin
self.step = step
self.end = end # None -> "infinite" series
def __iter__(self):
result = type(self.begin + self.step)(self.begin)
forever = self.end is None
while forever or result < self.end:
yield result
result += self.step

View File

@@ -1,48 +1,44 @@
""" """
Arithmetic progression class Arithmetic progression class
# BEGIN ARITPROG_CLASS_DEMO
>>> ap = ArithmeticProgression(0, 1, 3)
>>> list(ap)
[0, 1, 2]
>>> ap = ArithmeticProgression(1, .5, 3) >>> ap = ArithmeticProgression(1, .5, 3)
>>> list(ap) >>> list(ap)
[1.0, 1.5, 2.0, 2.5] [1.0, 1.5, 2.0, 2.5]
>>> ap = ArithmeticProgression(0, 1/3, 1)
>>> list(ap)
[0.0, 0.3333333333333333, 0.6666666666666666]
>>> from fractions import Fraction
>>> ap = ArithmeticProgression(0, Fraction(1, 3), 1)
>>> list(ap)
[Fraction(0, 1), Fraction(1, 3), Fraction(2, 3)]
>>> from decimal import Decimal
>>> ap = ArithmeticProgression(0, Decimal('.1'), .3)
>>> list(ap)
[Decimal('0.0'), Decimal('0.1'), Decimal('0.2')]
# END ARITPROG_CLASS_DEMO
""" """
import array
from collections import abc
# BEGIN ARITPROG_CLASS
class ArithmeticProgression: class ArithmeticProgression:
def __init__(self, begin, step, end): def __init__(self, begin, step, end=None): # <1>
self.begin = begin self.begin = begin
self.step = step self.step = step
self.end = end self.end = end # None -> "infinite" series
self._build()
def _build(self):
self._numbers = array.array('d')
n = self.begin
while n < self.end:
self._numbers.append(n)
n += self.step
def __iter__(self): def __iter__(self):
return ArithmeticProgressionIterator(self._numbers) result = type(self.begin + self.step)(self.begin) # <2>
forever = self.end is None # <3>
index = 0
class ArithmeticProgressionIterator(abc.Iterator): while forever or result < self.end: # <4>
yield result # <5>
def __init__(self, series): index += 1
self._series = series result = self.begin + self.step * index # <6>
self._index = 0 # END ARITPROG_CLASS
def __next__(self):
if self._index < len(self._series):
item = self._series[self._index]
self._index += 1
return item
else:
raise StopIteration

View File

@@ -1,32 +1,31 @@
""" """
Arithmetic progression class Arithmetic progression generator function::
>>> ap = ArithmeticProgression(1, .5, 3) >>> ap = aritprog_gen(1, .5, 3)
>>> list(ap) >>> list(ap)
[1.0, 1.5, 2.0, 2.5] [1.0, 1.5, 2.0, 2.5]
>>> ap = aritprog_gen(0, 1/3, 1)
>>> list(ap)
[0.0, 0.3333333333333333, 0.6666666666666666]
>>> from fractions import Fraction
>>> ap = aritprog_gen(0, Fraction(1, 3), 1)
>>> list(ap)
[Fraction(0, 1), Fraction(1, 3), Fraction(2, 3)]
>>> from decimal import Decimal
>>> ap = aritprog_gen(0, Decimal('.1'), .3)
>>> list(ap)
[Decimal('0.0'), Decimal('0.1'), Decimal('0.2')]
""" """
import array
from collections import abc
class ArithmeticProgression: # BEGIN ARITPROG_GENFUNC
def aritprog_gen(begin, step, end=None):
def __init__(self, begin, step, end): result = type(begin + step)(begin)
self.begin = begin forever = end is None
self.step = step index = 0
self.end = end while forever or result < end:
self._build() yield result
index += 1
def _build(self): result = begin + step * index
self._numbers = array.array('d') # END ARITPROG_GENFUNC
n = self.begin
while n < self.end:
self._numbers.append(n)
n += self.step
def __iter__(self):
for item in self._numbers:
yield item
return StopIteration

View File

@@ -1,27 +1,11 @@
""" # BEGIN ARITPROG_ITERTOOLS
Arithmetic progression class import itertools
>>> ap = ArithmeticProgression(1, .5, 3)
>>> list(ap)
[1.0, 1.5, 2.0, 2.5]
""" def aritprog_gen(begin, step, end=None):
first = type(begin + step)(begin)
import array ap_gen = itertools.count(first, step)
from collections import abc if end is not None:
ap_gen = itertools.takewhile(lambda n: n < end, ap_gen)
class ArithmeticProgression: return ap_gen
# END ARITPROG_ITERTOOLS
def __init__(self, begin, step, end=None):
self.begin = float(begin)
self.step = float(step)
self.end = end # None -> "infinite" series
def __iter__(self):
result = self.begin
forever = self.end is None
while forever or result < self.end:
yield result
result += self.step
raise StopIteration

View File

@@ -1,29 +1,14 @@
""" # BEGIN ARITPROG_ITERTOOLS
Arithmetic progression class import itertools
>>> ap = ArithmeticProgression(1, .5, 3)
>>> list(ap)
[1.0, 1.5, 2.0, 2.5]
""" def aritprog_gen(begin, step, end=None):
if end is not None and begin >= end:
import array return
from collections import abc yield type(begin + step)(begin)
tail_gen = itertools.count(begin+step, step)
class ArithmeticProgression: if end is not None:
tail_gen = itertools.takewhile(lambda n: n < end, tail_gen)
def __init__(self, begin, step, end=None): for x in tail_gen:
self.begin = begin yield x
self.step = step # END ARITPROG_ITERTOOLS
self.end = end # None -> "infinite" series
def __iter__(self):
result = type(self.step)(self.begin)
forever = self.end is None
index = 0
while forever or result < self.end:
yield result
index += 1
result = self.begin + self.step * index
raise StopIteration

13
iterables/aritprog_v5.py Normal file
View File

@@ -0,0 +1,13 @@
# BEGIN ARITPROG_ITERTOOLS
import itertools
def aritprog_gen(begin, step, end=None):
if end is not None and begin >= end:
return
yield type(begin + step)(begin)
tail_gen = itertools.count(begin+step, step)
if end is not None:
tail_gen = itertools.takewhile(lambda n: n < end, tail_gen)
yield from tail_gen
# END ARITPROG_ITERTOOLS

54
iterables/sentence.rst Normal file
View File

@@ -0,0 +1,54 @@
==============================
Tests for a ``Sentence`` class
==============================
A ``Sentence`` is built from a ``str`` and allows iteration
word-by-word.
::
>>> s = Sentence('The time has come')
>>> s
Sentence('The time has come')
>>> list(s)
['The', 'time', 'has', 'come']
>>> it = iter(s)
>>> next(it)
'The'
>>> next(it)
'time'
>>> next(it)
'has'
>>> next(it)
'come'
>>> next(it)
Traceback (most recent call last):
...
StopIteration
Any punctuation is skipped while iterating::
>>> s = Sentence('"The time has come," the Walrus said,')
>>> s
Sentence('"The time ha... Walrus said,')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']
White space including line breaks are also ignored::
>>> s = Sentence('''"The time has come," the Walrus said,
... "To talk of many things:"''')
>>> s
Sentence('"The time ha...many things:"')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said', 'To', 'talk', 'of', 'many', 'things']
Accented Latin characters are also recognized as word characters::
>>> s = Sentence('Agora vou-me. Ou me vão?')
>>> s
Sentence('Agora vou-me. Ou me vão?')
>>> list(s)
['Agora', 'vou', 'me', 'Ou', 'me', 'vão']

View File

@@ -1,40 +0,0 @@
>>> from sentence_gen import Sentence
>>> s = Sentence('The time has come')
>>> s
Sentence('The time has come')
>>> list(s)
['The', 'time', 'has', 'come']
>>> it = iter(s)
>>> next(it)
'The'
>>> next(it)
'time'
>>> next(it)
'has'
>>> next(it)
'come'
>>> next(it)
Traceback (most recent call last):
...
StopIteration
>>> s = Sentence('"The time has come," the Walrus said,')
>>> s
Sentence('"The time ha... Walrus said,')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']
>>> s = Sentence('''"The time has come," the Walrus said,
... "To talk of many things:"''')
>>> s
Sentence('"The time ha...many things:"')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said', 'To', 'talk', 'of', 'many', 'things']
>>> s = Sentence('Agora vou-me. Ou me vão?')
>>> s
Sentence('Agora vou-me. Ou me vão?')
>>> list(s)
['Agora', 'vou', 'me', 'Ou', 'me', 'vão']

View File

@@ -12,12 +12,14 @@ class Sentence:
def __init__(self, text): def __init__(self, text):
self.text = text self.text = text
self.words = RE_WORD.findall(text)
def __repr__(self): def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text) return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self): def __iter__(self):
for match in RE_WORD.finditer(self.text): # <1> for word in self.words: # <1>
yield match.group() # <2> yield word # <2>
return # <3>
# done! <3> # done! <4>

View File

@@ -0,0 +1,21 @@
"""
Sentence: iterate over words using a generator function
"""
import re
import reprlib
RE_WORD = re.compile('\w+')
class Sentence:
def __init__(self, text):
self.text = text # <1>
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
for match in RE_WORD.finditer(self.text): # <2>
yield match.group() # <3>

View File

@@ -1,40 +0,0 @@
>>> from sentence_genexp import Sentence
>>> s = Sentence('The time has come')
>>> s
Sentence('The time has come')
>>> list(s)
['The', 'time', 'has', 'come']
>>> it = iter(s)
>>> next(it)
'The'
>>> next(it)
'time'
>>> next(it)
'has'
>>> next(it)
'come'
>>> next(it)
Traceback (most recent call last):
...
StopIteration
>>> s = Sentence('"The time has come," the Walrus said,')
>>> s
Sentence('"The time ha... Walrus said,')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']
>>> s = Sentence('''"The time has come," the Walrus said,
... "To talk of many things:"''')
>>> s
Sentence('"The time ha...many things:"')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said', 'To', 'talk', 'of', 'many', 'things']
>>> s = Sentence('Agora vou-me. Ou me vão?')
>>> s
Sentence('Agora vou-me. Ou me vão?')
>>> list(s)
['Agora', 'vou', 'me', 'Ou', 'me', 'vão']

View File

@@ -1,40 +0,0 @@
>>> from sentence_iter import Sentence
>>> s = Sentence('The time has come')
>>> s
Sentence('The time has come')
>>> list(s)
['The', 'time', 'has', 'come']
>>> it = iter(s)
>>> next(it)
'The'
>>> next(it)
'time'
>>> next(it)
'has'
>>> next(it)
'come'
>>> next(it)
Traceback (most recent call last):
...
StopIteration
>>> s = Sentence('"The time has come," the Walrus said,')
>>> s
Sentence('"The time ha... Walrus said,')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']
>>> s = Sentence('''"The time has come," the Walrus said,
... "To talk of many things:"''')
>>> s
Sentence('"The time ha...many things:"')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said', 'To', 'talk', 'of', 'many', 'things']
>>> s = Sentence('Agora vou-me. Ou me vão?')
>>> s
Sentence('Agora vou-me. Ou me vão?')
>>> list(s)
['Agora', 'vou', 'me', 'Ou', 'me', 'vão']

View File

@@ -22,10 +22,10 @@ class Sentence:
return 'Sentence(%s)' % reprlib.repr(self.text) return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self): # <1> def __iter__(self): # <1>
return SentenceIter(self.words) # <2> return SentenceIterator(self.words) # <2>
class SentenceIter: class SentenceIterator:
def __init__(self, words): def __init__(self, words):
self.words = words # <3> self.words = words # <3>

View File

@@ -1,40 +0,0 @@
>>> from sentence_iter2 import Sentence
>>> s = Sentence('The time has come')
>>> s
Sentence('The time has come')
>>> list(s)
['The', 'time', 'has', 'come']
>>> it = iter(s)
>>> next(it)
'The'
>>> next(it)
'time'
>>> next(it)
'has'
>>> next(it)
'come'
>>> next(it)
Traceback (most recent call last):
...
StopIteration
>>> s = Sentence('"The time has come," the Walrus said,')
>>> s
Sentence('"The time ha... Walrus said,')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']
>>> s = Sentence('''"The time has come," the Walrus said,
... "To talk of many things:"''')
>>> s
Sentence('"The time ha...many things:"')
>>> list(s)
['The', 'time', 'has', 'come', 'the', 'Walrus', 'said', 'To', 'talk', 'of', 'many', 'things']
>>> s = Sentence('Agora vou-me. Ou me vão?')
>>> s
Sentence('Agora vou-me. Ou me vão?')
>>> list(s)
['Agora', 'vou', 'me', 'Ou', 'me', 'vão']

View File

@@ -0,0 +1,36 @@
import doctest
import importlib
import glob
TARGET_GLOB = 'sentence*.py'
TEST_FILE = 'sentence.rst'
TEST_MSG = '{0:16} {1.attempted:2} tests, {1.failed:2} failed - {2}'
def main(argv):
verbose = '-v' in argv
for module_file_name in sorted(glob.glob(TARGET_GLOB)):
module_name = module_file_name.replace('.py', '')
module = importlib.import_module(module_name)
try:
cls = getattr(module, 'Sentence')
except AttributeError:
continue
test(cls, verbose)
def test(cls, verbose=False):
res = doctest.testfile(
TEST_FILE,
globs={'Sentence': cls},
verbose=verbose,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
tag = 'FAIL' if res.failed else 'OK'
print(TEST_MSG.format(cls.__module__, res, tag))
if __name__ == '__main__':
import sys
main(sys.argv)

View File

@@ -1,24 +0,0 @@
"""
Demonstrate difference between Arithmetic Progression calculated
as a series of increments accumulating errors versus one addition
and one multiplication.
"""
from fractions import Fraction
from aritprog_v3 import ArithmeticProgression as APv3
from aritprog_v4 import ArithmeticProgression as APv4
ap3 = iter(APv3(1, .1))
ap4 = iter(APv4(1, .1))
ap_frac = iter(APv4(Fraction(1, 1), Fraction(1, 10)))
epsilon = 10**-10
iteration = 0
delta = next(ap3) - next(ap4)
frac = next(ap_frac)
while abs(delta) <= epsilon:
delta = next(ap3) - next(ap4)
frac = next(ap_frac)
iteration +=1
print('iteration: {}\tfraction: {}\tepsilon: {}\tdelta: {}'.
format(iteration, frac, epsilon, delta))