Sunday, April 07, 2019

Re:mass mailing service/https cpanel/admin RDP

hi there,

we updated our inbox smtp for email blast/cpanel/RDP/Zimbra webmail/email  extractor tools,

please add my below contacts for any inquiry

Skype ID live:tools2018_2

ICQ UIN 742 624 895

Wechat ID smtptools_1

Whats app: 0086-13857707871 (China No)

 

Package 1: Unlimited SMTP server + Turbo Mailer + admin RDP/Price: $175/Per Month

(once SMTP blacklist, we will give 2 times replacement for free)

 

Package 2: Unlimited web-based SMTP/Price:$175/Per Month

interspire email marketer installed

 

Package 3: Supmer mailer + admin RDP + 5 SMTP rotate/price: $300/Per Month

 

Package 4: Supmer mailer + admin RDP + 10 SMTP rotate/price: $500/Per Month

 

Package 5: Unlimited SMTP server/Price: $99/Per Month

(once SMTP blacklist, we will give 2 times replacement for free)

 

Package 6: Unlimited webmail 

Roundcube webmail (bcc up to 1000 emails)price: $135/Per Month

Zimbra webmail (bcc up to 1000 emails)price: $155/Per Month

 

Package 7: spam and scan friendly Admin RDP/price: $45/Per Month

multiple locations RDP avaiable

 

Package 8: Email Sorter and Email list manager/price: $135 with lifetime license

 

Package 9: general business/office 365/CEO & CFO email leads

1- general business company email leads: $50 per 100k

2- office 365 emails: $60 per 100k

3- CEO & CFO email leads: $100 per 100k 

 

Package 10: bulletproof cpanel/WHM Price: $75/Per Month

host any page no trouble/ignore any reports/create unlimited cpanel accounts

 

Package 11: email extractor/price: $155 with lifetime license

(extract email by keyword /also can extract by country)

 

Package 12:email verifier/price $135 with lifetime license 

(remove invalied emails)

 

For payment, we accept below:

1- Perfect Money

2- Bitcoin

3- Western Union

4- Money Gram

5- Bank T/T

 

Oline info & tech marketing LTD ( China based)

Skype ID live:tools2018_2

ICQ UIN 742 624 895

Wechat ID smtptools_1
Whats app: 0086-13857707871

Email:728556969@qq.com

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Tuesday, April 02, 2019

Harlequins: Not Sure If Good

Harlequins are decent at best.

I'm just going to come out and say it:  I don't think Harlequins are looking too good from a competitive standpoint.  With the book firmly in hand now, I don't see quite as much value from them compared to Dark Eldar when the army first got teased.

Before I completely put them aside, just note that I think there are a few things that Harlequins bring to the table.  These are few, they're niche, and they're certainly conditional, but I think Harlequins can have some interesting options that no one else can really pull off.  For example, when you look at some of the things that Soaring Spite can do with their Masque Form, you'll know that the army will be able to move 16"+6" and still shoot with 6" Fusion Pistols without penalty for 28" threat range.  This awesomeness simply cannot be ignored.  Similarly, if you take Faolchu's Talon for your Soaring Spite Warlord, you can move an additional 6" in your movement, and when you blow up, nothing happens.  No explosion, no models dying, you just roll out of your drive-by mobile and find another joyride to blow people up in.  This is great and all, but it's also very niche.  Hell, even their big fancy Webway Gate wants me to drop multiple Talos or a fat unit of Grots out of them instead.

So here's where I have problems with the army:  They're melee Horrors.  They're melee-based units that cost a ton but still have the same statline as those little pink dudes.  You have an army of 1W T3 4++ melee Horrors that desperately want to be relevant in a meta filled with resilience and anti-alpha.  Everyone and their mother knows that T3 and 4++ with a single wound just get absolutely murdered by almost any type of shooting and even below-average melee fillers that play much better in attrition simply because of the points.  Harlequins are great if you think that killing MEQ with 3+ for almost 30 points is great.  You know what else is 30 points?  A Grot, and a Grot comes with so much more resilience because a single Grotesque can be T6 with 4 wounds and 4++ with FNP.  Speaking of 4W, this is actually much bigger than people realize.  It takes 2 D2 shots to kill, out of kill scope of D3 weapons, and makes D6 weapons very nervous.  It's pretty much the sweetest spot for being infuriating at 30ppm.  When it comes to bashing in a Marine's face, a Grot does just as much damage but can stay alive much longer vs. almost any kind of shooting and any kind of melee.  In fact, Harlequin melee stopped being relevant ever since stronger alternatives came out:  Genestealers, Grotesques, Dawneagle Shield-Captains, the list goes on and on.  Hell, even Wyches are better for the points if you want a melee option.  Marines are dead easy to kill with any competitive army worth their salt because single-wound that cost a lot are just not cost-effective in today's meta.  Attrition matters and Harlequins play the game the worst out of all the units in the game.  Every other army that wants to be in melee does it better for the cost.  For me, since I play Dark Eldar in a very shooty manner, why bother being in melee if you can shoot them to death from far away?  My T3 5+ AS with an FNP Warrior that cost 6 points is looking a lot more cost-effective next to a 28-point Harlequin with a Fusion Pistol and an Embrace.  You are essentially paying a premium for a luxury that's not needed.

Arguably the best Form in the book.

This brings me to match-up.  In any given competitive setting, you're going to be looking at your local meta or even the greater meta (GTs or national events) and comparing yourself to all the other armies out there.  You have to factor in the fact that Harlequins are not cheap, not in the slightest.  Their unit choices are limited already, but what you pay for is a unit that's not very durable but has a ton of bad match-ups.  If you run into a Tyranid list with a lot of Genestealers for example, you know for the points that you're going to fight an attrition battle that you're not going to like.  If you're fighting a lot of Gaunts, forget about it because you already lost the points game here (anything with Fearless sucks).  God forbid you to run into a unit of Wyches, or even worse, a unit of Grots.  With Meat Mountain being so popular these days, just running into a unit that you're not going to be able to really hurt while still taking assloads of damage in return is going to suck.  The worst part is when you start thinking about this from a points perspective.  Having Harlequins killing cheap fodder units is a waste of time and it's only going to get you shot up afterward and killed.  A canny opponent is just going to spread out his line so he sets up kill zones for your units afterward (why Midnight Sorrow might be pretty decent).  IG carparks are going to be super annoying and so are most armies with cheap armor and plentiful shooting.  I feel very confident with my pure Kabal army vs. any army that takes a decent amount of Harlequins for example.  When you bleed expensive models, your firepower and melee threat goes down a ton.  That's one of the reasons why I prayed to the dice gods that GW was going to give the army -1 To Hit all-around.  Alas, this was not to be.  Instead, you have to pay up the ass in CPs and bet on Psychic powers or other instances to keep your basic stuff alive long enough to be relevant.

Harlequins are points-prohibitive.  If you take them, you won't have a lot of anything else.  If you want to run them in any meaningful way, you will take them as a Battalion.  You will already need multiple HQs to get the most of your army like the Shadowseer and Troupe Master, and Troupes just naturally fill in the rest of the core choices.  The difficult part here is getting into a points zone where you can still be relevant and be a threat to the enemy without costing an arm and a leg.  It's not just the points that matter here, it's about being relevant and a threat to the enemy.  What I mean by this is that you need to pack anti-tank in any competitive list as well as being a threat in melee because that's what you're taking Harlequins for.  The army, in general, is bi-polar.  If you want them to be a strong AT threat, you take Fusion Pistols.  If you want them to be a big melee threat, you mix up Caress and Embrace.  The problem is that they both go on the same model and when that model dies, he takes both of those upgrades with him.  Some people argue saying that you can take them stock, or leave specials off them as extra wounds, but why the hell would you do that?  If you're just looking at a few models that can do damage, Wyches can fill that role for much cheaper.  Unfortunately, you have this current situation where both ranged and melee special weapons cost a good deal of points on an already expensive model to begin. This is why the attrition factor sucks so much for this army.  It's not very durable and every model lost feels like chunks out of the army's total strength compared to other armies.  Hell, most would agree with me when I say that Soaring Spite is arguably the best Form right now for Harlequins, but what people talk about but don't consider is how many points a boat filled with Fusion Pistol Troupes really are.  If you want to decrease the cost by removing Fusion Pistols, you lose out on the Form's benefits.  You cut the melee weapons and you're now a glorified Wych.  Grats.  More importantly, for how many points you're spending trying to make this clusterfuck work, you're also taking away points from allies who can possibly perform the same role better.  Case in point, you can buy an entire Black Heart Spearhead for less than 500 points if you just want something to shoot.

Too much, too little.

So what am I getting at here?  It means that if you put a lot of points into Harlequins, you need them to be a decent standalone force.  But if you need them to be standalone, in the fact that you need your points to also equate out to the ability to kill tanks and infantry, then you're simply increasing the cost of each Troupe unit.  Taking a deeper dive:  For 500 points, I can buy a Black Heart Spearhead with 3x Ravagers with Dissies on all of them.  What do Dissies do?  They can pretty much wreck anything because this buys the army 27 BS3+ S5 AP-3 D2 shots that can threaten GEQ, MEQ, multi-wound, single-wound, high-armor, whatever, you name it.  This is just from shooting because you're not counting access to Agents of Vect, Living Muse, Cunning, or FNP on all your vehicles.  You put 500 points into a Harlequin force and what do you get?  You do the math and get back to me with exactly what firepower you have in shooting and in melee and see if the numbers pay off for you.  First, you need to be a certain distance from the enemy to threaten them with AT Fusion Pistols, then you need to be in combat to get the most out of them.  To get in, you have to brave the Overwatch, hope none of your 28 point models die, roll to get in, and then you can really shine.  You have to play much cleaner, much more precise and pray for some good ol' dice rolls because there's a lot that can go wrong.  With Grots, you just push models forward and results happen.  With Ravagers, it's the same thing, but you don't need to commit because you're 36" away from your target.  With Harlequins, it's all risk, and I hate risk.  And so do most competitive players.

You know what else is risky?  Conditional effects.  When you look at Harlequins, almost everything in the army requires you to be within 6", roll something to enable (Veiled Path), cast a psychic power, drop multiple Strategems across multiple phases, or something else.  Most of these things can fail to bad luck, some can be outright countered (Vect, Denied), and others can be counter-played sufficiently to really take the wind out of your sails.  The best counter to melee-oriented armies is proper spacing and understanding threat range and averages.  A good player with solid understanding of melee threat range and bubble-wraps will be murderous to Harlequins.  In general, the army is almost too much fluff and not enough consistency when it comes to a lot of their army mechanics and that is a huge risk to competitive players looking to win a GT.  The variables are already great, with matchups and different strength of schedules and players, so you don't need more randomness.  It's almost like you're playing Orks, but you're trying to build a competitive army so you took Eldar or Dark Eldar allies and they're all looking at you like WTF, you took up half of my army points?  A common theme within competitive armies is that they're consistent in their performance.  Just look at some of the discussions around Harlequins being a competitive threat.  It always starts with:  Oh first you take this, then you do this, then you cast this, then you play this Strategem, and then you shoot and lel you embark back in your transport!  Yeah, that's nice, but I play Prophets of Flesh and my entire army has 4++.  That's what consistency looks like and that's why it wins games.  That's why Meat Mountain is doing so much work right now.  That is until people figure out how to beat it.

