Как получить скрипт оболочки для правильного перемешивания значений массива? - PullRequest
2 голосов
/ 04 февраля 2012

У меня есть фантастический сценарий оболочки, который прекрасно работает: берет строку значений Unicode и перемешивает их. Проблема в том, что мне нужно быть абсолютно уверенным, что каждое значение находится в другом месте в строке.

Например, если моя строка (просто использующая ascii):

АБВГДЕЖ

Мне нужно знать, что ни один из этих символов не будет в том же месте после перетасовки:

gbadcef не будет работать, потому что "d" находится в том же месте. Взять самое последнее значение и поставить его на первое место сработает ...

fabcde

... но это не дает мне случайность, необходимую для приложения.

Фактическая строка данных - это значения Unicode, длинные, длинные, длинные строки, разделенные точкой с запятой:

₮„‮″⃝Ⴎ𠂮ž etc.

Вот код тасования, который у меня сейчас есть:

#!/bin/bash
echo "Input Filename:";
read ifilename;
echo "Output Filename:";
read ofilename;
cat $ifilename | sed -r 's/(.[^;]*;)/ \1 /g' | tr " " "\n" | shuf | tr -d "\n" > $ofilename;

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

Спасибо за любую помощь!

Ответы [ 2 ]

0 голосов
/ 04 февраля 2012

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

#!/bin/bash
IFS=";"
while read -r -a array
do
    num=${#array[@]}
    for ((i = 0; i < num; i++))
    do
        r=$i
        while ((r == i)) || [[ ${new[r]} ]]
        do
            ((r = $RANDOM % num))
        done
        new[r]=${array[i]}
    done
    echo "Input:  ${array[*]}"
    echo "Output: ${new[*]}"
done

Пример:

$ charshuf < charfile
Input:  a;b;c;d;e;f;g;h;i;j;k;l
Output: j;h;i;a;b;k;f;e;g;c;l;d
Input:  1;2;3;4;5;6;7;8
Output: 6;3;8;2;4;7;5;1
0 голосов
/ 04 февраля 2012

Возможно, это бесполезно, потому что я не видел тег perl, но я бы использовал этот инструмент для работы.Сценарий принимает два аргумента: входной файл для чтения строк Unicode и выходной файл для записи перемешанных строк.

Содержимое script.pl:

use warnings;
use strict;
use List::Util qw( shuffle );

## Check arguments for two files, one for input and other for output.
die qq[Usage: perl $0 <input-file> <output-file>\n] unless @ARGV == 2;

## Open files.
open my $ifh, qq[<], shift @ARGV or die qq[Cannot open argument file\n];
open my $ofh, qq[>], shift @ARGV or die qq[Cannot open argument file\n];


## Read from input file ...
while ( <$ifh> ) { 

    ## Array with suffled characters.
    my @shuffle;

    ## Remove last newline character.
    chomp;

    ## Create an array with chars of input string.
    my @f = split /;/;

    ## Repeat: Shuffle array until no char keeps
    ## its original position.
    SHUFFLE: while ( 1 ) { 
        @shuffle = shuffle @f; 
        for my $i ( 0 .. $#f ) { 
            next SHUFFLE if $shuffle[ $i ] eq $f[ $i ];
        }   
        last;
    }   

    ## Print shuffled array.
    printf $ofh qq[%s\n], join qq[;], @shuffle;
}

Содержимое infile:

&#x020AE;&#x0201E;&#x0202E;&#x02033;&#x020DD;&#x010AE;&#x200AE;&#x0009E;
&#x02043;&#x02099;&#x0ABCD;&#x02033;&#x020DD;

Запустить сценарий с правильными аргументами:

perl script.pl infile outfile

и содержимым outfile после выполнения:

&#x020DD;&#x010AE;&#x02033;&#x0009E;&#x0201E;&#x020AE;&#x0202E;&#x200AE
&#x02099;&#x0ABCD;&#x02033;&#x020DD;&#x02043
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...