Task: Card shuffles


C++: #include <time.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <deque>


class riffle
{
public:
    void shuffle( std::deque<int>* v, int tm )
    {
        std::deque<int> tmp;
	bool fl;
	size_t len;
	std::deque<int>::iterator it;

	copyTo( v, &tmp );

	for( int t = 0; t < tm; t++ )
	{
	    std::deque<int> lHand( rand() % ( tmp.size() / 3 ) + ( tmp.size() >> 1 ) ), rHand( tmp.size() - lHand.size() );

	    std::copy( tmp.begin(), tmp.begin() + lHand.size(), lHand.begin() );
	    std::copy( tmp.begin() + lHand.size(), tmp.end(), rHand.begin() );
	    tmp.clear();

	    while( lHand.size() && rHand.size() )
	    {
		fl = rand() % 10 < 5;
		if( fl )
    		    len = 1 + lHand.size() > 3 ? rand() % 3 + 1 : rand() % ( lHand.size() ) + 1;
		else
		    len = 1 + rHand.size() > 3 ? rand() % 3 + 1 : rand() % ( rHand.size() ) + 1;

		while( len )
		{
		    if( fl ) 
		    {
			tmp.push_front( *lHand.begin() );
			lHand.erase( lHand.begin() );
		    }
		    else 
		    {
			tmp.push_front( *rHand.begin() );
			rHand.erase( rHand.begin() );
		    }
		    len--;
		}
	    }

	    if( lHand.size() < 1 ) 
	    {
		for( std::deque<int>::iterator x = rHand.begin(); x != rHand.end(); x++ )
		    tmp.push_front( *x );
	    }
	    if( rHand.size() < 1 ) 
	    {
		for( std::deque<int>::iterator x = lHand.begin(); x != lHand.end(); x++ )
		    tmp.push_front( *x );
	    }
	}
	copyTo( &tmp, v );
    }
private:
    void copyTo( std::deque<int>* a, std::deque<int>* b )
    {
	for( std::deque<int>::iterator x = a->begin(); x != a->end(); x++ )
	    b->push_back( *x );
	a->clear();
    }
};

class overhand
{
public:
    void shuffle( std::deque<int>* v, int tm )
    {
	std::deque<int> tmp;
	bool top;
	for( int t = 0; t < tm; t++ )
	{
	    while( v->size() )
	    {
		size_t len = rand() % ( v->size() ) + 1;
		top = rand() % 10 < 5;
		while( len )
		{
		    if( top ) tmp.push_back( *v->begin() );
		    else tmp.push_front( *v->begin() );
		    v->erase( v->begin() );
		    len--;
		}
	    }
	    for( std::deque<int>::iterator x = tmp.begin(); x != tmp.end(); x++ )
		v->push_back( *x );

	    tmp.clear();
	}
    }
};


std::deque<int> cards;

void fill()
{
    cards.clear();
    for( int x = 0; x < 20; x++ )
	cards.push_back( x + 1 );
}

void display( std::string t )
{
    std::cout << t << "\n";
    for( std::deque<int>::iterator x = cards.begin(); x != cards.end(); x++ )
	std::cout << *x << " ";
    std::cout << "\n\n";
}

int main( int argc, char* argv[] )
{
    srand( static_cast<unsigned>( time( NULL ) ) );
    riffle r; overhand o;	

    fill(); r.shuffle( &cards, 10 ); display( "RIFFLE" );
    fill(); o.shuffle( &cards, 10 ); display( "OVERHAND" );
    fill(); std::random_shuffle( cards.begin(), cards.end() ); display( "STD SHUFFLE" );

    return 0;
}







VB: Imports System.Runtime.CompilerServices
Imports System.Text

Module Module1

    <Extension()>
    Function AsString(Of T)(c As ICollection(Of T)) As String
        Dim sb = New StringBuilder("[")
        sb.Append(String.Join(", ", c))
        Return sb.Append("]").ToString()
    End Function

    Private rand As New Random()

    Function RiffleShuffle(Of T)(list As ICollection(Of T), flips As Integer) As List(Of T)
        Dim newList As New List(Of T)(list)

        For n = 1 To flips
            
            Dim cutPoint As Integer = newList.Count / 2 + If(rand.Next(0, 2) = 0, -1, 1) * rand.Next(newList.Count * 0.1)

            
            Dim left As New List(Of T)(newList.Take(cutPoint))
            Dim right As New List(Of T)(newList.Skip(cutPoint))

            newList.Clear()

            While left.Count > 0 AndAlso right.Count > 0
                
                
                
                If rand.NextDouble() >= left.Count / right.Count / 2 Then
                    newList.Add(right.First())
                    right.RemoveAt(0)
                Else
                    newList.Add(left.First())
                    left.RemoveAt(0)
                End If
            End While

            
            If left.Count > 0 Then
                newList.AddRange(left)
            End If
            If right.Count > 0 Then
                newList.AddRange(right)
            End If
        Next

        Return newList
    End Function

    Function OverhandShuffle(Of T)(list As ICollection(Of T), passes As Integer) As List(Of T)
        Dim mainHand As New List(Of T)(list)

        For n = 1 To passes
            Dim otherhand = New List(Of T)

            While mainHand.Count > 0
                
                Dim cutSize = rand.Next(list.Count * 0.2) + 1

                Dim temp = New List(Of T)

                
                Dim i = 0
                While i < cutSize AndAlso mainHand.Count > 0
                    temp.Add(mainHand.First())
                    mainHand.RemoveAt(0)
                    i = i + 1
                End While

                
                If rand.NextDouble() >= 0.1 Then
                    
                    temp.AddRange(otherhand)
                    otherhand = temp
                Else
                    
                    otherhand.AddRange(temp)
                End If
            End While

            
            mainHand = otherhand
        Next

        Return mainHand
    End Function

    Sub Main()
        Dim list = New List(Of Integer)(Enumerable.Range(1, 20))
        Console.WriteLine(list.AsString())
        list = RiffleShuffle(list, 10)
        Console.WriteLine(list.AsString())
        Console.WriteLine()

        list = New List(Of Integer)(Enumerable.Range(1, 20))
        Console.WriteLine(list.AsString())
        list = RiffleShuffle(list, 1)
        Console.WriteLine(list.AsString())
        Console.WriteLine()

        list = New List(Of Integer)(Enumerable.Range(1, 20))
        Console.WriteLine(list.AsString())
        list = OverhandShuffle(list, 10)
        Console.WriteLine(list.AsString())
        Console.WriteLine()

        list = New List(Of Integer)(Enumerable.Range(1, 20))
        Console.WriteLine(list.AsString())
        list = OverhandShuffle(list, 1)
        Console.WriteLine(list.AsString())
        Console.WriteLine()
    End Sub

End Module