Find category-of-4 for number starting at 2 - python-2.7

I'm tasked with categorizing numbers into groups with a range of four, starting at 2 (2, 6, 10, 14...). So for the number 9, the category would be 6 (between 6 and 10). I've developed the following function but I'm guessing there's a more efficient means and one that isn't limited in range.
>>> def FindCategory (num):
categories = [2]
lastVal = 2
for i in range (100):
lastVal = lastVal + 4
categories += [lastVal]
try:
return [cat for cat in categories if cat < num and num < cat + 4] [0]
except:
return
>>> FindCategory (56)
54
>>> FindCategory (99999999999999999999999999)
>>>

Just use math?
def category(n):
return (((n + 2) // 4) * 4) - 2
Examples:
>>> category(2)
2
>>> category(56)
54
>>> category(99)
98
>>> category(99999999999999999999999999)
99999999999999999999999998
By way of explanation: without the shift-by-2, you're just looking for the closest (lower) multiple of four, which can be found just by integer-division and then multiplication by 4 (i.e. (n//4)*4). The +2 and -2 account for the shift in your categories.

Related

In the PuLP scheduling problem, how to bring/group the consecutive Zeros together and still get an optimal solution? For meal breaks in the schedule

Solving an agent scheduling problem using PuLP.
8 hours of shift, 4 agents.
I have to generate an output where the 8 hrs of shift is divided into 15-minute intervals. Hence, 32 total periods. (the 15 minute periods of an 8 hour shift is a fixed input, which is not allowed to be tweaked.)
At any given period, there need to be a minimum of 3 agents working (i.e.not on break)
Now, there needs to be a 1 hour meal break, and a 30 min short break.
So, for 1 hour meal break, I will have to combine 4 periods of 15 mins, and for the 30 min short break, I'll have to combine 2 periods of 15 mins.
I tried getting 26 counts of 1... and, 6 counts of 0.
The idea was to then combine 4 zeros together (meal break), and the remaining 2 zeros together (short break).
The current LpStatus is 'infeasible'... if i remove the constraint where i am trying to club the zeros, then the solution is optimal, or else it shows infeasible.
Have also pasted my final dataframe output screenshots.
import pandas as pd
import numpy as np
import scipy as sp
import seaborn as sns
import matplotlib.pyplot as plt
from pandas.plotting import table
import os, sys, json
from pulp import *
%matplotlib inline
# agent works either 1, 2, 3, 4, 5, 6, 7, 8 hours per week.
working_periods = [26]
# maximum periods that agent will work (7 hrs in each shift)
max_periods = 26
# planning_length
planning_length = 1 # TODO: Total number of shifts i.e. 21 in our case
# Number of periods per shift:
daily_periods = [0, 1, 2, 3, 4, 5, 6, 7, 8,9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
# Label the days from Monday to Sunday.
s = ['Period']
# Create the required_agents dataframe
col_2 = range(0, 1*planning_length)
required_agents_per_period = pd.DataFrame(data = None, columns=s, index = daily_periods)
for j in col_2:
# Small number is better for visualization.
required_agents_per_period.iloc[0][j] = 3
required_agents_per_period.iloc[1][j] = 3
required_agents_per_period.iloc[2][j] = 3
required_agents_per_period.iloc[3][j] = 3
required_agents_per_period.iloc[4][j] = 3
required_agents_per_period.iloc[5][j] = 3
required_agents_per_period.iloc[6][j] = 3
required_agents_per_period.iloc[7][j] = 3
required_agents_per_period.iloc[8][j] = 3
required_agents_per_period.iloc[9][j] = 3
required_agents_per_period.iloc[10][j] = 3
required_agents_per_period.iloc[11][j] = 3
required_agents_per_period.iloc[12][j] = 3
required_agents_per_period.iloc[13][j] = 3
required_agents_per_period.iloc[14][j] = 3
required_agents_per_period.iloc[15][j] = 3
required_agents_per_period.iloc[16][j] = 3
required_agents_per_period.iloc[17][j] = 3
required_agents_per_period.iloc[18][j] = 3
required_agents_per_period.iloc[19][j] = 3
required_agents_per_period.iloc[20][j] = 3
required_agents_per_period.iloc[21][j] = 3
required_agents_per_period.iloc[22][j] = 3
required_agents_per_period.iloc[23][j] = 3
required_agents_per_period.iloc[24][j] = 3
required_agents_per_period.iloc[25][j] = 3
required_agents_per_period.iloc[26][j] = 3
required_agents_per_period.iloc[27][j] = 3
required_agents_per_period.iloc[28][j] = 3
required_agents_per_period.iloc[29][j] = 3
required_agents_per_period.iloc[30][j] = 3
required_agents_per_period.iloc[31][j] = 3
# List of number of agents required in specific periods
r_p = required_agents_per_period.values.swapaxes(0,1).ravel()
print("The number of agents required for each period is: ")
print (r_p)
print("Total no. of periods is: ", len(r_p))
print ("\nIn matrix form:")
print (required_agents_per_period)
# Total number of the agents
total = 4
print ("\nTotal number of agents are: {}".format(total))
# Create agents_id tag
agent_id_working_in_shift = ['agent7', 'agent10', 'agent13', 'agent18'] # TODO: Important: Here agent_id will be array of agents that will be extracted from dataframe.
print ("\nThe agents are: ")
print (agent_id_working_in_shift)
# Total periods
periods = range(1*32)
agents_per_shift = range(total)
## Create shift names based on index:
period_name = []
for p in periods:
period_name.append(s[0] + '_' + 'P' + str(p))
print("The periods are: ")
print(periods)
print("\nThe names of corresponding periods are: ")
print(period_name)
print("\nThe agents are: ")
print(agents_per_shift)
def LpProb():
# The prob variable is created to contain the problem data
prob = LpProblem("Agents Meal Scheduling Per Shift",LpMinimize)
# Creating the variables.
var = {
(n, p): pulp.LpVariable(
"schdule_{0}_{1}".format(n, p), cat = "Binary")
for n in agents_per_shift for p in periods
}
# add constraints:
for n in agents_per_shift:
for p in periods:
prob.addConstraint(var[(n,p)] <= 1)
# add constraints:
# Exactly 32 working periods per shift
for n in agents_per_shift:
prob.addConstraint(
sum(var[(n,p)] for p in periods) == 26
)
for n in agents_per_shift:
for p in periods:
if(p == periods[-1] or p == periods[-2] or p == periods[-3]):
continue
prob.addConstraint(var[(n,p)] + var[(n,p+1)] + var[(n,p+2)] + var[(n,p+3)] == 0)
# add constraints
# for each shift, the numbers of working agents should be greater than or equal to
# the required numbers of agents
for p in periods:
try:
prob.addConstraint(
sum(var[(n,p)] for n in agents_per_shift) >= 3
)
except:
print("len(periods) should be equal to len(agents_per_shift)")
sys.exit(-1)
prob.objective = sum(var[(n,p)] for n in agents_per_shift for p in periods)
return var, prob
# Run the solver
var, prob = LpProb()
prob.solve()
print(LpStatus[prob.status])
def agent_scheduling(var = var):
schedule = pd.DataFrame(data=None, index = agent_id_working_in_shift, columns = period_name)
for k, v in var.items():
n, p = k[0], k[1]
schedule.iloc[n][p] = int(value(v)) # pulp.value()
return schedule
schedule = agent_scheduling()
schedule.T
I was expecting an output of only zeros and one.
Want to combine four 0's as meal break, that need to be consecutive, and then a two 0's consecutive for short break (remaining 26 cells should be 1's)
Also, only 1 agent can be on a break (0), the other 3 agents needs to be working in that period (1)
OUTPUTS:-
enter image description here
enter image description here
enter image description here

How can I print output with a defined number of characters in each line with python?

I used textwrap.fill (textwrap.fill(text, 6)) to limit each line in only 6 characters, but there is a problem with using this command because my purpose is go to new line exact at 6 character, I mean:
for example using textwrap.fill(I am a student, 8):
what I want:
(I am a s
tudent)
output:
(I am a
student)
One approach:
>>> text = 'I am a student, 8'
>>> text = 'I am a student'
>>> for i in range(0, len(text), 8):
... print text[i:i+8]
...
I am a s
tudent
for i in range(0, len(text), 8) means "Give me numbers starting at 0, incrementing by 8 at a time, and ending before the length of the text."
EDIT
If you want the value in a single string:
>>> wrapped = "\n".join(text[i:i+8] for i in range(0, len(text), 8))
>>> wrapped
'I am a s\ntudent'

create multiple lists for a given test data in python

I am relatively new to python so please excuse me if this is a very rudimentary question. This is my first time asking question.
I have a test file which is of the format below.
1 2 4
1 3 2
1 4 1
2 1 2
2 2 1
2 3 1
3 2 3
3 7 1
4 1 1
....
I am trying to read the file line by line and for each value in column 1 (1, 2, 3...), i need to create a list of the form below
list_1 = [[2,4], [3,2], [4,1]]
list_2 = [[1,2], [2,1], [3,1]]
list_3 = [[2,3], [7,1]]
list_4 = [[1,1]]
...
list_n
where values in the list are from column 2 and column 3 respectively.
Sincerely appreciate any guidance in this regard. Thank you
Use a defaultdict. This way, you don't have to check if your key already exists in the dictionary.
from collections import defaultdict
def parse(filename):
result = defaultdict(list)
with open(filename) as infile:
for line in infile:
c1, c2, c3 = map(int, line.split())
result[c1].append([c2, c3])
return result
def main():
result = parse("test_data.txt")
print(result)
if __name__ == '__main__':
main()

One user input three different output in python, code does not work

In my homework a user is supposed to enter a number and display factorial,Fibonacci series and all cubed numbers up to the number entered by the user in Python, cannot figure out where is the problem
#!/Python27/python
def factorial( n ):
if n <1: # base case
return 1
else:
return n * factorial( n - 1 )
# recursive call
def fact(n):
for i in range(1, n+1 ):
print "%d" % ( factorial( i ) )
# write Fibonacci series up to n
def fib(n):
a, b = 0, 1
while b < n:
print b
a, b = b, a+b
def cube(n): return n*n*n
def cubes(n):
for i in range(1, n+1):
print "%d" % (cube(i))
def main():
nr = int(input("Enter a number: ")
factorial(nr)
fact(nr)
cubes(nr)
main()
The problem arises from you not having enough brackets:
def main():
nr = int(input("Enter a number: "))
...
You forgot the closing bracket for int()
To display the output in a table, I would to return a list from each function then in main do something like:
import itertools
print "Factorial up to {n}\tFibonacci of 1 to {n}\tCubes of 1 to {n}".format(n = nr)
print '\n'.join('\t'.join(map(str, seq)) for seq in itertools.izip_longest(factorial(nr), fib(nr), cubes(nr), fillvalue=''))
Now if each of the functions (respectively) returned the following lists:
>>> factorial(nr)=> [1, 2, 3, 4]
>>> fib(nr)=> [3, 4, 5, 6, 7]
>>> cubes(nr)=> [7, 453, 23, 676]
Using the above method will yield output like this:
Factorial up to -inf Fibonacci of 1 to -inf Cubes of 1 to -inf
1 3 7
2 4 453
3 5 23
4 6 676
7
It doesn't quite look like a table, but if you stuff more tab characters into the output, you should get something looking closer to table format

Pandas list comprehension in a dataframe

I would like to pull out the price at the next day's open currently stored in (row + 1) and store it in a new column, if some condition is met.
df['b']=''
df['shift']=''
df['shift']=df['open'].shift(-1)
df['b']=df[x for x in df['shift'] if df["MA10"]>df["MA100"]]
There are a few approaches. Using apply:
>>> df = pd.read_csv("bondstack.csv")
>>> df["shift"] = df["open"].shift(-1)
>>> df["b"] = df.apply(lambda row: row["shift"] if row["MA10"] > row["MA100"] else np.nan, axis=1)
which produces
>>> df[["MA10", "MA100", "shift", "b"]][:10]
MA10 MA100 shift b
0 16.915625 17.405625 16.734375 NaN
1 16.871875 17.358750 17.171875 NaN
2 16.893750 17.317187 17.359375 NaN
3 16.950000 17.279062 17.359375 NaN
4 17.137500 17.254062 18.640625 NaN
5 17.365625 17.229063 18.921875 18.921875
6 17.550000 17.200312 18.296875 18.296875
7 17.681250 17.177500 18.640625 18.640625
8 17.812500 17.159375 18.609375 18.609375
9 17.943750 17.142813 18.234375 18.234375
For a more vectorized approach, you could use
>>> df = pd.read_csv("bondstack.csv")
>>> df["b"] = np.nan
>>> df["b"][df["MA10"] > df["MA100"]] = df["open"].shift(-1)
or my preferred approach:
>>> df = pd.read_csv("bondstack.csv")
>>> df["b"] = df["open"].shift(-1).where(df["MA10"] > df["MA100"])
Modifying DSM's approach 3, stating True/False values in np.where explicitly:
#numpy.where(condition, x, y)
df["b"] = np.where(df["MA10"] > df["MA100"], df["open"].shift(-1), np.nan)
Using list comprehension explicitly:
#[xv if c else yv for (c,xv,yv) in zip(condition,x,y)] #np.where documentation
df['b'] = [ xv if c else np.nan for (c,xv) in zip(df["MA10"]> df["MA100"], df["open"].shift(-1))]