I have a problem with below design. I am looking for a vectorized solution for below circular reference problem. Value (calculated by func1) uses the content from number (calculated by func2), number gets increased by Value afterwards and everything will be produced in a dataframe via build().
class test(object):
def __init__(self, bool, start=100):
self.start = start
self.bool = bool
self.value = self.func1()
self.number = self.func2()
def func1(self):
if bool==True:
value = **`here value from func2`**/ 2
else:
value = 0
return value
def func2(self):
number = start + self.value
return number
def build(self):
df = pd.DataFrame()
df['bool'] = self.bool
df['value']= self.value
df['number'] = self.number
so in the end the dataframe should look like this:
bool = pd.Series([False, True, False, True, False,.....])
bool value number
Index
0 False 0 100
1 True 50 100
2 False 0 150
3 True 75 150
4 False 0 225
my question is: how can I create this with classes and separate methods for value and number without iteration? The problem is that value depends on numberand vice versa (circular reference).
EDIT: although not modeled in this way here the number could be a cash account and value a certain number of shares that can be bought depending on the account size. account size then increases/decreases based on what happened to the shares. The main difficulty how to define the formula used for number (the account). you have a starting value but then in needs to increase depending on the future. but if you write like:
number = start + self.value ((which are the proceeds/results of other columns))
It does not work in the first row because the self.value does not yet exist. therefore I used the term circular reference.
Based on what you describe, I think you are trying to implement some sorts of class which construct the list "dynamically". While I think it is better to separate the task into two: one is form the DataFrame; second is to update it.
Below is my implementation of the class to form the DataFrame based on a Bool array and the values.
class test(object):
def __init__(self, _bool, v, start=100):
self._bool = _bool
self.v = v
self.df = pd.DataFrame()
self.vout = []
self.start = start
self.contruct()
def contruct(self):
i=0
for b in self._bool:
if b:
self.vout.append(self.v[i])
i += 1
else:
self.vout.append(0)
def build(self):
self.df['bool']=self._bool
self.df['value']= self.vout
self.df['sum'] = self.df['value'].cumsum() + self.start
return self.df
_bool = pd.Series([False, True, False, True, False])
_v = [50, 75]
a = test(_bool, _v)
df= a.build()
print df
Out[48]:
bool value sum
0 False 0 100
1 True 50 150
2 False 0 150
3 True 75 225
4 False 0 225
FYI, when you define the attribute, you shouldn't use bool as it is python reversed namespace and will cause confusion to interpreter as well as to people who read you code.
Related
I would like to implement the str method to nicely format the string representation of the matrix: one line per row, two characters per number (%2d) and a space between numbers. For example:
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
print(m)
1 0 0
0 1 0
0 0 1
I've tried this:
class Matrix:
def __init__(self, rows):
self.rows = rows
def __str__(self):
for element in self.rows:
for i in element:
print(i, end=" ")
print()
But my output becomes
1 2 3
4 5 6
7 8 9
None
How would I solve this? Because the none shouldn't be there.
The __str__ method has to return a string, not print it.
What you are seeing is:
The prints inside of __str__.
The return value of __str__, which is None.
To correct it, build a string in __str__ and return it.
class Matrix:
def __init__(self, rows):
self.rows = rows
def read(self):
for element in self.rows:
for i in element:
print(i, end=" ")
print('\n')
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
m.read()
You Should use something like this. Creating a new function to represent your data is good practice than trying to use the __str__ method to do your job. because you might need to handle other edge cases explicitly
Output:
1 0 0
0 1 0
0 0 1
Note: This way you can remove None at the end as well
because The first is inside function and the second is outside function. When a function doesn't return anything, it implicitly returns None.
Maybe you could do it like this?
class Matrix:
def __init__(self, rows):
self.rows = np.array(rows)
def __str__(self):
return "\n".join(np.array2string(row)[1:-1] for row in self.rows)
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
print(m)
Notice that we here convert rows to to a 2d numpy array first. If you want to avoid numpy for some reason, you can do this.
class Matrix:
def __init__(self, rows):
self.rows = rows
def __str__(self):
return '\n'.join(' '.join(map(str, row)) for row in self.rows)
m = Matrix([[1,0,0],[0,1,0],[0,0,1]])
print(m)
I'm writing an Iterator class that generate all possible ID numbers.
the issue is that I need it to print all 9 digit numbers including the ones that starts with 0 for example: 000000001 000000002 ect.
I need the output as a number and not a string, is there a way to do it?
my code:
class IDIterator:
def __init__(self):
self._id = range(000000000, 1000000000)
self._next_id = 000000000
def __iter__(self):
return self
def __next__(self):
self._next_id += 1
if self._next_id == 999999999:
raise StopIteration
return self._next_id
ID = iter(IDIterator())
print(next(ID))
print(next(ID))
print(next(ID))
output = 1
2
3
..
Python has a built in string function which will perform the left-padding of zeros
>>> before = 1
>>> after = str(before).zfill(9)
000000001
>>> type(after)
<class 'str'>
If you need the ID returned as an integer number with leading zeros preserved, I don't believe there's a way to do what you're looking for--the primitive Python type simply does not support this type of representation. Another strategy would be to store the ID's as normal integers and format with leading zeros when you need to display something to the user.
def format_id(string, length=9):
return str(string).zfill(length)
Here is my python code:
class Solution():
def isPalindrome(self):
return str(self.x) == str(self.x)[::-1]
s1 = Solution()
s1.x = 121
s1.isPalindrome()
It checks to see if the input is a palindrome. I want to create a new object that has the x value 121 and when I execute the isPalindrom function, I want it to return either a true or false boolean answer.
Currently when I run this program, nothing gets outputted. I am a bit lost as to where to go from here, would appreciate help.
Just print out the return value of isPalindrome(), because if you have a line with only a return value (this case being a boolean), the compiler won't know what to do with it.
class Solution():
def isPalindrome(self):
return str(self.x) == str(self.x)[::-1]
s1 = Solution()
s1.x = 121
print(s1.isPalindrome())
You're not telling the program to print anything. Try using print to make it reveal the answer.
Along with printing results we can also make class more pythonic.
class Solution:
def __init__(self):
self.input = None
def is_palindrome(self):
if isinstance(self.input, str):
return self.input == self.input[::-1]
print("Error: Expects str input")
return False # or leave blank to return None
s1 = Solution()
print(s1.is_palindrome())
s1.input = "121"
print(s1.is_palindrome())
output
Error: Expects str input
False
True
The main idea here is divide number. let's take number 122. First of all you need store it in a variable, in this case r_num. While loop is used and the last digit of the number is obtained by using the modulus operator %. The last digit 2 is then stored at the one’s place, second last at the ten’s place and so on. The last digit is then removed by truly dividing the number with 10, here we use //. And lastly the reverse of the number is then compared with the integer value stored in the temporary variable tmp if both are equal, the number is a palindrome, otherwise it is not a palindrome.
def ispalindrom(x):
r_num = 0
tmp = x
while tmp > 0:
r_num = (r_num * 10) + tmp % 10
tmp = tmp // 10
if x == r_num:
return True
return False
The problem is a homework problem. I think I solved it but I'm wondering is it the best solution? The problem is to take a list and run through it to see if it contains a specific subsequence: 007. Here subsequence is used in the mathematical sense (so 0110227 does contain 007 and returns True).
def spy_game(nums):
if 0 in nums:
a_1=nums.index(0)
nums_1=nums[a_1+1:]
if 0 in nums_1:
a_2=nums_1.index(0)
if 7 in nums[a_2+1:]:
return True
else:
return False
else:
return False
else:
return False
Start by negating your test condition so you can simply return early. The last test doesn't require an if statement at all, since by that point the result of the condition is the return value of the function.
def spy_game(nums):
if 0 not in nums:
return False
a_1 = nums.index(0)
nums_1 = nums[a_1+1:]
if 0 not in nums_1:
return False
a_2 = nums_1.index(0)
return 7 in nums[a_2+1:]
If you negate your inclusion conditions you can return early rather than introducing further nesting.
def spy_game(nums):
if 0 not in nums:
return False
a_1 = nums.index(0)
num_1 = nums[a_1+1:]
if 0 not in nums_1:
return False
a_2 = nums_1.index(0)
return 7 in nums_1[a_2+1:]
You can also write this without creating any copies of the list by using the start parameter to the index method, which will tell the index method the index at which to start searching for the element. This code looks different but achieves the same thing and may be easier to maintain for you.
def spy_game(nums):
try:
start = 0
for n in [0, 0, 7]:
start = nums.index(n, start)
return True
except ValueError:
return False
It's better to design your functions so that they don't depend on the specific input. For example:
def contains_anywhere(s, search):
i = 0
for c in search:
try:
i = s.index(c, i) + 1
except ValueError:
return False
return True
ok = contains_anywhere([0,1,1,0,2,2,7,2], [0,0,7])
Just another option, I personally don't see an issue with the nesting here.
This is shortening it up:
def spy_game(nums):
if 0 in nums:
nums_1 = nums[nums.index(0)+1:]
if 0 in nums_1:
if 7 in nums[nums_1.index(0)+1:]:
return True
return False
output:
>>> spy_game([1,0,7])
False
>>> spy_game([0,1,7])
False
>>> spy_game([1,0,1])
False
>>> spy_game([0,0,7])
True
Your code hides what you are trying to do. Try this alternative. even though it still has 3 levels of nesting, it is clearer about what it is doing:
def spy_game(nums):
search_for = [x for x in "007"]
for n in nums:
if not search_for: # found everything we were looking for
return True
if n == search_for[0]: # found the next item
search_for.pop(0)
return False
I want to have a number that breaks into 2 other numbers and checks for end conditions, breaking off each number until the conditions are met.
I came up with the following example to try to figure it out. Take a number, and break it into 2 more numbers: one is the original number multiplied by 2 and the other number is the original number divided by 3 without a remainder (//). This continues until a number is either greater than 100, equal to 6, or a square.
I want to record every chain that is made to be returned and printed out at the end. I can only do this by checking the second number in a chain currently and am not clever enough to figure out how to check both numbers. I want a new chain to be created every time the number is broken into 2 new numbers.
Currently, here is what I have:
import numpy as np
def check_conditions(number):
if number > 100:
return False
if number == 6:
return False
if np.sqrt(number) % 1 == 0:
return False
return True
def find_decay(number):
'''
Rule: Number is broken into two chains. First chain is
mulitplied by 2. Seconds chain is // 3. Same thing happens
to both chains unless end condition is met:
1. number is greater than 100
2. number is equal to 6
3. number is a perfect square
'''
master_chain = []
while check_conditions(number):
new_chain1 = [number * 2]
master_chain.append(new_chain1)
new_chain2 = [number // 3]
master_chain.append(new_chain2)
number = new_chain2[-1]
return master_chain
if __name__ == '__main__':
print find_decay(int(raw_input('Number: ')))
Does anyone have any ideas of ways to check conditions in a while loop for 2 separate numbers like?
This sort of problem typically lends itself to trees and/or recursion. However, the rate at which you're spawning new work is quite high compared to the rate at which you're going to satisfy the conditions. (ie while it won't take too many operations to exceed 100 for one product of each value, but low chances of finding a perfect square or exactly 6 on either fork)
Therefore, you'll want to set a max recursion depth for your implementation else you'll come up against the interpreter's limit (sys.getrecursionlimit()) and fail ugly.
I've provided a simple example of how you might do it below, recursively building a tree.
This is not particularly efficient though, and if you are interested in very long 'chains' then you may need to consider addressing this another way.
import sys
import numpy as np
class Node(object):
def __init__(self,number,parent):
self._parent = parent
self._number = number
self._satisfied = number > 100 or number == 6 or np.sqrt(number) % 1 == 0
self._left = None
self._right = None
self._depth = parent.depth + 1 if parent != None else 1
#property
def parent(self):
return self._parent
#property
def number(self):
return self._number
#property
def satisfied(self):
return self._satisfied
#property
def depth(self):
return self._depth
#property
def left(self):
return self._left
#left.setter
def left(self,value):
self._left = value
#property
def right(self):
return self._right
#right.setter
def right(self,value):
self._right = value
def print_all_chains(node,chain=[]):
if node.left is None:
chain.append(node.number)
print '{0}: {1}'.format(node.satisfied, chain)
else:
print_all_chains(node.left, chain[:] + [node.number])
print_all_chains(node.right, chain[:] + [node.number])
def build_tree(node, maxDepth):
if not node.satisfied and node.depth<maxDepth:
node.left = Node(node.number*2, node)
build_tree(node.left,maxDepth)
node.right = Node(node.number//3, node)
build_tree(node.right,maxDepth)
def find_decay(number):
root = Node(number,None)
build_tree(root,maxDepth=10)
print_all_chains(root)
if __name__ == '__main__':
find_decay(int(raw_input('Number: ')))
Using a simple Node class, this can give you an idea of the tree structure. This traverses the tree in level-order (which guarantees to find the shortest chain):
from collections import deque
import numpy as np
def check_conditions(number):
return number > 100 or number == 6 or np.sqrt(number) % 1 == 0
class Node():
def __init__(self, value, parent=None):
self.value, self.parent = value, parent
def chain(self):
node = self
while node:
yield node.value
node = node.parent
def find_decay(number):
agenda = deque([Node(number)])
while agenda:
node = agenda.popleft() # use pop() for depth-first
num = node.value
if check_conditions(num):
return list(node.chain())
agenda.append(Node(num//3, parent=node))
agenda.append(Node(num*2, parent=node))
if __name__ == '__main__':
for x in find_decay(int(raw_input('Number: '))):
print x,
37: 37 12 4