Показать сообщение отдельно
Старый 22.05.2011, 13:59
wvxvw вне форума Посмотреть профиль Отправить личное сообщение для wvxvw Найти все сообщения от wvxvw
  № 19  
Ответить с цитированием
wvxvw
Modus ponens
 
Аватар для wvxvw

модератор форума
Регистрация: Jul 2006
Адрес: #1=(list #1#)
Сообщений: 8,049
Записей в блоге: 38
А еще, конечно, не мозговыносящий алгоритм, но уже интереснее...
Код AS3:
package tests 
{
	import flash.display.Sprite;
 
	/**
	 * ...
	 * @author wvxvw
	 */
	public class ProbabilityTest extends Sprite
	{
		private const _variants:Vector.<uint> = 
			new <uint>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
 
		private const _weights:Vector.<uint> = 
			new <uint>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
		private var _sum:uint = 10;
		public function ProbabilityTest() 
		{
			super();
//			position: 0 total: 67
//			position: 1 total: 107
//			position: 2 total: 105
//			position: 3 total: 113
//			position: 4 total: 108
//			position: 5 total: 88
//			position: 6 total: 91
//			position: 7 total: 107
//			position: 8 total: 115
//			position: 9 total: 99
			this.testDistribution();
			// exclude 5 from the pool completely
			this.setChance(5, 0);
//			1,2,3,4,5,5,6,7,8,9
//			position: 0 total: 110
//			position: 1 total: 120
//			position: 2 total: 107
//			position: 3 total: 117
//			position: 4 total: 117
//			position: 5 total: 0
//			position: 6 total: 97
//			position: 7 total: 115
//			position: 8 total: 108
//			position: 9 total: 109
			this.testDistribution();
			// double the chaces for 6
			this.setChance(6, 2);
//			1,2,3,4,5,5,7,8,9,10
//			position: 0 total: 110
//			position: 1 total: 107
//			position: 2 total: 106
//			position: 3 total: 105
//			position: 4 total: 88
//			position: 5 total: 0
//			position: 6 total: 205
//			position: 7 total: 85
//			position: 8 total: 93
//			position: 9 total: 101
			this.testDistribution();
		}
 
		public function setChance(of:uint, to:uint):void
		{
			of = of % 10;
			this._sum = this.updateIndices(of, to - this.weightAt(of));
		}
 
		private function weightAt(index:uint):uint
		{
			var previous:uint;
 
			if (index) previous = this._weights[index - 1];
			return this._weights[index] - previous;
		}
 
		private function updateIndices(from:uint, by:int):uint
		{
			while (from < 10) this._weights[from++] += by;
			return this._sum + by;
		}
 
		private function testDistribution():void
		{
			var results:Vector.<uint> = new Vector.<uint>(10);
			var i:int;
 
			for (i = 0; i < 1e3; i++)
			{
				results[this.selectRandom()]++;
			}
			for (i = 0; i < 10; i++)
			{
				trace("position:", i, "total:", results[i]);
			}
		}
 
		private function selectRandom():uint
		{
			var random:uint = this._sum * Math.random();
			var index:uint = 4;
 
 
			if (this._weights[index] <= random)
			{
				while (index < 10)
				{
					if (this._weights[index++] > random)
					{
						index--;
						break;
					}
				}
			}
			else
			{
				while (index)
				{
					if (this._weights[--index] <= random)
					{
						index++;
						break;
					}
				}
			}
			return index;
		}
	}
}
Добавлено через 4 минуты
ЗЫ. Не обязательно двоичное дерево, но тоже вариант. Можно предугадать позицию, если, например, мы знаем, что на каждый "шанс" у нас приходится по, скажем, 2 деления, то, тогда, если рандом выдал 8, то это значит, что это должно быть где-то в районе 4-го элемента. Ну или хотябы просто считать не с начала, а с середины, в таком случае наш самый худший случай будет в 2 раза меньше, чем если мы всегда будем считать от начала.

EDIT: Да, а еще можно было бы находить предполагаемый участок, куда упал рандомальный выбор по типу как в quicksort, т.е. делить оставшийся диапазон на 2 все время... хм... ну, вечером наверн сделаю
__________________
Hell is the possibility of sanity


Последний раз редактировалось wvxvw; 22.05.2011 в 14:12.