Возьмём 3000 позиций. Тогда с довольно большой вероятностью у нас закончится какой-то элемент раньше. Например на 2900-м элементе. После чего пойдёт bcbcbcbcbcbcbc.<div>Я это решал заполнением массива не по порядку, а случайным образом.<br>

<br><div class="gmail_quote">2009/12/23 Ruslan Zakirov <span dir="ltr">&lt;<a href="mailto:ruslan.zakirov@gmail.com">ruslan.zakirov@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

Ну не совсем так. По разному, но в общем у низкочастотного эелемента<br>
мало шансов появится в начале.<br>
<br>
Что понимать под равномерной тогда? Если у нас 2 элемента X и всего 20<br>
позиций, то на каких местах лучше разместить элементы X?<br>
<br>
* 1, 20?<br>
* 5, 15?<br>
<br>
Все это решаемо вполне.<br>
<div class="im"><br>
2009/12/23 Андрей Костенко &lt;<a href="mailto:andrey@kostenko.name">andrey@kostenko.name</a>&gt;:<br>
</div><div><div></div><div class="h5">&gt; не всё так просто. в начале у нас будет выбираться элемент с вероятностью<br>
&gt; 0,2. А в конце пойдут два оставшиеся с веротностью 0.5. И в конце на больших<br>
&gt; длинах получается bcbcbcbcbc или acacacacac. Поэтому я и заполняю его не по<br>
&gt; порядку, а слуайным образом.<br>
&gt;<br>
&gt; 2009/12/23 Ruslan Zakirov &lt;<a href="mailto:ruslan.zakirov@gmail.com">ruslan.zakirov@gmail.com</a>&gt;<br>
&gt;&gt;<br>
&gt;&gt; Привет, dvhillard :)<br>
&gt;&gt;<br>
&gt;&gt; Введение:<br>
&gt;&gt;<br>
&gt;&gt; 1) сгруппируем одинаковые элементы<br>
&gt;&gt; 2) введем L(g) - длина группы<br>
&gt;&gt; 3) задача отсутствия повторений не решается, если существует группа i,<br>
&gt;&gt; где L(G(i)) = MAX(L(G(j))) для любого j и L(G(i)) &gt; SUM(L(G(j)))+1 для<br>
&gt;&gt; люого j != i. По простецки - если группа с максимальной длинной<br>
&gt;&gt; длиннее объединения всех остальных групп. Доказать элементарно.<br>
&gt;&gt; 4) Введем понятие группа i в критичном состоянии, если L(G(i)) =<br>
&gt;&gt; SUM(L(G(j))) + 1 где j != i. Доказательством от противного легко<br>
&gt;&gt; доказывается, что в наборе не может быть две группы в критичном<br>
&gt;&gt; состоянии. Понятно, что такая группа может иметь только максимальную<br>
&gt;&gt; длинну во всем наборе.<br>
&gt;&gt;<br>
&gt;&gt; Алгоритм:<br>
&gt;&gt; 0) Конец, если все группы пусты<br>
&gt;&gt; 1) Если есть группа в критичном состоянии, то берем элемент из нее. к<br>
&gt;&gt; пункту 0<br>
&gt;&gt; 2) Иначе выбираем &quot;случайно&quot; группу (пропорционально длиннам),<br>
&gt;&gt; исключая группу с предыдущим элементом. К пункту 0<br>
&gt;&gt;<br>
&gt;&gt; Одна и таже группа не может стать два раза подряд критичной, а значит<br>
&gt;&gt; мы не сможем нарушить условие неповторения элементов. Если мы выбрали<br>
&gt;&gt; элемент в пункте 2, то невозможно, что эта группа будет критичной на<br>
&gt;&gt; следующем цикле, а следовательно не нарушается условие неповторения.<br>
&gt;&gt;<br>
&gt;&gt; Из всего вышесказанного следует, что решение существует, при<br>
&gt;&gt; соблюдении условия 3.<br>
&gt;&gt;<br>
&gt;&gt; Вот и простой код в лоб:<br>
&gt;&gt;<br>
&gt;&gt; use strict;<br>
&gt;&gt; use warnings;<br>
&gt;&gt;<br>
&gt;&gt; my @e = qw(a a a a a b b b c c c c d e e e e e e e e e e e e e e);<br>
&gt;&gt; my %g;<br>
&gt;&gt; $g{$_}++ foreach @e;<br>
&gt;&gt;<br>
&gt;&gt; my @res;<br>
&gt;&gt;<br>
&gt;&gt; my $last;<br>
&gt;&gt; while ( keys %g ) {<br>
&gt;&gt;    my $pick = find_critical();<br>
&gt;&gt;    unless ( defined $pick ) {<br>
&gt;&gt;        $pick = pick_except_last();<br>
&gt;&gt;    }<br>
&gt;&gt;    $g{$pick}--;<br>
&gt;&gt;    delete $g{$pick} unless $g{$pick};<br>
&gt;&gt;    push @res, $last = $pick;<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; print join( &#39; &#39;, @e ), &quot;\n&quot;;<br>
&gt;&gt; print join( &#39; &#39;, @res ), &quot;\n&quot;;<br>
&gt;&gt;<br>
&gt;&gt; sub find_critical {<br>
&gt;&gt;    my $critical;<br>
&gt;&gt;    my ($max, $rest) = (0, 0);<br>
&gt;&gt;    foreach my $e ( keys %g ) {<br>
&gt;&gt;        if ( $g{$e} &gt; $max ) {<br>
&gt;&gt;            $rest += $max;<br>
&gt;&gt;            $max = $g{$e};<br>
&gt;&gt;            $critical = $e;<br>
&gt;&gt;        } else {<br>
&gt;&gt;            $rest += $g{$e};<br>
&gt;&gt;        }<br>
&gt;&gt;    }<br>
&gt;&gt;    return undef if $max &lt; $rest + 1;<br>
&gt;&gt;    return $critical if $max == $rest + 1;<br>
&gt;&gt;    die &quot;No solution, too many &#39;$critical&#39; elements&quot;;<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; sub pick_except_last {<br>
&gt;&gt;    my @tmp;<br>
&gt;&gt;    while ( my ($k,$v) = each %g ) {<br>
&gt;&gt;        next if defined $last and $last eq $k;<br>
&gt;&gt;        push @tmp, ($k) x $v;<br>
&gt;&gt;    }<br>
&gt;&gt;    return $tmp[ int rand @tmp ];<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; --<br>
&gt;&gt; Best regards, Ruslan.<br>
&gt;&gt; --<br>
&gt;&gt; Moscow.pm mailing list<br>
&gt;&gt; <a href="mailto:moscow-pm@pm.org">moscow-pm@pm.org</a> | <a href="http://moscow.pm.org" target="_blank">http://moscow.pm.org</a><br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Moscow.pm mailing list<br>
&gt; <a href="mailto:moscow-pm@pm.org">moscow-pm@pm.org</a> | <a href="http://moscow.pm.org" target="_blank">http://moscow.pm.org</a><br>
&gt;<br>
&gt;<br>
<br>
<br>
<br>
</div></div>--<br>
<div><div></div><div class="h5">Best regards, Ruslan.<br>
--<br>
Moscow.pm mailing list<br>
<a href="mailto:moscow-pm@pm.org">moscow-pm@pm.org</a> | <a href="http://moscow.pm.org" target="_blank">http://moscow.pm.org</a><br>
</div></div></blockquote></div><br></div>