There is a mild saving grace for the army though, is that they're Battle Brothers with both Dark Eldar and Eldar.  I would say that both of these armies are very competitive with a multitude of unit options.  Eldar arguably has the best psykers (Doom, Jinx) in the game, Shining Spears, Dark Reapers, Wave Serpents, and both the Hemlock and Crimson Hunter Exarch are insane.  Dark Eldar can run Meat Mountain down your throat and cost-effective Kabal units, Ravager Spearheads, Agents of Vect, and CP manipulation up the wazoo.  There is a lot of good stuff in both of these armies, but ultimately it comes down to the points question all over again.  Is Harlequins competitive enough to share the same points as these armies here if you're trying to build competitive?  Only time will tell.  Personally, I think the best Harlequin lists will be the ones mixed with either Eldar or Dark Eldar.  Cegorach knows that I've been trying to make it work.

I really hope I made some solid points here.  Don't get me wrong, I own a ton of the little fuckers and I love them to death, but they're definitely more of a fluffy choice than a competitive choice for me.  There are just too many good unit choices out there that makes army building with them difficult.  I know, I've been trying to design a good army list with Harlequins/DE and/or Eldar for the last couple of days and it's mind-boggling.  When I have something good, I'll show it off.

Explore Simple Game Algorithms With Color Walk: Part 5

We're continuing to look at different game algorithms using the simple game Color Walk as a sandbox for exploration and discovery. The last post covered our first foray into a non-trivial algorithm, namely the greedy algorithm. We found that using the strategy of grabbing the most blocks from the board on each move was a reasonable thing to try, and it outperformed all the previous trivial algorithms. Then we extended the greedy algorithm to look ahead one move and found that it performed even better. Now we're going to extend the greedy algorithm to look ahead arbitrarily far and see how far we can actually look before the run time of the algorithm becomes prohibitive. In this process we should be able to find a way to improve the current data structure of the board to make searching more efficient and allow the algorithm to search more moves ahead as a result.

Greedy to the Nth Degree


The greedy algorithm can naturally be extended to look more moves ahead when making the decision of which block color to remove next. We saw in the last post that to look beyond the current move, we had to modify the board-checking algorithm to mark matching blocks with the number of the move that was being searched. Then, each color could be used in the search and easily rolled back for the next color. In this way each color could be used in the search for the first move, and for each of those colors on the first move, each color is used in a search on the second move. If on each move we ignore the color that was used for the previous move, the first move will consist of 4 searches, and each of those searches will generate 4 additional searches for the second move, resulting in 16 searches of the board for the second move.

Because of how the blocks are marked with the move number, there's no need to stop at the second move. We can continue to look further ahead in moves, looking at another 4 colors on the next move for each color chosen on the current move. Looking ahead 3 moves would result in 64 third-move searches in addition to the first- and second-move searches for a total of 84 searches. Looking ahead 4 moves would add another 256 searches, for a total of 340 searches. You can see how quickly the number of searches increases with each additional move we look ahead. The greedy look-ahead algorithm experiences exponential growth in the number of searches, and that's going to limit the number of moves that we can reasonably look ahead.

We'll tuck that thought in the back of our mind for the moment because we need to modify the algorithm a bit to enable looking ahead more than 2 moves. First, we can add to the GUI so that we can specify how many moves we want to look ahead when running the algorithm. Adding a text input after the drop-down selection box will be sufficient, and I called this text input element solver_max_moves for the JavaScript code. The rest of the changes are all about using this new variable to control the depth of the search in the greedy look-ahead algorithm. First, we need to add the variable and initialize it when either the solver control button or solver batch mode run button is clicked:
function colorWalk()
// ...

