Alternative to global variable - python

I got a recursive function, which reverses an integer. The reversed Integer can not start with zero, e.g.: 12340 becomes 4321.
res = 0
base = 1
def reverse(n):
global res
global base
if n > 0:
reverse(n // 10)
res = res + (n % 10) * base
base = base * 10
return res
this code works, but only once and hence I want to get rid of the global variables. I thought of a helper function, inside of the reverse(n) function, but I could not get it to work properly. I have tried for almost an hour and would love to see the solution eventually.

It's totally possible with a helper method:
def reverse_recursive(i: int) -> int:
def helper(i: int, result_up_to_now: int) -> int:
if i == 0:
return result_up_to_now
return helper(i // 10, result_up_to_now * 10 + (i % 10))
return helper(i, 0)
assert reverse_recursive(123456789) == 987654321
And even without one:
def reverse_recursive_nohelper(i: int, result_up_to_now=0) -> int:
if i == 0:
return result_up_to_now
return reverse_recursive_nohelper(i // 10, result_up_to_now * 10 + (i % 10))
assert reverse_recursive_nohelper(123456789) == 987654321
But the latter one could of course be misused/misunderstood by someone.
Just for comparison, the non-recursive version:
def reverse_straight(i: int) -> int:
result = 0
while i != 0:
result = result*10 + i % 10
i //= 10
return result
assert reverse_straight(123456789) == 987654321

global only on the agg_res variable for the result.
Anyway agg_res is reinitialized at the end of the calculation (no influence on the second re-use)
agg_res=0
def reverse(n, res=0, base=1):
global agg_res
ls = len(str(n))
if n > 0:
reverse(n // 10, res, base)
res = res + (n % 10)
base = base * (10**(ls-1))
agg_res += res*base
else :
agg_res=0
# First time
reverse(5786)
print(agg_res)
# 6875
# Second time
reverse(5786)
print(agg_res)
# 6875

Example of using a mutable argument to get rid of globals
def reverse(n, res_base = None):
if res_base is None:
res_base = [0, 1] # Use two element list for res, base
# res_base[0] -> res
# res_base[1] -> base
if n > 0:
reverse(n // 10, res_base)
# Update as in original code
# but replacing res & base with elements from list res_base
res_base[0] = (res_base[0] + (n%10)*res_base[1]) # res update
res_base[1] = res_base[1] * 10 # base update
return res_base[0]
Check that it works on multiple runs
print(reverse(12345)) # Output: 54321
print(reverse(6789)) # 9876
Alternative Using Helper Function
def reverse(n):
def helper(n, res, base):
if n > 0:
res, base = helper(n // 10, res, base)
res = res + (n % 10) * base
base = base * 10
return res, base
res, base = helper(n, 0, 1)
return res
print(reverse(12345)) # Output: 54321
print(reverse(6789)) # 9876
Shows Use of Mutable Argument
Use mutable argument removes need to pass update back to parent
def reverse(n):
def helper(n, res_base):
if n > 0:
helper(n//10, res_base)
res_base[0] += (n%10)*res_base[1] # Since res_base is mutable, it's parent will see the change in value
res_base[1] *= 10
res_base = [0, 1]
helper(n, res_base)
return res_base[0]
print(reverse(12345)) # Out: 54321

Related

binary search delete min

I am wondering in the following code,
In the code below i is set to min child, why is this done instead of say just having i = i*2. Both ways 'lower' the level of the binary heap, I am just curious as to why the minimum would be chosen (Assuming both children are NOT smaller than parent, why is the smaller of the two larger children chosen instead of one of them arbitrarily)
To be clear these methods below also belong to the binaryheap class
def percDown(self,i):
while (i * 2) <= self.currentSize:
mc = self.minChild(i)
if self.heapList[i] > self.heapList[mc]:
tmp = self.heapList[i]
self.heapList[i] = self.heapList[mc]
self.heapList[mc] = tmp
i = mc
def minChild(self,i):
if i * 2 + 1 > self.currentSize:
return i * 2
else:
if self.heapList[i*2] < self.heapList[i*2+1]:
return i * 2
else:
return i * 2 + 1
The code for the binary heap class is
class BinHeap:
def __init__(self):
self.heapList = [0]
self.currentSize = 0
def delMin(self):
retval = self.heapList[1]
self.heapList[1] = self.heapList[self.currentSize]
self.currentSize = self.currentSize - 1
self.heapList.pop()
self.percDown(1)
return retval

name " " is not defined

import math
EMPTY = '-'
def is_between(value, min_value, max_value):
""" (number, number, number) -> bool
Precondition: min_value <= max_value
Return True if and only if value is between min_value and max_value,
or equal to one or both of them.
>>> is_between(1.0, 0.0, 2)
True
>>> is_between(0, 1, 2)
False
"""
return value >= min_value and value <= max_value
# Students are to complete the body of this function, and then put their
# solutions for the other required functions below this function.
def game_board_full(cells):
""" (str) -> bool
Return True if no EMPTY in cells and else False
>>> game_board_full ("xxox")
True
>>> game_board_full ("xx-o")
False
"""
return "-" not in cells
def get_board_size (cells):
""" (str) -> int
Return the square root of the length of the cells
>>>get_board_size ("xxox")
2
>>>get_board_size ("xoxoxoxox")
3
"""
sqrt_cell= len(cells) ** 0.5
return int(sqrt_cell)
def make_empty_board (size):
""" (int) -> str
Precondition: size>=1 and size<=9
Return a string for storing information with the size
>>>make_empty_board (2)
"----"
>>>make_empty_board (3)
"---------"
"""
return "-" *size ** 2
def get_position (row_index,col_index,size):
""" (int,int,int) -> int
Precondition:size >=col_index and size >= row_index
Return the str_index of the cell with row_index,col_index and size
>>>get_position (2,2,4)
5
>>>get_position (3,4,5)
13
"""
str_index = (row_index - 1) * size + col_index - 1
return str_index
def make_move( symbol,row_index,col_index,game_board):
"""(str,int,int,str) -> str
Return the resultant game board with symbol,row_index,col_index and game_board
>>>make_move("o",1,1,"----")
"o---"
>>>make_move("x"2,3,"---------")
"-----x---"
"""
length=len(game_board)
size=len(cells) ** 0.5
str_index = (row_index - 1) * size + col_index - 1
return "-"*(str_index-1)+symbol+"-"*(length-str_index)
def extract_line (cells,direction,cells_num):
""" (str,str,int) -> str
Return the characters of a specified row with cells, direction and cells_num
>>>extract_line ("xoxoxoxox","across",2)
"oxo"
>>>extract_line ("xoxo","up_diagonal","-")
"xo"
"""
num=cells_num
s=cells
size= get_board_size (cells)
if direction=="across":
return s[(num-1)* size : num*size]
elif direction=="down":
return s[num-1:size **2:size]
elif direction=="up_diagonal":
return s[(size-1)*size:size-2:1-size]
elif direction=="down_diagonal":
return s[0:size*2:size+1]
NameError: name 'cells' is not defined
I don't know how to define cells because it is a parameter.
You have NO cells parameter in
def make_move( symbol,row_index,col_index,game_board):
Next time read the error message carefully so you know in which code line you have a problem.
I find that you have referred to the variable cells in your make_move function without declaration, maybe you should define it in the arguments list.
By the way, you MUST put up all your traceback or it's difficult for all of us to find out the problem.

Python: Why is my generator based range is X2 slower than xrange?

Just of curiosity, I've written 3 tests in Python and timed them out using timeit:
import timeit
# simple range based on generator
def my_range(start, stop):
i = start
while (i < stop):
yield i
i += 1
# test regular range
def test_range():
x = range(1, 100000)
sum = 0
for i in x:
sum += i
# test xrange
def test_xrange():
x = xrange(1, 100000)
sum = 0
for i in x:
sum += i
# test my range
def test_my_range():
x = my_range(1, 100000)
sum = 0
for i in x:
sum += i
print timeit.timeit("test_range()", setup = "from __main__ import test_range", number = 100)
print timeit.timeit("test_xrange()", setup = "from __main__ import test_xrange", number = 100)
print timeit.timeit("test_my_range()", setup = "from __main__ import test_my_range", number = 100)
And I've got these benchmarks:
regular range based test - 0.616795163262
xrange based test - 0.537716731096
my_range (generator) based test - **1.27872886337**
My range was X2 slower even than a range that creates a list. Why?
Are xrange() / range() implemented using C directly?
Are they implemented without condition check?
Thanks!
I feel that the simple answer is that xrange() is builtin and written in C.
I added another case to your test (see below): A pure-Python reference implementation of xrange() based on the CPython source.
import timeit
from collections import Sequence, Iterator
from math import ceil
# simple range based on generator
def my_range(start, stop):
i = start
while (i < stop):
yield i
i += 1
# test regular range
def test_range():
x = range(1, 100000)
sum = 0
for i in x:
sum += i
# test xrange
def test_xrange():
x = xrange(1, 100000)
sum = 0
for i in x:
sum += i
# test my range
def test_my_range():
x = my_range(1, 100000)
sum = 0
for i in x:
sum += i
class pure_python_xrange(Sequence):
"""Pure-Python implementation of an ``xrange`` (aka ``range``
in Python 3) object. See `the CPython documentation
<http://docs.python.org/py3k/library/functions.html#range>`_
for details.
"""
def __init__(self, *args):
if len(args) == 1:
start, stop, step = 0, args[0], 1
elif len(args) == 2:
start, stop, step = args[0], args[1], 1
elif len(args) == 3:
start, stop, step = args
else:
raise TypeError('pure_python_xrange() requires 1-3 int arguments')
try:
start, stop, step = int(start), int(stop), int(step)
except ValueError:
raise TypeError('an integer is required')
if step == 0:
raise ValueError('pure_python_xrange() arg 3 must not be zero')
elif step < 0:
stop = min(stop, start)
else:
stop = max(stop, start)
self._start = start
self._stop = stop
self._step = step
self._len = (stop - start) // step + bool((stop - start) % step)
def __repr__(self):
if self._start == 0 and self._step == 1:
return 'pure_python_xrange(%d)' % self._stop
elif self._step == 1:
return 'pure_python_xrange(%d, %d)' % (self._start, self._stop)
return 'pure_python_xrange(%d, %d, %d)' % (self._start, self._stop, self._step)
def __eq__(self, other):
return isinstance(other, xrange) and \
self._start == other._start and \
self._stop == other._stop and \
self._step == other._step
def __len__(self):
return self._len
def index(self, value):
"""Return the 0-based position of integer `value` in
the sequence this xrange represents."""
diff = value - self._start
quotient, remainder = divmod(diff, self._step)
if remainder == 0 and 0 <= quotient < self._len:
return abs(quotient)
raise ValueError('%r is not in range' % value)
def count(self, value):
"""Return the number of ocurrences of integer `value`
in the sequence this xrange represents."""
# a value can occur exactly zero or one times
return int(value in self)
def __contains__(self, value):
"""Return ``True`` if the integer `value` occurs in
the sequence this xrange represents."""
try:
self.index(value)
return True
except ValueError:
return False
def __reversed__(self):
"""Return an xrange which represents a sequence whose
contents are the same as the sequence this xrange
represents, but in the opposite order."""
sign = self._step / abs(self._step)
last = self._start + ((self._len - 1) * self._step)
return pure_python_xrange(last, self._start - sign, -1 * self._step)
def __getitem__(self, index):
"""Return the element at position ``index`` in the sequence
this xrange represents, or raise :class:`IndexError` if the
position is out of range."""
if isinstance(index, slice):
return self.__getitem_slice(index)
if index < 0:
# negative indexes access from the end
index = self._len + index
if index < 0 or index >= self._len:
raise IndexError('xrange object index out of range')
return self._start + index * self._step
def __getitem_slice(self, slce):
"""Return an xrange which represents the requested slce
of the sequence represented by this xrange.
"""
start, stop, step = slce.start, slce.stop, slce.step
if step == 0:
raise ValueError('slice step cannot be 0')
start = start or self._start
stop = stop or self._stop
if start < 0:
start = max(0, start + self._len)
if stop < 0:
stop = max(start, stop + self._len)
if step is None or step > 0:
return pure_python_xrange(start, stop, step or 1)
else:
rv = reversed(self)
rv._step = step
return rv
def __iter__(self):
"""Return an iterator which enumerates the elements of the
sequence this xrange represents."""
return xrangeiterator(self)
class xrangeiterator(Iterator):
"""An iterator for an :class:`xrange`.
"""
def __init__(self, xrangeobj):
self._xrange = xrangeobj
# Intialize the "last outputted value" to the value
# just before the first value; this simplifies next()
self._last = self._xrange._start - self._xrange._step
self._count = 0
def __iter__(self):
"""An iterator is already an iterator, so return ``self``.
"""
return self
def next(self):
"""Return the next element in the sequence represented
by the xrange we are iterating, or raise StopIteration
if we have passed the end of the sequence."""
self._last += self._xrange._step
self._count += 1
if self._count > self._xrange._len:
raise StopIteration()
return self._last
# test xrange
def test_pure_python_xrange():
x = pure_python_xrange(1, 100000)
sum = 0
for i in x:
sum += i
print timeit.timeit("test_range()", setup = "from __main__ import test_range", number = 100)
print timeit.timeit("test_xrange()", setup = "from __main__ import test_xrange", number = 100)
print timeit.timeit("test_my_range()", setup = "from __main__ import test_my_range", number = 100)
print timeit.timeit("test_pure_python_xrange()", setup = "from __main__ import test_pure_python_xrange", number = 100)
The results?
$ python so.py
0.426695823669
0.371111869812
0.964643001556
6.06390094757
This is simply the difference between interpreted Python code and C. Additionally, as #byels mentioned above, xrange() is limited to short integers, which likely has positive effect.
This is an interesting test. Looking at the python 2 docs on xrange, one guess that comes to mind is that xrange is alowed to take advantage of type restrictions (only uses "short" integers)

Python: using a custom number class or type

I am working with a custom number type which is best thought of as YearQuarter, (i.e. 20141, 20142, 20143, 20144, 20151, 20152, ...), or as I label it, quarter_code, q_code for short. Its incrementing function would be something like:
def code_sum(q_code, n):
q_code_year, q_code_quarter = q_code // 10, q_code % 10
n_year, n_quarter = (n // 4), (n % 4 - 1)
quarters = q_code_quarter + n_quarter
years = q_code_year + n_year + quarters // 4
return years * 10 + quarters % 4 + 1
# code_sum(20141, 1) = 20142, code_sum(20144, 1) = 20151
# code_sum(20144, -1) = 20143, code_sum(20151, -1) = 20144
# NOTE: code_sum(20147, 0) = 20153
I want to warn or raise exceptions for numbers which don't conform to the form year*10 + number_of_quarters. It easy to write and call a check function, but I'm wondering if constantly calling check is the best approach when using quarter_codes in many different functions. E.g.
def foo(qc1, qc2, qc3):
qc1, qc2, qc3 = check(qc1, qc2, qc3)
# do something
return bar
def foo2(qc, arg1, arg2) ...
qc = check(qc)
return 42
def fooN(qc1, qc2, arg1):
qc1, qc2 = check(qc1, qc2)
And so on. Here is a short check function as an example.
def check(*args):
checked = tuple()
for q_code in args:
if q_code % 10 > 4:
while q_code % 10 > 4:
q_code += 6
print('Number of quarters > 4. Using {}'.format(q_code))
checked += (q_code, )
else:
checked += (q_code, )
return checked[0] if len(checked) == 1 else checked
It seems a little laborious to create class YearQtr although maybe I am missing something here altogether. My question really boils to: how far should I go to creating a custom number class or type? And how would I do that?
I hope this can help you
class QuarterCode(object):
"""docstring for QuarterCode"""
#property
def value(self):
return self.__value;
#value.setter
def value(self, value):
assert 1 <= value%10 <=4, "Number of quarters differs from {1,2,3,4}"
self.__value = value
def __init__(self, value):
self.value = value
def code_sum(self, n):
q_code_year, q_code_quarter = self.value // 10, self.value % 10
n_year, n_quarter = (n // 4), (n % 4 - 1)
quarters = q_code_quarter + n_quarter
years = q_code_year + n_year + quarters // 4
self.value = years * 10 + quarters % 4 + 1
You can use this class as follows:
>>>q1 = QuarterCode(20142)
>>>q1.value
20142
>>>q1.code_sum(10)
20164
>>>q1.value = 20145
AssertionError: Number of quarters differs from {1,2,3,4}

list with infinite elments

I need to operate on two separate infinite list of numbers, but could not find a way to generate, store and operate on it in python.
Can any one please suggest me a way to handle infinite Arithmetic Progession or any series and how to operate on them considering the fact the minimal use of memory and time.
Thanks every one for their suggestions in advance.
You are looking for a python generator instead:
def infinitenumbers():
count = 0
while True:
yield count
count += 1
The itertools package comes with a pre-built count generator.
>>> import itertools
>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> for i in itertools.islice(c, 5):
... print i
...
2
3
4
5
6
This is where the iterator comes in. You can't have an infinite list of numbers, but you can have an infinite iterator.
import itertools
arithmetic_progression = itertools.count(start,step) #from the python docs
The docs for Python2 can be found here
I have another python3 solution (read SICP chapter 3.5)
class Stream:
def __init__(self, head, tail):
self.head = head
self.tail = tail
self.memory = None
self.isDone = False
def car(self):
return self.head
def cdr(self):
if self.isDone:
return self.memory
self.memory = self.tail()
self.isDone = True
return self.memory
def __getitem__(self, pullFrom):
if pullFrom < 1 or self.memory == []:
return []
return [self.car()] + self.cdr()[pullFrom - 1]
def __repr__(self):
return "[" + repr(self.car()) + " x " + repr(self.tail) + "]"
def map(self, func):
if self.memory == []:
return []
return Stream(func(self.car()), lambda: Stream.map(self.cdr(), func))
def from_list(lst):
if lst == []:
return []
return Stream(lst[0], lambda:
Stream.from_list(lst[1:]))
def filter(self, pred):
if self.memory == []:
return []
elif pred(self.car()):
return Stream(self.car(), lambda: Stream.filter(self.cdr(), pred))
else:
return self.cdr().filter(pred)
def sieve(self):
return Stream(self.car(), lambda: self.cdr().filter(lambda n: n % self.car() > 0).sieve())
def foreach(self, action, pull = None):
if pull is None:
action(self.car())
self.cdr().foreach(action, pull)
elif pull <= 0:
return
else:
action(self.car())
self.cdr().foreach(action, pull-1)and run:
a = Stream(0, lambda: a.map((lambda x: x + 1)))
print(a[10])
which returns:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] .
But streams are lazily evaluated, so:
>>> a = Stream(0, lambda: a.map((lambda x: x + 1)))
>>> print(a)
prints:
[0 x [...]]
To create an object that acts like a "mutable" infinite list, you can overload the __getitem__ and __setitem__ methods in a class:
class infinite_list():
def __init__(self, func):
self.func = func
self.assigned_items = {}
def __getitem__(self, key):
if key in self.assigned_items:
return self.assigned_items[key]
else:
return self.func(key)
def __setitem__(self, key , value):
self.assigned_items[key] = value
Then, you can initialize the "infinite list" with a lambda expression and modify an item in the list:
infinite_thing = infinite_list(lambda a: a*2)
print(infinite_thing[1]) #prints "2"
infinite_thing[1] = infinite_thing[2]
print(infinite_thing[1]) #prints "4"
Similarly, it is possible to create an "infinite dictionary" that provides a default value for each missing key.
Perhaps the natural way to generate an infinite series is using a generator:
def arith(a, d):
while True:
yield a
a += d
This can be used like so:
print list(itertools.islice(arith(10, 2), 100))
My solution is:
from hofs import *
def cons_stream(head,tail):
return [head,tail,False,False]
def stream_cdr(strm):
if strm[2]:
return strm[3]
strm[3] = strm[1]()
strm[2] = True
return strm[3]
def show_stream(stream, num = 10):
if empty(stream):
return []
if num == 0:
return []
return adjoin(stream[0], show_stream(stream_cdr(stream), num - 1))
def add_streams(a , b):
if empty(a):
return b
if empty(b):
return a
return cons_stream(a[0] + b[0] , lambda : add_streams( stream_cdr(a), stream_cdr(b)))
def stream_filter( pred , stream ):
if empty(stream):
return []
if pred(stream[0]):
return cons_stream(stream[0], lambda : stream_filter(pred, stream_cdr(stream)))
else:
return stream_filter( pred , stream_cdr( stream ))
def sieve(stream):
return cons_stream(stream[0] , lambda : sieve(stream_filter(lambda x : x % stream[0] > 0 , stream_cdr(stream))))
ones = cons_stream(1, lambda : ones)
integers = cons_stream(1, lambda : add_streams(ones, integers))
primes = sieve(stream_cdr(integers))
print(show_stream(primes))
Copy the Python code above.
When I tried it, i got [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] which is 10 of an infinite list of primes.
You need hofs.py to be
def empty(data):
return data == []
def adjoin(value,data):
result = [value]
result.extend(data)
return result
def map(func, data):
if empty(data):
return []
else:
return adjoin(func(data[0]), map(func, data[1:]))
def keep(pred, data):
if empty(data):
return []
elif pred(data[0]):
return adjoin( data[0] , keep(pred, data[1:]))
else:
return keep(pred, data[1:])
I assume you want a list of infinite numbers within a range. I have a similar problem, and here is my solution:
c = 0
step = 0.0001 # the difference between the numbers
limit = 100 # The upper limit
myInfList = []
while c <= limit:
myInfList.append(c)
c = c + step
print(myInfList)

Categories