Card Shuffle (SPOJ / Interviewstreet)

This question was asked before, but none of them received a definitive answer, and I tried to collect all the information I found here. Feel free to merge / switch to another stackexchange site if necessary.

Here are the questions I found in connection with this:

The problem was originally posted as Sprint Sprinter Sprinter, but now it is listed as a problem with practice . It has also been ported to SPOJ .

Here is a description of the problem:

Here is the N-card shuffling algorithm:

1) Cards are divided into K equal piles.

2) The bottom N / K cards belong to heap 1 in the same order (so the bottom card of the starting heap is the bottom card of heap 1).

3) The following N / K cards from the bottom belong to heap 2, etc.

4) Now the top card of the shuffled heap is the top card of pile 1. The next card is the top card of piles 2, ..., the card Kth of the shuffled heap is the top> card of piles K. Then the (K + 1) -th card is a card , which is now at the top of pile 1, (K + 2) nd is the card that is now at the top of pile 2, etc.

For example, if N = 6 and K = 3, the order of the deck of cards "ABCDEF" (from top to bottom) during shuffling will be changed to "ECAFDB" once.

Given N and K, what is the minimum number of transfers required after the heap is returned to its original order?

Input: the first line contains the number of test cases T. The next T lines contain two integers N and K.

Output: output lines T, one for each test case containing the minimum required amount of shuffling. If the deck never returns to its original order, output -1.

Limitations:

  • K is a factor of N.
  • T <= 10000
  • 2 <= K <= N <= 10 ^ 9

Spoiler warning - do not read below if you want to solve it yourself.

The problem can be translated as:

Find the number of times you need to complete a K-shaped (perfect) in-shuffle to restore a deck of N cards to its original order.

I decided two approaches to solving this problem. The first approach that came to mind was as follows:

  • find the formula that, for a given position in the initial order, will create the next map the next position
  • use the formula to determine the number of shuffles that each card takes from the first pile (n / k in size) to return to its original position.
  • returns the smallest total multiple of the number of shuffles defined previously

The complexity of this solution is O (n / k + max_number_of_suhffles). Here is the actual implementation . The problem is that it exceeds the maximum time, so I started looking for a formula that would allow me to get the number in almost constant time.

The most that I could optimize here (for example, use some cards to cache calculated values ​​in the same permutation cycle, etc.) was to pass the 3/10 interview test.


I found this implementation , which suggests that the amount of shuffling needed to return to its original state is the multiplicative order of K relative to N + 1. From the wiki:

As a consequence of Lagrange theorem, ordn(a) always divides φ(n). 

φ (n) is the Euler tolerance function , ordn is the order of the groups - what we are looking for. I found this article that uses φ to calculate the number of shuffles, but this is only for 2-way in-shuffle, not k-way.

Here are the steps for this implementation:

  • pre-computed list of primes <100,000
  • calculated φ(N+1) from its simple factors.
  • defined all factors φ(N + 1) , combining its prime factors in all possible ways.
  • tried each factor in turn and got the smallest of them, x , which checks k ^ x % N + 1 = 1

This implementation is also hosted on GitHub .

This works very fast, but the automatic grader gives me the “wrong answer” for 9 out of 10 tests, both in SPOJ and in the interview.

I tried to compare the result of two implementations, but for the test boxes I entered (known result and random), the two implementations always output the same thing. This is strange, since I am sure that the first algorithm is correct, I assume that the second should also be.

The “incorrect answer” classification may occur due to a code runtime error, but nothing jumps out as a possible reason for this.

I did not take into account the case when no number shuffling can return the deck to its original state - I understand that this is impossible. The final number of perfect shuffles will ultimately restore the original order, although the number of shuffles can be really high.

If you took the time to read this, thanks. :) I'm curious about the problem, I would like it to be resolved.

+6
source share
3 answers

This is what I came up with after some of the comments I made on paper.

 class CardShuffle { private long k; private long n; private long kn; private long kn2; public CardShuffle(long k, long n) { //I omitted some checks done here this.k = k; this.n = n; this.kn = k / n; this.kn2 = k - kn; } public long shuffle() { long count = 0L; long next = 0L; do { //this can be further optimized next = kn2 - kn * (next % n) + (next / n); ++count; } while((next != 0L) && (count < k)); if(count > k) return -1; return count; } } 

Results...

 Testing 1000000 : 2 #ms: 3.121905 #ms: 1424.487191 #1: 9900 #2: 9900 Testing 1000000 : 5 #ms: 1.409955 #ms: 556.329366 #1: 2475 #2: 2475 Testing 1000000 : 10 #ms: 0.007823 #ms: 186.797204 #1: 12 #2: 12 Testing 1000000 : 20 #ms: 0.590298 #ms: 275.751527 #1: 4950 #2: 4950 Testing 1000000 : 25 #ms: 0.298642 #ms: 260.559372 #1: 2475 #2: 2475 Testing 1000000 : 40 #ms: 1.187581 #ms: 241.956729 #1: 9900 #2: 9900 Testing 1000000 : 50 #ms: 1.187581 #ms: 241.015548 #1: 9900 #2: 9900 Testing 9999999 : 41841 #ms: 14.499887 #ms: 1829.868042 #1: 125000 #2: 125000 Testing 9999999 : 3333333 #ms: 58.119398 #ms: 311.005728 #1: 500000 #2: 500000 Testing 9999999 : 13947 #ms: 52.704185 #ms: 2095.336418 #1: 500000 #2: 500000 

checked on this input ...

 10 1000000 2 1000000 5 1000000 10 1000000 20 1000000 25 1000000 40 1000000 50 9999999 41841 9999999 3333333 9999999 13947 

The first #ms is the time in milliseconds that my method took, the second is yours. #1 and #2 are the results, respectively.

Where - as for this input ...

 15 1000000000 2 1000000000 5 1000000000 10 1000000000 20 1000000000 25 1000000000 40 1000000000 50 1000000000 1000 1000000000 200000000 1000000000 250000000 1000000000 500000000 1000000000 50000000 999999999 1001001 999999999 37037037 999999999 333333333 

My method finds a solution in

 Testing 1000000000 : 2 #ms: 71.360466 #1: 525780 Testing 1000000000 : 5 #ms: 68.987259 #1: 525780 Testing 1000000000 : 10 #ms: 0.008381 #1: 18 Testing 1000000000 : 20 #ms: 75.608492 #1: 525780 Testing 1000000000 : 25 #ms: 31.843154 #1: 262890 Testing 1000000000 : 40 #ms: 33.014531 #1: 262890 Testing 1000000000 : 50 #ms: 84.27384 #1: 525780 Testing 1000000000 : 1000 #ms: 0.006705 #1: 6 Testing 1000000000 : 200000000 #ms: 53.991778 #1: 525780 Testing 1000000000 : 250000000 #ms: 43.765898 #1: 262890 Testing 1000000000 : 500000000 #ms: 54.457201 #1: 525780 Testing 1000000000 : 50000000 #ms: 68.080999 #1: 525780 Testing 999999999 : 1001001 #ms: 115.060154 #1: 1000000 Testing 999999999 : 37037037 #ms: 5783.539528 #1: 50000000 Testing 999999999 : 333333333 #ms: 5391.880532 #1: 50000000 

while you lose memory on the very first, on my old and slow laptop.

I have not yet confirmed this approach, but it looks like it works. You can try and see if it works on some inputs. I will be grateful.

If you are interested in how I developed the formula, leave a comment.

I also presented a solution for the survey, but he could not perform the 4th test test due to the time limit.

I will try with program c very soon and report here.

+3
source

Given N and K, work out what permutation produces and determine how it looks in http://en.wikipedia.org/wiki/Cycle_notation . In a cycle designation, permutation is the product of disjoint cycles, for example. ABCDEF => ECAFDB (AEDFBC) because A-> E-> D-> F-> B-> C-> A. If your permutation is a single loop like this, the length of the loop is the number of times you you need to repeat it to return to the same place. If the permutation is the product of several disjoint loops, such as (ABC) (DE) (F), the number of times you need to repeat is http://en.wikipedia.org/wiki/Least_common_multiple of the lengths of the individual loops.

0
source
 #include <iostream> using namespace std; int main() { int t, m , n, c, p, k, pos, cases; cin>>cases; while(cases--) { cin>>t; cin>>k; p = t/k; pos = 1; c = 0; do { c++; m = (pos - 1)%p + 1; n = k - (pos - m)/p; pos = k*(m-1) + n; }while(pos!=1); cout<<c<<endl; } return 0; } 
-1
source

Source: https://habr.com/ru/post/923331/


All Articles