Skip to content

Instantly share code, notes, and snippets.

@yhnmj6666
Last active July 19, 2020 12:38
Show Gist options
  • Save yhnmj6666/926fce27ecb5101e22909dd930e84823 to your computer and use it in GitHub Desktop.
Save yhnmj6666/926fce27ecb5101e22909dd930e84823 to your computer and use it in GitHub Desktop.
Number Split
# split a number into a array that
# the sum of array equals to the input number
import numpy as np
from numpy.random import default_rng
import pandas as pd
#configs
presicion=2
calcPrecision=presicion+3
full=100
splitScale=0.1
detailScale=0.005
detailScore=np.array([
[13,13,13,0,12,13,0,12,12,12,],
[0,0,0,0,0,0,0,100,0,0,],
[10]*10,
[10]*10,
[13,13,13,0,12,13,0,12,12,12,],
[0,0,0,0,0,0,0,100,0,0,],
[13,13,13,12,13,12,12,0,0,12,],
[13,13,13,12,13,12,12,0,0,12,],
])
rng=default_rng()
def getRandomSplit(value,total,baseSplit,scale):
non0split=baseSplit[np.nonzero(baseSplit)]
finalScale=min(scale,min((total-value)*non0split))
split=value*non0split
modifier=finalScale*(rng.standard_normal(size=len(split)-1)/3)
modifier=np.append(modifier,-modifier.sum())
rng.shuffle(modifier)
modSplit=split+modifier
i=0;j=0
restore0ModSplit=[]
while(i<len(baseSplit)):
if baseSplit[i]==0:
restore0ModSplit.append(0)
i+=1
else:
restore0ModSplit.append(modSplit[j])
i+=1
j+=1
return np.array(restore0ModSplit)
def finalRepair(detailSplit, target):
unit=0.1**presicion
count=int(round((detailSplit.sum()-target)/unit))
split=detailSplit.flatten()
if count>0:
for _ in range(count):
while True:
index=int(len(split)*rng.random())
if split[index]-unit>=0:
split[index]-=unit
break
elif count<0:
for _ in range(-count):
while True:
index=int(len(split)*rng.random())
if split[index]>0:
split[index]+=unit
break
return split
#change runSplit if needed
def runSplit(score,split):
if score==0:
return [0]*len(split)
while True:
nonzeroScores=len(np.nonzero(split)[0])
scoreSplit=getRandomSplit(score,1,split,splitScale)
scoreSplit=np.round(scoreSplit,2)
finalSplit=finalRepair(scoreSplit,score)
if np.all((finalSplit*full)<=full*split) and np.all(finalSplit>=0):
break
return finalSplit*full
#usage
#runSplit(73/100,detailScore[0]/100)
assert(runSplit(63/full,detailScore[0]/full).sum()-63==0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment