Как я могу создать файл случайных отрицательных и положительных целых чисел в последовательном? - PullRequest
0 голосов
/ 07 апреля 2009

Я хочу файл случайным образом сгенерированных положительных или отрицательных последовательных целых чисел. На данный момент я прошу, чтобы файл содержал примерно (без гарантии) равные числа отрицательных и положительных значений, но позже легко изменить пропорции. Под «последовательным» я подразумеваю k-й случайный отрицатель, равный -k, и k-й случайный отрицательный знак, равный + k.

Этот однострочный скрипт GNU Bash будет соответствовать формату файла, но просто не будет random .

$ seq -1 -1 -5 && seq 1 5
-1
-2
-3
-4
-5
1
2
3
4
5

Этот пример показывает, что я ищу, еще лучше, но все еще не случайно, поскольку целые числа предсказуемо чередуются между отрицательным и положительным.

$ paste <(seq -1 -1 -5) <(seq 1 5) | tr '\t' '\n'
-1
1
-2
2
-3
3
-4
4
-5
5

Отправка одного из них с помощью команды shuf делает их случайным образом отрицательными или положительными, но они теряют свою серийность.

$ paste <(seq -1 -1 -5) <(seq 1 5) | tr '\t' '\n' | shuf
-5
4
3
2
-2
1
-1
-4
5
-3

Примечание: я пытаюсь протестировать алгоритмы, которые сортируют списки / массивы битов (нули и единицы), но если я буду использовать 0 и 1, я не смогу проанализировать поведение сортировки или сказать, сохранена ли стабильность.

Ответы [ 6 ]

6 голосов
/ 07 апреля 2009

Если я правильно понимаю, вы хотите чередовать положительные и отрицательные числа случайным образом. Например: 1 2 -1 3 -2 4 5- 3.

my $count = 10;
my $pos   =  1;
my $neg   = -1;

my @random = map { 
    int(rand 2) 
    ? $pos++ 
    : $neg--
} 1..$count; 

print "@random\n";

Обновление:

Чтобы изменить пропорции, я бы сделал это:

use strict;
use warnings;

my $next = get_list_generator(.5);

my @random = map $next->(), 1..10; 
print "@random\n";

my $again = get_list_generator(.25);

my @another = map $again->(), 1..10; 
print "@another\n";

sub get_list_generator {
    my $prob_positive = shift;

    my $pos = 1;
    my $neg = -1;

    return sub {
        return rand() <= $prob_positive ? scalar $pos++ : scalar $neg--;
    }

}

Функция get_list_generator() возвращает замыкание. Таким образом, вы можете использовать сразу несколько генераторов списков.

3 голосов
/ 07 апреля 2009

Давайте начнем соревнование по гольфу? (44) * * 1 001

perl -le'print rand>.5?++$a:--$b for 1..10'

Редактировать : Версия Daotoad 40 символов

seq 1 10|perl -ple'$_=rand>.5?++$a:--$b'
2 голосов
/ 07 апреля 2009

Где 15 - это общее количество сгенерированных чисел, а tp - количество нужных вам положительных чисел (эффективно указывающих соотношение pos / neg):

tp=8
unset p n
for i in $(printf '%s\n' {1..15} | gsort -R); do
    (( i <= tp )) && \
        echo $((++p)) || \
        echo $((--n))
done
1 голос
/ 07 апреля 2009
#!/bin/bash

pos=0 neg=0
for i in {1..10}
do 
    if (( ($RANDOM > 16384 ? ++pos : --neg) > 0 ))
    then echo $pos
    else echo $neg
    fi
done

Я не мог вписать это в одну строчку. Кто-нибудь еще?

edit : Ах, одна строка, 65 символов (необходимо установить a и b, если вы неоднократно вызываете это в одной и той же оболочке):

a=0 b=0;for i in {1..10}; do echo $(($RANDOM>16384?++a:--b));done
0 голосов
/ 07 апреля 2009

Вот одна строчка из Bash (2?), Вдохновленная ответами Луната и Брайана.

RANDOM=$$; pos=1; neg=-1; for i in {1..10}; do \
echo $(( $(echo $RANDOM / 32767 \> 0.5 | bc -l) ? pos++ : neg-- )); done

Вот сценарий Awk, который участвует в соревновании по гольфу (44).

seq 1 10|awk '{print(rand()>0.5?++p:--n);}'

Это более понятный идиоматический способ написать это:

seq 1 10 | awk 'BEGIN{srand(); pos=1; neg=-1;}
                {print (rand() > 0.5 ? pos++ : neg--);}'
0 голосов
/ 07 апреля 2009

Не существует набора чисел, который будет соответствовать всем вашим критериям. Вы не можете сказать, что хотите случайное, но в то же время говорите, что k-е отрицательное значение == -k и k-е положительное значение == k. Вы можете сделать это случайно или нет.

Что касается того, что вы пытаетесь сделать, почему бы не разделить две проблемы и проверить сортировку на чем-то вроде массива пар целых чисел длины n. Первый из пары может быть нулем или 1, а второй из пары будет вашим трекером стабильности (просто счет от 0 до n).

Создайте список 0 и 1, которые вы хотите, и перемешайте их, а затем добавьте к целому числу трекера. Теперь отсортируйте пары по их первому элементу.

Входные данные для вашего вида будут выглядеть примерно так.

0, 1
1, 2
0, 3
1, 4
1, 5
0, 6
0, 7
1, 8
1, 9
1, 10
0, 11
0, 12
0, 13

Стабильные сорта будут производить это

0, 1
0, 3
0, 6
0, 7
0, 11
0, 12
0, 13
1, 2
1, 4
1, 5
1, 8
1, 9
1, 10

Нестабильные сгенерируют 0 и 1 с целыми числами трекера.

...