2015-01-17 4 views
-1

키를 사용하여 원래 상태로 되돌릴 수있는 C# ArrayList에서 뒤집을 셔플 알고리즘을 어떻게 코딩합니까?키를 사용하는 Arraylist Shuffle 알고리즘

+0

이를 되돌릴 수 있는지 걱정하는 대신 ori 사본을 저장하는 것이 훨씬 간단합니다. ginal 상태. –

+0

Matt가 이미 말한 이후의 대체 제안 : 인덱스 0, ..., n을 저장하는 두 번째 배열을 만듭니다. 다른 배열 (n)의 길이로 초기화 한 다음 색인 배열을 임의로 섞습니다. 임의의 순서로 첫 번째 배열에 액세스하려면 임의 순서로 배열 된 인덱스 배열을 사용하여 원래 항목을 찾으십시오. – john

+1

왜 downvotes? – Cullub

답변

0
private class myItem 
    { 
     public Int32 ID { get; set; } 
     public Int32 Rand { get; set; } 
     public String Value { get; set; } 

    } 

    private void Main(object sender, EventArgs e) 
    { 

     string[] array = new string[] { "alpha", "beta", "gamma", "delta" }; 
     List<myItem> myArray = addKeys(array);//adds keys to array required for randomization and reversing 
     string[] randomarray = randomize(myArray); 
     string[] reversedarray = reverse(myArray); 

    } 
    private List<myItem> addKeys(string[] array) 
    { 
     Random random = new Random(); 
     List<myItem> myArr = new List<myItem>(); 
     for (int i = 0; i < array.Length; i++) 
     { 
      myArr.Add(new myItem { ID = i, Rand = random.Next(), Value = array[i] }); 

     } 
     return myArr; 
    } 
    private string[] randomize(List<myItem> myArray) 
    { 
     return (from item in myArray 
         orderby item.Rand 
         select item.Value).ToArray(); 
    } 
    private string[] reverse(List<myItem> myArray) 
    { 
     return (from item in myArray 
         orderby item.ID 
         select item.Value).ToArray(); 
    } 
0

KeyValuePair를 사용할 수 있습니다. 다음 사이트에서 자세한 설명을 볼 수 있습니다. http://www.dotnetperls.com/shuffle

그러나 역순으로 사용하려면 DataTable을 사용하는 것이 좋습니다. 첫 번째 열에서는 원래 정렬 순서 (정수가 될 수 있음)를 가질 수 있고 두 번째 열에서는 임의의 숫자를 만들 수 있습니다. 세 번째 열에서 정렬해야하는 값을 가질 수 있습니다. 그런 다음 두 번째 열의 정렬을 사용하여 순서를 변경 한 다음 첫 번째 열을 기준으로 정렬하여 되돌립니다.

+0

자사의 가역적이 아닙니다 – CarlesBerg

+0

코드를 공유하십시오 – CarlesBerg

0

여기에는 셔플 알고리즘을 변경하지 않고 "키"만 저장하면되는 간단한 방법이 있습니다.

동일한 키 또는 시드를 사용하고 셔플 알고리즘을 두 번 실행하면 두 번 똑같은 방식으로 셔플됩니다. 즉, 재생할 수있는 한 어떤 셔플 알고리즘을 사용하든 상관 없습니다.

shuffle 알고리즘에 키 또는 시드를 사용하면 그렇게 할 수 있습니다.

뒤집기 위해 수행해야하는 작업은 정수 배열을 임의로 섞는 것입니다. 여기서 셔플 이전 배열의 값은 각 요소의 인덱스에 해당합니다. 위와 동일한 키 또는 시드를 사용하여 셔플을 한 후에는 셔플 된 복사본이 생깁니다. 각 값은 변경되지 않은 배열의 원래 배치에 대한 인덱스입니다.

예를 들어 설명해 드리겠습니다.

0부터 3까지의 4 개의 정수 배열 (인덱스 0의 요소 값은 0이고 인덱스 1의 요소 값은 1 등)을 가정 해 봅시다.

이 배열 얻었다이 셔플 : 3, 1, 2, 0

이 현재 인덱스 3에서 예전 셔플 어레이의 첫 번째 요소는, 두 번째 요소의 인덱스는 1임을 의미 인덱스 2의 세번째 인덱스 0

+0

:) – CarlesBerg

+0

아이디어가 좋지만 설명이 잘못되었습니다. 요구 사항은 (동일한 입력, 동일한 키)가 (동일한 순서 뒤섞기) 제공하지만 다른 입력, 동일한 키에 적용한다는 것입니다. 이 시나리오에서는 (동일한 셔플 순서) 보장되지 않습니다. 나는 네가 네 조건을 강화해야한다고 생각해. –

+0

나는 "입력"에 의해 내가 핵심 또는 씨앗을 의미하고, 섞여있는 요소가 아니라는 말을 다시 할 것이다. –

0

Shuffling 배열 어레이 수회 내부의 요소를 교체함으로써 수행시 제.

배열을 가져온 경우 요소를 교체 한 다음 다시 바꿔 넣으십시오.하지만 역순으로 처음 배열을 바꾼 경우 원본 배열이 다시 나타납니다.

이 셔플 링 위치는 PRNG (Pseudorandom number generator)에서 생성 할 수 있습니다. 주어진 seed의 경우 PNRG은 항상 동일한 숫자를 생성합니다. 즉 "키"가됩니다.여기

은 ( Fisher Yates는 셔플에 사용되는) 그 아이디어를 사용하여 일부 코드 :

public static void Shuffle(ArrayList list, int seed, bool reverse = false) 
{   
    Random rng = new Random(seed); 
    List<Tuple<int, int>> swaps = new List<Tuple<int, int>>(); 
    int n = list.Count; 

    //prepare swapping positions 
    while (n > 1) { 
     n--; 
     int k = rng.Next(n + 1); 
     swaps.Add(new Tuple<int, int>(k, n)); 
    } 

    //reverse if needed 
    if(reverse) 
     swaps.Reverse(); 

    //swap the items 
    foreach(Tuple<int, int> swap in swaps) 
    {  
     object value = list[swap.Item1]; 
     list[swap.Item1] = list[swap.Item2]; 
     list[swap.Item2] = value; 
    } 
} 

사용법 : 당신이 원하지 않는 경우 키가 정수가 될 것을

ArrayList a = new ArrayList(); 
int key = 2742; 

Shuffle(a, key); 
Shuffle(a, key, true); 

주 문자열이지만 똑같은 방법을 사용할 수도 있지만 정수를 사용하면됩니다. "somekey".GetHashCode()