Limegarden.net Personal site of Wouter Lindenhof

10Mar/100

Marketing and fuzzy distribution

I have mentioned fuzzy logic and random distribution before but I think that it is also being applied in some marketing strategies.

A supermarket chain in our country is giving away collectibles in the form of images of football players (soccer for the Americans). For every, Oh… I don’t know, € 5 , you spend you will get 5 random pictures.

At lunch my mother, who collects them, was going over a list of friends seeing if they have a picture she doesn’t have or the other way around and she noted that certain images nobody seems to have.

If you think about it from a marketing perspective it makes a lot sense why she doesn’t have certain images. The marketing strategy is all about making you willing to pay a certain amount or attract customers because you want those pictures. Once you have them, the marketing strategy will no longer have affect on you. It is in interest of the marketing company to try and keep you as long as possible under the effect of the marketing strategy.

One way of doing it by doing an imbalanced distribution: Certain pictures will not be distributed in certain locations. That way the customer under the effect of marketing will keep buying. Of course this won’t hold in the long run, so what you do is slowly slide the distribution.

Sliding random distribution:

A distribution whose content is randomized will only distribute a small subset which moves over the entire distribution so that in the end the entire content was equally distributed, however if a moment in time was used only a small subset would have been available.

If you have trouble understanding think of it as traveling from the north pole to the south pole visiting every restaurant you can find. At every stop you will select one random soup on the menu. Each place has different flavors and as you go more and more south you will encounter different flavors. However because your are “sliding” you will often encounter the same soup.

Anyway if that wasn’t clear here is it in code:

[cc_cpp]
#include
#include
#include

#define MAX_AMOUNT 100
#define SLIDER_SIZE 5
/* Uncomment the next line to see the values in random order */
#define USE_RANDOM_ORDER

class SlidingDistribution{
int m_Values[MAX_AMOUNT];
int m_SliderBegin;
int m_SubPos;
public:
SlidingDistribution() : m_SliderBegin(0), m_SubPos(0) {
for(int i =0; i < MAX_AMOUNT; ++i)
{
m_Values[i] = i;
}
#ifdef USE_RANDOM_ORDER
std::random_shuffle(m_Values, m_Values + MAX_AMOUNT);
#endif
}

int GetRandomNumber(){
m_SubPos += 1;
if(m_SubPos % SLIDER_SIZE == 0)
{
m_SliderBegin = (m_SliderBegin + 1) % MAX_AMOUNT;
m_SubPos = 0;
}
return m_Values[(m_SliderBegin + (m_SubPos % SLIDER_SIZE))%MAX_AMOUNT];
}
};

int main(int argc, const char** argv)
{
SlidingDistribution distribution;
int amounts = 0;
do{
int alignCounter = 0;
while(amounts)
{
std::cout << std::setfill(' ') << std::setw(3) << distribution.GetRandomNumber();
alignCounter++;
if(alignCounter >= 14)
{
std::cout << "\n";
alignCounter = 0;
}else
{
std::cout << " ";
}

amounts--;
}
std::cout << "\n" << "How many values do you wish to see? (type 0 to quit)\nLoops: ";
std::cin >> amounts;
} while(amounts);
return 0;
}
[/cc_cpp]

7Mar/090

Random distribution

One of the special effects I recently worked one was cellular noise (original made by Steve Worley) and the book that I read used Poisson distribution. The Poisson distribution is a table which holds random values that guarantees certain conditions (like an average mean). However I’m not going to talk about Poisson distribution, it just remembered me of some old error I made and how I finally solved it. Besides there are better sources than me who can explain the math behind it.

But first a talk of a prehistoric me talking about some game that I worked on.

One of the games that I worked on as a student was a shooter like Tyrian but then in 3D. You would race around in hovering car through a fixed path in a 3D city and you would shoot down enemy cars. Since the path was a circle, you would go around and around until you were death, you could jump from one car to another and that was pretty cool to see (and made the game quite easy if you knew the timing). However some cars would be rare to encounter because they had better armor or better weapons and we needed fact in the spawning code. I made up some kind of obscure code for it that based on random number and a “common” value would spawn one of the cars. Before I started on it I thought it wouldn’t be too hard. But this is one of the times I was actually wrong. It worked to some degree but I noticed that some cars were rarely spanned, even though they had a high “common” value. The problem was obvious in the code I had written but at that time I couldn’t think of an algorithm that would solve this issue.

Ok, enough history, let’s go back to the future.

By now I have worked on a lot more of code and when I read how Poisson distribution is used, which is properly how more distribution work, I noticed it was similar to what I once invented.

So to illustrate the problem I will try and remember and describe what I used for that game.

We could use [cci_cpp]rand() % MAX_CAR_ID[/cci_cpp] to generate a lot of random numbers so that we have a list of cars that we use for the game. Using [cci_cpp]std::vector CarSpawnList[rand()%ListSize][/cci_cpp] we could decide the next car. Problem is that this method is slow and does not guarantee the distribution we are looking for and some of the cars might not even be in the list to begin with.

A better method is using two lists. The first list contains all the values we want to have like for every Saab there are five Fords, then we would add the ID of a Saab once and then we add the ID of a Ford five times. Problem with this list is that the numbers are ordered or are in a way ordered. We could still use [cci_cpp]CarSpawnList[rand()%ListSize][/cci_cpp] but if we have a bad seed we could still have three Saabs before we encounter a ford.

So let’s introduce the second list. The second list will start empty and we move every item in the initial list to the second least. So we remove it in the first list and add it to the second list. The item chosen in the first list is random and because it is removed we will make certain that the Saabs and Fords balance each other. In code it would look something like:

[cc_cpp]
#define CAR_SAAB_ID 1
#define CAR_SAAB_MAX 1
#define CAR_FORD_ID 2
#define CAR_FORD_MAX 5
#define CAR_MAX_ORDER 1

void FullListRandom()
{
std::vector lInitialList;
std::vector lFinalList;

for(int i = 0; i < CAR_SAAB_MAX * CAR_MAX_ORDER; i++)
lInitialList.push_back(CAR_SAAB_ID);
for(int i = 0; i < CAR_FORD_MAX * CAR_MAX_ORDER; i++)
lInitialList.push_back(CAR_FORD_ID);

// now create the final list
while(lInitialList.size())
{
int CurId = rand() % lInitialList.size();
lFinalList.push_back( lInitialList[CurId] );
lInitialList.erase( lInitialList.begin() + CurId );
}
};
[/cc_cpp]

Of course you have to put [cci_cpp]lFinalList[/cci_cpp] somewhere more global, I just wrote this code for this post, but if you increase [cci_cpp]CAR_MAX_ORDER[/cci_cpp] then you can prevent a repeating pattern. If you would think of [cci_cpp]lFinalList[/cci_cpp] as circular list (meaning, once you reach the end you start over) this will provide a quite good and consistent distrubution.

By now the above method is common knowledge for me and it is rather simply once you know how to do it.

References