function Solver() {
var that = this;
var iterations = 0;
var max_moves = 2;

this.index = 0;

this.init = function() {
this.solver = $('<div>', {
id: 'solver',
class: 'control btn',
style: 'background-color:' + colors[this.index]
}).on('click', function (e) {
max_moves = $('#solver_max_moves').val();
that.runAlgorithm();
}).appendTo('#solver_container');

// ...

$('#solver_play').on('click', function (e) {
iterations = $('#solver_iterations').val();
max_moves = $('#solver_max_moves').val();
that.run();
});
};
The max_moves is initialized to 2 because that will be the default number of moves deep that the algorithm will search—one move for the current move and one move for the next move. Next, we can modify the Solver.greedyLookAhead() function to search as deep as specified by max_moves. As a reminder, here's what the function looked like before:
    this.greedyLookAhead = function() {
var max_control = _.max(controls, function(control1) {
if (control1.checkGameBoard(1) === 0) {
return 0;
}
var matches = _.map(controls, function(control2) {
return control2.checkGameBoard(2);
})
return _.max(matches);
});
this.index = max_control.index;
}
Instead of nesting the second call to Control.checkGameBoard() inside the loop that searches through the controls for the first move, we can call another function that we can then call recursively, incrementing the move number on each call until we reach the maximum search depth. The new algorithm looks like this:
    this.greedyLookAhead = function() {
var max_control = _.max(controls, function(control) {
if (control.checkGameBoard(1) === 0) {
return 0;
}
return greedyLookAheadN(2);
});
this.index = max_control.index;
}

function greedyLookAheadN(move) {
return _.max(_.map(controls, function(control) {
var matches = control.checkGameBoard(move);
if (matches === 0 || move >= max_moves) {
return matches;
}
return greedyLookAheadN(move + 1);
}));
}
In greedyLookAhead(), we can simply return the value returned from calling greedyLookAheadN() to _.max() for selecting the control that results in the most blocks removed for the search depth that we used. Then inside greedyLookAheadN(), we return the maximum number of blocks we've seen from searching all of the controls for the current move. For each control if we've reached the max_moves, we return the number of matches found on this move. Otherwise, we look ahead to the next move and return the maximum number of matches found in that search path. We can also immediately stop searching on controls that produce zero matches because choosing such a control was useless, and we know that other search paths will result in less moves to clear the board without that useless move.

We can verify that the recursive function will terminate because each call to greedyLookAheadN() increments the move number so that it will eventually reach max_moves. If the board is cleared before it reaches max_moves, then there will be zero matches and the function returns without calling itself again, so it will terminate in that case as well. The correctness of this algorithm can be verified by comparing the statistical results of a batch run when max_moves = 2 to the previous version of greedyLookAhead(), and the results are indeed the same. Now we can explore what happens when we increase the search depth to 3:

Color Walk run with 100 iterations of greedy look-ahead by 3 algorithm

Once again the algorithm performance has improved by every statistical measure, as can be easily seen in the table of results:

AlgorithmMinMeanMaxStdev
Round Robin 37 48.3 62 4.5
RR with Skipping 37 46.9 59 4.1
Random Choice 60 80.2 115 10.5
Random with Skipping 43 53.1 64 4.5
Greedy 31 39.8 48 3.5
Greedy Look-Ahead-2 28 37.0 45 3.1
Greedy Look-Ahead-3 25 34.2 40 2.7

However, we're definitely starting to pay a price. The algorithm is starting to run noticeably slower because of all of the searching it needs to do to look an extra move ahead. Setting the max_moves to 4 makes things even worse, resulting in a run time that's getting close to intolerable. The results for such a run of 100 iterations does still improve the performance, but only slightly:

Color Walk run with 100 iterations of greedy look-ahead by 4

We may have hit the point of real diminishing returns, but it's hard to tell without looking at least one more move ahead. Extending to a search depth of 5 is just not feasible, unless we're willing to wait an hour for the results. If we want to break that 5-move barrier, we have a couple options. One is to come up with a different algorithm that doesn't have exponential growth, or at least smaller exponential growth. We'll definitely get to that, but the move-search algorithm isn't the only algorithm in this program that could be optimized. We also have a matching color search algorithm that could be improved.

Improved Color Matching


We have finally reached the pain point of the slow color search routine in Control.checkGameBoard(), and it's time to look at how we can optimize it. First, let's review how the current search algorithm works for finding blocks of the selected color that are adjacent to the empty area of the board:
  1. All blocks on the board are scanned, even live ones.
  2. For each block, if it is dead, then its neighbors are inspected.
  3. If a neighbor matches the color being searched, and it's not dead, then it is marked dead.
  4. For any neighbor marked in step 3, the search is repeated with step 2 and its neighbors.
This search algorithm is not terribly inefficient. Without analyzing it too deeply, it appears roughly linear with the number of blocks on the board because every block is searched and none of the recursive searches for neighbors of matching blocks should run very deep. However, the multiplier on that linear search is pretty high. Every block is inspected at least four times (except for the boundary blocks) because every block is a neighbor to four other blocks. Neighbors are inspected indiscriminately, so each block is inspected as a neighbor four times. On top of that, a large number of blocks are inspected that we know don't need to be. Only the blocks at the boundary between dead and alive need to be inspected, but the algorithm inspects all of the dead blocks and all of the live blocks on every trip through the search algorithm. This adds up to a lot of inspections when we start looking four or five moves deep in the greedy look-ahead algorithm.

In order to get a better idea of how many block inspections we're talking about, we can instrument the code with a simple counter that keeps a tally of how many block inspections occur on each batch run:
    function checkNeighbors(positions, color, check_move) {
_.each(positions, function (position) {
_block_inspect_counter += 1;
// ...
});
}
The counter gets reset when the batch mode play button is clicked, and it gets printed to the console when the batch run completes (in other code, not here). After a run of 100 iterations of the greedy look-ahead-by-2 algorithm, (so we can get a fair distribution of boards) we get a count of 98,350,244 inspections. With an average of 37 moves per iteration, we have an average of 26,581 inspections per move. That's a lot of inspections, but it's nothing compared to the look-ahead-by-3 algorithm, with 441,824,947 inspections over 100 iterations, or an average of 129,188 inspections per move. Notice that's about 5 times more inspections than the look-ahead-by-2 count, which is the same as the number of color choices. That's not a coincidence; it's the exponential growth rate of the greedy look-ahead algorithm. Going to look-ahead-by-4 will increase the inspection count by another factor of 5.

Clearly, we are looking at a lot of blocks on every move, way more than we need to. More specifically, every time we search through the blocks on a new move, we are repeatedly finding the same color blocks that are adjacent to the blocks that are being marked. This repetition didn't really exist with the other algorithms, but with greedy look-ahead, we're looking at the same collections of blocks again and again with the same color choices, just in different orders each time. This duplication, along with mostly inspecting blocks that we don't need to, adds up to a ton of wasted effort.

In order to improve the efficiency of searching, we can modify the data structure for the board, and then use the new data structure to dramatically reduce the number of blocks that need to be inspected in the search algorithm. To enable this huge gain in efficiency, we're going to introduce the notion of a cluster of blocks. A cluster is a set of blocks that are all adjacent to each other and have the same color. Clusters can be found in a very similar way to how adjacent blocks of the same color were found in the old code when marking them. Each cluster will have a list of blocks that belong to it, and each of those blocks will have a parameter identifying which cluster it's in.

Once we have clusters, we need a good way to find clusters that are adjacent to any given cluster. These adjacent clusters are called neighbors, and each cluster will have an array of pointers to its neighbors. Every neighbor of a cluster A will have exactly one neighbor that is the original cluster A, so that the graph of clusters has all bi-directional links. This property is necessary because it's possible for blocks to be adjacent to the cleared blocks from any direction. We need to be able to reach clusters from any direction when searching the cluster graph.

Building the Cluster Graph


Now that we have this idea of a new and improved data structure, we need to build it from a board of individual blocks. We can start by adding a list of clusters to the game, creating a new cluster for the first block, and pushing it onto the list:
  function makeBlocks() {
var x = 0;
var y = 0;

blocks = [];
clusters = [];
moves = 0;

// ...
_.each(_.range(grid_length * grid_height), function (num) {
// ...
});

clusters.push(new Cluster(blocks[0]));
};
This is a simple start, but we need to do a lot more to define a Cluster and build up the graph. The rest of the graph will be added recursively from the construction of the first cluster. Here's the start of the definition of a Cluster:
  function Cluster(block) {
this.blocks = [block];
this.neighbors = [];
block.cluster = this;
var that = this;

var cluster_neighbors = findClusterNeighbors(block);
createNeighboringClusters(cluster_neighbors);
We see the list of blocks starts with the initial block passed to the new cluster, and the list of neighbors starts off empty. The cluster of the block that was passed in can be updated to this cluster we're creating, and then we proceed to find the rest of the blocks in the cluster and then find the neighboring clusters. Each of these final two tasks are much more involved, so they are split out into functions. Here's what findClusterNeighbors() looks like:
    function findClusterNeighbors(block) {
var cluster_neighbors = getNeighbors(block);
var cluster_blocks = selectClusterBlocks(cluster_neighbors);
cluster_neighbors = _.difference(cluster_neighbors,
cluster_blocks);

while (cluster_blocks.length > 0) {
cluster_blocks = _.flatten(_.map(cluster_blocks, function(pos) {
that.blocks.push(blocks[pos]);
blocks[pos].cluster = that;
cluster_neighbors = _.union(cluster_neighbors,
getNeighbors(blocks[pos]));
return selectClusterBlocks(getNeighbors(blocks[pos]));
}));
cluster_neighbors = _.difference(cluster_neighbors,
cluster_blocks);
}

pos_blocks = _.map(that.blocks, function(b) { return b.position; });
return _.difference(cluster_neighbors, pos_blocks);
};
This function gets a little complicated, so let's go through it carefully. The basic idea of this method of finding a cluster and its neighbors is that we're going to use the block passed in as a seed block. That block is already part of the cluster, but we're going to look at all of its neighbors in the first line. Then we select the neighbors that are the same color as the seed block and belong in the cluster. Those selected cluster_blocks are removed from the list of cluster_neighbors, and what's left is all blocks that are neighbors to this cluster.

With this starting point, we can loop through the set of blocks in cluster_blocks. For each block that belongs in the cluster, we'll add it to the cluster, set the block's cluster to this cluster, add all of the block's neighbors to the list of cluster_neighbors, and then return the set of neighboring blocks that should be added to this cluster. Again, these cluster_blocks are removed from the list of cluster_neighbors, and then the loop goes around again. If you think of how this function works on a large cluster, it will start with one block in the cluster, and the set of cluster_blocks and cluster_neighbors will keep expanding until all matching blocks are added to the cluster, and the list of neighbors consists of all blocks bordering the cluster. The blocks that were added to the cluster need to be removed from the cluster_neighbors at the end because some will have been re-added to that list during the loop iterations.

To complete the description of findClusterNeighbors(), we should look at the utility functions getNeighbors() and selectClusterBlocks():
    function getNeighbors(block) {
var neighbors = [];
var i = block.position;
if (i % grid_length > 0) {
neighbors.push(i - 1);
}
if (i % grid_length + 1 < grid_length) {
neighbors.push(i + 1);
}
if (i - grid_length > 0) {
neighbors.push(i - grid_length);
}
if (i + grid_length + 1 < grid_length * grid_height) {
neighbors.push(i + grid_length);
}

return neighbors;
};

function selectClusterBlocks(neighbors) {
return _.filter(neighbors, function(pos) {
return blocks[pos].cluster == null &&
blocks[pos].color === block.color;
});
};
The getNeighbors() function simply looks at each neighboring block to the block passed in, and if the neighbor is not off the edge of the board, it is added to the list of neighbors. The selectClusterBlocks() function filters the list of neighbors passed in for those blocks that are not already part of the cluster (since that would create an infinite loop of re-adding cluster_blocks) and are the same color as the seed block of this cluster.

With those utility functions out of the way, we're ready to look at recursively creating the rest of the clusters with createNeighboringClusters():
    function createNeighboringClusters(cluster_neighbors) {
_.each(cluster_neighbors, function(pos) {
if (blocks[pos].cluster == null) {
clusters.push(new Cluster(blocks[pos]));
}
if (!_.contains(that.neighbors, blocks[pos].cluster)) {
blocks[pos].cluster.neighbors.push(that);
that.neighbors.push(blocks[pos].cluster);
}
});
}
Walking through this function, we look at each cluster neighbor block found in the previous step, and the first thing we do is check if the block is associated with a cluster. If it's not, we create a new cluster and add it to the list of clusters. Then, regardless of whether we created a new cluster or not, we check if the block's cluster is already a neighbor of the current cluster being created. If not, we add it to the list of neighbors and add this cluster to the neighbor's neighbors to create the bidirectional link.

Putting Clusters to Use


Whew, okay, still with me? Now that we have this enhanced data structure, we need a way to put it to use by marking whole clusters of blocks as dead or marking them with the move number for the greedy look-ahead algorithm. We can accomplish this task with a function that's very similar to how we found and marked blocks before:
    this.markNeighbors = function(color, check_move) {
_.each(that.neighbors, function (neighbor) {
_block_inspect_counter += 1;
var block = neighbor.blocks[0];

if (block.color === color &&
!block.isDead &&
block.marked === 0) {
_.each(neighbor.blocks, function(block) {
if (check_move > 0) {
block.marked = check_move;
} else {
block.isDead = true;
$('#block' + block.position).css('background-color', '#d9d9d9');
}
});
}
});
This marNeighbors() function is basically the same as the old Control.checkNeighbors() function, except for one thing. We've added a loop to mark each block within the cluster since now there are potentially many blocks to mark instead of just one. With this function, we should be able to modify our search algorithm to use clusters instead of blocks:
    this.checkGameBoard = function(check_move) {
var color = this.color;
_.each(blocks, function (block) {
if (block.marked >= check_move) {
block.marked = 0;
}
});

// New search using clusters
_.each(clusters, function (cluster) {
var block = cluster.blocks[0];
if (block.isDead || (block.marked < check_move &&
block.marked !== 0)) {
cluster.markNeighbors(color, check_move);
}
});

return _.filter(blocks, function (block) {
return (0 !== block.marked);
}).length;
}
Now instead of inspecting every block at least four times, we inspect clusters and mark all of the blocks in a cluster when a matching cluster is found. This new algorithm by no means uses the full power of our new data structure, but it does allow us to test correctness of the cluster implementation and see if we're moving in the right direction. After running with the new data structure, we find that the greedy look-ahead-by-2 inspects 66,693,673 blocks. Not a huge improvement, but still, a 32% improvement is something. Checking the greedy look-ahead-by-3 run gives 300,428,165 inspections for another 32% improvement, and in both cases the move statistics check out with their previous values. It looks like we're on the right track, so let's unleash the full power of clusters. First, we need to add a feature to limit the searching we do when marking neighboring clusters:
    this.markNeighbors = function(color, check_move) {
_.each(that.neighbors, function (neighbor) {
_block_inspect_counter += 1;
var block = neighbor.blocks[0];

if (that.blocks[0].marked < block.marked && block.marked < check_move) {
block.cluster.markNeighbors(color, check_move);
} else if (block.color === color && !block.isDead && block.marked === 0) {
_.each(neighbor.blocks, function(block) {
if (check_move > 0) {
block.marked = check_move;
} else {
block.isDead = true;
$('#block' + block.position).css('background-color', '#d9d9d9');
}
});

if (check_move === 0) {
that.blocks = _.union(that.blocks, neighbor.blocks);
that.neighbors = _.union(_.without(that.neighbors, neighbor), _.without(neighbor.neighbors, that));
_.each(neighbor.neighbors, function (next_neighbor) {
next_neighbor.neighbors = _.without(next_neighbor.neighbors, neighbor);
})
}
}
});
When we're inspecting the neighbors to the cluster that we're currently on, we check if the blocks are marked with a move that's between the current cluster and the maximum number of moves we're looking through. If this check is true, then we're going to follow this neighboring cluster with a recursive call to markNeighbors(). This check allows us to quickly move to the clusters at the border between marked blocks and unmarked blocks without moving backwards on those bidirectional neighbor links.

The other additional chunk of code at the end of the else-if branch actually merges matching clusters with the dead pool of blocks to make a growing set of blocks all marked dead. This dead pool can be accessed immediately with blocks[0].cluster, and it allows for extremely efficient searching one move deep because all the neighbors of the dead pool are the clusters we're interested in for the next move. Note that this merge is only a partial merge. Neighboring blocks are added to the dead pool list of blocks, and the neighbor links are carefully updated so that the dead pool's list of neighbors is updated and the newly dead cluster's neighbors now point to the dead pool. However, the blocks and neighbors of the newly dead cluster are not updated, since they don't need to be. These clusters will never be directly referenced again, so we don't need to waste time updating them.

With that addition to markNeighbors(), we can dramatically simplify our search algorithm:
    this.checkGameBoard = function(check_move) {
_.each(blocks, function (block) {
if (block.marked >= check_move) {
block.marked = 0;
}
});

blocks[0].cluster.markNeighbors(this.color, check_move);

return _.filter(blocks, function (block) {
return (0 !== block.marked);
}).length;
}
All we have to do is call markNeighbors() for the dead pool cluster, which is found with blocks[0].cluster. Now running the greedy look-ahead-by-2 algorithm for 100 iterations results in only 3,698,309 inspections, or about 1,000 inspections per move. Wow! That's more that 26 times less than we were doing with the original per-block algorithm. Checking the look-ahead-by-3 algorithm gives 27,241,991 inspections, or about 7,965 inspections per move. That's more than 5 times the look-ahead-by-2 number, but it's less than the per-block algorithm by a factor of 16.

I think we're ready to put the cluster search method to work and see how well the greedy look-ahead-by-5 algorithm performs:

Color Walk 100 iteration run with greedy look-ahead-by-5

Well, that's surprising. It doesn't seem to do much better at all. Comparing it with the rest of the algorithms, we get this:

AlgorithmMinMeanMaxStdev
Round Robin 37 48.3 62 4.5
RR with Skipping 37 46.9 59 4.1
Random Choice 60 80.2 115 10.5
Random with Skipping 43 53.1 64 4.5
Greedy 31 39.8 48 3.5
Greedy Look-Ahead-2 28 37.0 45 3.1
Greedy Look-Ahead-3 25 34.2 40 2.7
Greedy Look-Ahead-4 25 33.3 39 2.6
Greedy Look-Ahead-5 25 33.1 41 2.8

On average, the look-ahead-by-5 run only did slightly better than look-ahead-by-4, and it even did worse in at least one case, giving it a maximum number of moves of 41 instead of 39. It may be the case that looking ahead that many moves causes certain paths in the move order to be picked that look like they'll be better, but in the long run these choices turn out to be slightly worse than making a choice with less information. At any rate, it looks like we're reaching the limits of the greedy look-ahead algorithm because looking much further ahead will take an inordinate amount of time, and we probably have to look much further ahead to get additional gains from the algorithm.

In the process of expanding the greedy look-ahead algorithm we've discovered a few things. First, looking ahead up to 3 moves is quite beneficial to the greedy algorithm. We were able to regularly break the 30-move barrier, and we improved the average performance from about 40 moves to 34 moves.

Second, we ran into significant diminishing returns beyond looking 3 moves ahead while incurring exponentially rising costs in run time. Going from 3 moves ahead to 5 moves ahead only decreased the average number of moves by one, but increased the running time by a factor of six. Trying to push the algorithm further will just run into more extreme exponential growth in run time with potentially no gains in reducing the number of moves.

Finally, we could increase the speed of the color matching algorithm substantially by using a more intelligent data structure that took advantage of the features of the game. Grouping blocks into clusters when each board was created allowed us to make a more efficient search algorithm, but in the end it only delayed the inevitable slowness that results from the exponential growth of looking more moves ahead. We could find other optimizations, but each order-of-magnitude improvement would only allow us to look one or two more moves ahead and there just aren't that many order-of-magnitude optimizations to the color matching algorithm. The real limitation is in the greedy look-ahead algorithm itself, so next time we will move on to exploring other options and see how they do.


Article Index
Part 1: Introduction & Setup
Part 2: Tooling & Round-Robin
Part 3: Random & Skipping
Part 4: The Greedy Algorithm
Part 5: Greedy Look Ahead
Part 6: Heuristics & Hybrids
Part 7: Breadth-First Search
Part 8: Depth-First Search
Part 9: Dijkstra's Algorithm
Part 10: Dijkstra's Hybrids
Part 11: Priority Queues
Part 12: Summary

Friday, March 29, 2019

15 Best Highest Paying URL Shortener Sites to Earn Money Online

  1. Bc.vc

    Bc.vc is another great URL Shortener Site. It provides you an opportunity to earn $4 to $10 per 1000 visits on your Shortened URL. The minimum withdrawal is $10, and the payment method used PayPal or Payoneer.
    Payments are made automatically on every seven days for earnings higher than $10.00. It also runs a referral system wherein the rate of referral earning is 10%.
    • The payout for 1000 views-$10
    • Minimum payout -$10
    • Referral commission-10%
    • Payment method -Paypal
    • Payment time-daily

  2. Adf.ly

    Adf.ly is the oldest and one of the most trusted URL Shortener Service for making money by shrinking your links. Adf.ly provides you an opportunity to earn up to $5 per 1000 views. However, the earnings depend upon the demographics of users who go on to click the shortened link by Adf.ly.
    It offers a very comprehensive reporting system for tracking the performance of your each shortened URL. The minimum payout is kept low, and it is $5. It pays on 10th of every month. You can receive your earnings via PayPal, Payza, or AlertPay. Adf.ly also runs a referral program wherein you can earn a flat 20% commission for each referral for a lifetime.
  3. Linkrex.net

    Linkrex.net is one of the new URL shortener sites.You can trust it.It is paying and is a legit site.It offers high CPM rate.You can earn money by sing up to linkrex and shorten your URL link and paste it anywhere.You can paste it in your website or blog.You can paste it into social media networking sites like facebook, twitter or google plus etc.
    You will be paid whenever anyone will click on that shorten a link.You can earn more than $15 for 1000 views.You can withdraw your amount when it reaches $5.Another way of earning from this site is to refer other people.You can earn 25% as a referral commission.
    • The payout for 1000 views-$14
    • Minimum payout-$5
    • Referral commission-25%
    • Payment Options-Paypal,Bitcoin,Skrill and Paytm,etc
    • Payment time-daily

  4. Wi.cr

    Wi.cr is also one of the 30 highest paying URL sites.You can earn through shortening links.When someone will click on your link.You will be paid.They offer $7 for 1000 views.Minimum payout is $5.
    You can earn through its referral program.When someone will open the account through your link you will get 10% commission.Payment option is PayPal.
    • Payout for 1000 views-$7
    • Minimum payout-$5
    • Referral commission-10%
    • Payout method-Paypal
    • Payout time-daily

  5. Shrinkearn.com

    Shrinkearn.com is one of the best and most trusted sites from our 30 highest paying URL shortener list.It is also one of the old URL shortener sites.You just have to sign up in the shrinkearn.com website. Then you can shorten your URL and can put that URL to your website, blog or any other social networking sites.
    Whenever any visitor will click your shortener URL link you will get some amount for that click.The payout rates from Shrinkearn.com is very high.You can earn $20 for 1000 views.Visitor has to stay only for 5 seconds on the publisher site and then can click on skip button to go to the requesting site.
    • The payout for 1000 views- up to $20
    • Minimum payout-$1
    • Referral commission-25%
    • Payment methods-PayPal
    • Payment date-10th day of every month

  6. BIT-URL

    It is a new URL shortener website.Its CPM rate is good.You can sign up for free and shorten your URL and that shortener URL can be paste on your websites, blogs or social media networking sites.bit-url.com pays $8.10 for 1000 views.
    You can withdraw your amount when it reaches $3.bit-url.com offers 20% commission for your referral link.Payment methods are PayPal, Payza, Payeer, and Flexy etc.
    • The payout for 1000 views-$8.10
    • Minimum payout-$3
    • Referral commission-20%
    • Payment methods- Paypal, Payza, and Payeer
    • Payment time-daily

  7. Short.pe

    Short.pe is one of the most trusted sites from our top 30 highest paying URL shorteners.It pays on time.intrusting thing is that same visitor can click on your shorten link multiple times.You can earn by sign up and shorten your long URL.You just have to paste that URL to somewhere.
    You can paste it into your website, blog, or social media networking sites.They offer $5 for every 1000 views.You can also earn 20% referral commission from this site.Their minimum payout amount is only $1.You can withdraw from Paypal, Payza, and Payoneer.
    • The payout for 1000 views-$5
    • Minimum payout-$1
    • Referral commission-20% for lifetime
    • Payment methods-Paypal, Payza, and Payoneer
    • Payment time-on daily basis

  8. Clk.sh

    Clk.sh is a newly launched trusted link shortener network, it is a sister site of shrinkearn.com. I like ClkSh because it accepts multiple views from same visitors. If any one searching for Top and best url shortener service then i recommend this url shortener to our users. Clk.sh accepts advertisers and publishers from all over the world. It offers an opportunity to all its publishers to earn money and advertisers will get their targeted audience for cheapest rate. While writing ClkSh was offering up to $8 per 1000 visits and its minimum cpm rate is $1.4. Like Shrinkearn, Shorte.st url shorteners Clk.sh also offers some best features to all its users, including Good customer support, multiple views counting, decent cpm rates, good referral rate, multiple tools, quick payments etc. ClkSh offers 30% referral commission to its publishers. It uses 6 payment methods to all its users.
    • Payout for 1000 Views: Upto $8
    • Minimum Withdrawal: $5
    • Referral Commission: 30%
    • Payment Methods: PayPal, Payza, Skrill etc.
    • Payment Time: Daily

  9. Short.am

    Short.am provides a big opportunity for earning money by shortening links. It is a rapidly growing URL Shortening Service. You simply need to sign up and start shrinking links. You can share the shortened links across the web, on your webpage, Twitter, Facebook, and more. Short.am provides detailed statistics and easy-to-use API.
    It even provides add-ons and plugins so that you can monetize your WordPress site. The minimum payout is $5 before you will be paid. It pays users via PayPal or Payoneer. It has the best market payout rates, offering unparalleled revenue. Short.am also run a referral program wherein you can earn 20% extra commission for life.
  10. CPMlink

    CPMlink is one of the most legit URL shortener sites.You can sign up for free.It works like other shortener sites.You just have to shorten your link and paste that link into the internet.When someone will click on your link.
    You will get some amount of that click.It pays around $5 for every 1000 views.They offer 10% commission as the referral program.You can withdraw your amount when it reaches $5.The payment is then sent to your PayPal, Payza or Skrill account daily after requesting it.
    • The payout for 1000 views-$5
    • Minimum payout-$5
    • Referral commission-10%
    • Payment methods-Paypal, Payza, and Skrill
    • Payment time-daily

  11. LINK.TL

    LINK.TL is one of the best and highest URL shortener website.It pays up to $16 for every 1000 views.You just have to sign up for free.You can earn by shortening your long URL into short and you can paste that URL into your website, blogs or social media networking sites, like facebook, twitter, and google plus etc.
    One of the best thing about this site is its referral system.They offer 10% referral commission.You can withdraw your amount when it reaches $5.
    • Payout for 1000 views-$16
    • Minimum payout-$5
    • Referral commission-10%
    • Payout methods-Paypal, Payza, and Skrill
    • Payment time-daily basis

  12. Oke.io

    Oke.io provides you an opportunity to earn money online by shortening URLs. Oke.io is a very friendly URL Shortener Service as it enables you to earn money by shortening and sharing URLs easily.
    Oke.io can pay you anywhere from $5 to $10 for your US, UK, and Canada visitors, whereas for the rest of the world the CPM will not be less than $2. You can sign up by using your email. The minimum payout is $5, and the payment is made via PayPal.
    • The payout for 1000 views-$7
    • Minimum payout-$5
    • Referral commission-20%
    • Payout options-PayPal, Payza, Bitcoin and Skrill
    • Payment time-daily

  13. Ouo.io

    Ouo.io is one of the fastest growing URL Shortener Service. Its pretty domain name is helpful in generating more clicks than other URL Shortener Services, and so you get a good opportunity for earning more money out of your shortened link. Ouo.io comes with several advanced features as well as customization options.
    With Ouo.io you can earn up to $8 per 1000 views. It also counts multiple views from same IP or person. With Ouo.io is becomes easy to earn money using its URL Shortener Service. The minimum payout is $5. Your earnings are automatically credited to your PayPal or Payoneer account on 1st or 15th of the month.
    • Payout for every 1000 views-$5
    • Minimum payout-$5
    • Referral commission-20%
    • Payout time-1st and 15th date of the month
    • Payout options-PayPal and Payza

  14. Cut-win

    Cut-win is a new URL shortener website.It is paying at the time and you can trust it.You just have to sign up for an account and then you can shorten your URL and put that URL anywhere.You can paste it into your site, blog or even social media networking sites.It pays high CPM rate.
    You can earn $10 for 1000 views.You can earn 22% commission through the referral system.The most important thing is that you can withdraw your amount when it reaches $1.
    • The payout for 1000 views-$10
    • Minimum payout-$1
    • Referral commission-22%
    • Payment methods-PayPal, Payza, Bitcoin, Skrill, Western Union and Moneygram etc.
    • Payment time-daily

  15. Linkbucks

    Linkbucks is another best and one of the most popular sites for shortening URLs and earning money. It boasts of high Google Page Rank as well as very high Alexa rankings. Linkbucks is paying $0.5 to $7 per 1000 views, and it depends on country to country.
    The minimum payout is $10, and payment method is PayPal. It also provides the opportunity of referral earnings wherein you can earn 20% commission for a lifetime. Linkbucks runs advertising programs as well.
    • The payout for 1000 views-$3-9
    • Minimum payout-$10
    • Referral commission-20%
    • Payment options-PayPal,Payza,and Payoneer
    • Payment-on the daily basis