Originally published at https://steemit.com Thank you for reading my post, feel free to Follow, Upvote, Reply, ReSteem (repost) @justyy which motivates me to create more quality posts.
When your code has performance bottlenecks, you can use the profiler software to benchmark your code, which will reveal the potential problems in your code or modules (memory or time consuming)
Recently, my Profiler told me that I wrote a few lines of useless code.
最近我就用 Profiler 跑了一下,发现我写了几处无用的代码。具体如下:
As seen in the screenshot, the leftmost numbers are calling counters, the middle columns are time in milliseconds, and the rightmost columns are also time but with the sub-routines. Those lines are safety checks to prevent the crash due to possibly out-of-range errors.
Obviously, the statistics show that these exit conditions are never met. Removing these save 2-3 seconds execution time. The method of adding safety checks (e.g. check object for null), are often seen as a way to handle the exception softly. Some might argue that it is a way to hide the errors. It is always better to throw the exceptions as early as you can instead of hiding them, because they will eventually come back to bite you in the as*.
Originally published at https://steemit.com Thank you for reading my post, feel free to Follow, Upvote, Reply, ReSteem (repost) @justyy which motivates me to create more quality posts.
Originally published at https://steemit.com Thank you for reading my post, feel free to Follow, Upvote, Reply, ReSteem (repost) @justyy which motivates me to create more quality posts.
By using Javascript simulations, we happen to know that if the P is closer to 100%, we choose the ‘vote and rest’ strategy, otherwise, we can just vote all once right before the timespan ends.
This post, we use the backtracking to search all possible strategy solutions. The search space is huge and that is why we make T and N smaller i.e. N=4 (4 hours) and T=4 (4 upvotes per day). M=270 which is 100% payout in unit of dollars.
Let’s create an array that contains the minutes offsets (from the start) for each votes.
我们先定义一个点赞方案的数组, 值表示为离时间段开始的分钟偏移:
1 2 3 4
var sol = Array(); for (var i = 0; i < T; ++ i) { sol[i] = 0; }
For example, 比如
1
sol = [1, 2, 3, 4, 5, 6, 7, 8];
The sol represents voting every minute from the minute 1. There are 8 votes. We initialize the sol array to zeros meaning voting all once at the begining (with zero minute offset)
表示为每隔1分钟点1次,一共点8次,上面的JS代码初始方案数组为0,也就是说统统在开始点完。
Let’s also declare two variables, one stores the solutions and the other stores the maximum payout.
然后我们需要定义两个变量,一个是找到的最大方案数,另一个是最大收益值:初始化为:
1 2
var bestSol = sol.slice(0); var bestScore = 0;
We need to print out the solutions once we find the best one.
找到较优值后我们需要打印方案:
1 2 3 4 5 6 7
function print(sol) { var s = ""; for (var i = 0; i < T; ++ i) { s += sol[i] + ", "; } console.log(s); }
We need a evaluation function that computes the payout given a solution. Every minute, the SP restores 0.005/36.
然后我们需要评估一种方案的收益情况,这时候按分钟来回能量 (每分钟回 0.005/36 能量):
1 2 3 4 5 6 7 8 9 10 11 12
function eval(sol, P, M, T, N) { var sp_restored = 0.005 / 36; P = Math.min(1, P + sp_restored * (sol[0])); // Max = 100% 最大P为1 var x = 0; sol[T] = sol[T - 1]; // Avoid out of range access for sol[i+1] 哨兵:防止 sol[i + 1] 越界 for (var i = 0; i < T; ++ i) { x += P * M; // Accumulate Payout 累记收益 P -= 0.02; // 2% loss 点一次耗2% P += sp_restored * (sol[i + 1] - sol[i]); // SP restores before next vote 加上到下次点赞回血量 } return x; }
The best part is: the search algorithm. We enforce a 15-minute interval between intermediate votes unless the votes come to the end. The reason for doing this is that the search space is really huge and you can’ t basically finish the search on standard PC. The backtracking can be seen as a search tree, where we start from the root, go as deep as we can, expand to the sibling nodes, and rewind to the parents.
We don’t have the cut-off techniques here, meaning that when we vote at time t, the next votes could happen at t, t+1, t+2 until the end of timespan. The branch factor for this search tree is 60N (assume that all votes are placed at the same time), the depth of the search tree is T, obviously.
The search space is around (60N)^T and we certainly do not have time to bruteforce all possible solutions. With backtracking, the runtime complexity can be seen as C_(60N)^T i.e. the total number of different solutions to pick T from 60N.
The JS code for the backtracking search is: 回溯算法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
function search(sol, left, n, T, right) { if (n == T) { // when we reach the tree leaves 到达搜索树的叶子处 var score = eval(sol, P, M, T, N); // need to evaluate this solution 评估结点 if (score > bestScore) { // found a better solution? 记录更优解 bestScore = score; bestSol = sol.slice(0); } return; } for (var i = left; i <= right; ++ i) { sol[n] = i; // The n-th vote is placed at time i 第 n 次点赞在时间为 i 处 search(sol, Math.min(right, i + 15), n + 1, T, right); // try next vote 尝试下一次点赞 } }
The first vote should happen at minute 72 where the rest 3 should be at the end, which has earned 12 SBD more. 能量满的时候 第一次在第72分钟的时候点,剩下3次再最后的时间点,能比第三种方案多挣12美元!
Use only 1 vote at the begining and the rest at the end.. This problem is NP-hard, where you just have to know that it is VERY HARD problem, in WIKI, it describes as follows:
NP-hardness (non-deterministic polynomial-time hardness), in computational complexity theory, is the defining property of a class of problems that are, informally, “at least as hard as the hardest problems in NP”. More precisely, a problem H is NP-hard when every problem L in NP can be reduced in polynomial time to H, that is: assuming a solution for H takes 1 unit time, we can use H’s solution to solve L in polynomial time.[1][2] As a consequence, finding a polynomial algorithm to solve any NP-hard problem would give polynomial algorithms for all the problems in NP, which is unlikely as many of them are considered hard.[3]
OK, so the preliminary conclusion is: when P is closer to 100%, you might want to try place your first vote at the begining, and the rest right at the end. However, there might be better solutions, i.e. we enforce a 15-minute voting interval here.
Originally published at https://steemit.com Thank you for reading my post, feel free to Follow, Upvote, Reply, ReSteem (repost) @justyy which motivates me to create more quality posts.
The LINQ is out since .NET 3.5, and all above code is just doing one thing: select the specific types e.g. either LayoutAnt or LayoutDevice from a member list layoutList . And one line of LINQ does this exactly: OfType<>
The left version is OK, but it is just old-school considering the developer who did not get familiar with LINQ. But the right version is worse. It has added a ref List which will be cleared. This is not unit-testing friendly at all.
The private methods are not unit-test friendly. And one big issue for both methods is: the member variable layoutList is referenced. If you really have to re-invent the wheel, at least make it a public, static method which takes a readonly layoutList and returns a new copy of List. In this case, the entire function is immutable, and unit-test friendly.
Originally published at https://steemit.com Thank you for reading my post, feel free to Follow, Upvote, Reply, ReSteem (repost) @justyy which motivates me to create more quality posts.
SteemIt Markdown Editor does not support Latex easily. But one alternative (workaround) is to use the Google Tex Image URL. In particular I like Markdown and Latex because it is what-you-think is what-you-get.
我们都知道 STEEMIT支持HTML和MARKDOWN两种编辑模式,一旦启用了一种就无法使用另一种。我比较喜欢用Markdown, 因为这种是一种比较面向程序员 所想即所得的方式 (What you think is what you get).
I am a math fan, in my last post, I realized that inserting equations in SteemIt Markdown or HTML editor is a pain. The fact is that the Latex is not supported in the SteemIt Markdown editor.
Originally published at https://steemit.com Thank you for reading my post, feel free to Follow, Upvote, Reply, ReSteem (repost) @justyy which motivates me to create more quality posts.