Task: Card shuffles



C#: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CardShuffles {
    public static class Helper {
        public static string AsString<T>(this ICollection<T> c) {
            StringBuilder sb = new StringBuilder("[");
            sb.Append(string.Join(", ", c));
            return sb.Append("]").ToString();
        }
    }

    class Program {
        private static Random rand = new Random();

        public static List<T> riffleShuffle<T>(ICollection<T> list, int flips) {
            List<T> newList = new List<T>(list);

            for (int n = 0; n < flips; n++) {
                
                int cutPoint = newList.Count / 2
                    + (rand.Next(0, 2) == 0 ? -1 : 1) * rand.Next((int)(newList.Count * 0.1));

                
                List<T> left = new List<T>(newList.Take(cutPoint));
                List<T> right = new List<T>(newList.Skip(cutPoint));

                newList.Clear();

                while (left.Count > 0 && right.Count > 0) {
                    
                    
                    
                    if (rand.NextDouble() >= ((double)left.Count / right.Count) / 2) {
                        newList.Add(right.First());
                        right.RemoveAt(0);
                    }
                    else {
                        newList.Add(left.First());
                        left.RemoveAt(0);
                    }
                }

                
                if (left.Count > 0) newList.AddRange(left);
                if (right.Count > 0) newList.AddRange(right);
            }

            return newList;
        }

        public static List<T> overhandShuffle<T>(List<T> list, int passes) {
            List<T> mainHand = new List<T>(list);

            for (int n = 0; n < passes; n++) {
                List<T> otherHand = new List<T>();

                while (mainHand.Count>0) {
                    
                    int cutSize = rand.Next((int)(list.Count * 0.2)) + 1;

                    List<T> temp = new List<T>();

                    
                    for (int i = 0; i < cutSize && mainHand.Count > 0; i++) {
                        temp.Add(mainHand.First());
                        mainHand.RemoveAt(0);
                    }

                    
                    if (rand.NextDouble()>=0.1) {
                        
                        temp.AddRange(otherHand);
                        otherHand = temp;
                    }
                    else {
                        
                        otherHand.AddRange(temp);
                    }
                }

                
                mainHand = otherHand;
            }

            return mainHand;
        }

        static void Main(string[] args) {
            List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
            Console.WriteLine(list.AsString());
            list = riffleShuffle(list, 10);
            Console.WriteLine(list.AsString());
            Console.WriteLine();

            list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
            Console.WriteLine(list.AsString());
            list = riffleShuffle(list, 1);
            Console.WriteLine(list.AsString());
            Console.WriteLine();

            list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
            Console.WriteLine(list.AsString());
            list = overhandShuffle(list, 10);
            Console.WriteLine(list.AsString());
            Console.WriteLine();

            list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
            Console.WriteLine(list.AsString());
            list = overhandShuffle(list, 1);
            Console.WriteLine(list.AsString());
            Console.WriteLine();
        }
    }
}


Go: package main

import (
    "fmt"
    "math/rand"
    "time"
)

func reverse(s []int) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}

func riffle(deck []int, iterations int) []int {
    le := len(deck)
    pile := make([]int, le)
    copy(pile, deck)
    for i := 0; i < iterations; i++ {
        mid := le / 2
        tenpc := mid / 10
        
        cut := mid - tenpc + rand.Intn(2*tenpc+1)
        
        deck1 := make([]int, cut)
        deck2 := make([]int, le-cut)
        copy(deck1, pile[:cut])
        copy(deck2, pile[cut:])
        pile = pile[:0]
        fromTop := rand.Intn(2) 
        for len(deck1) > 0 && len(deck2) > 0 {
            if fromTop == 1 {
                el1 := deck1[0]
                deck1 = deck1[1:]
                el2 := deck2[0]
                deck2 = deck2[1:]
                pile = append(pile, el1, el2)
            } else {
                el1 := deck1[len(deck1)-1]
                deck1 = deck1[:len(deck1)-1]
                el2 := deck2[len(deck2)-1]
                deck2 = deck2[:len(deck2)-1]
                pile = append(pile, el1, el2)
            }
        }
        
        if len(deck1) > 0 {
            pile = append(pile, deck1...)
        } else if len(deck2) > 0 {
            pile = append(pile, deck2...)
        }
        reverse(pile) 
    }
    return pile
}

func overhand(deck []int, iterations int) []int {
    le := len(deck)
    pile := make([]int, le)
    copy(pile, deck)
    pile2 := make([]int, 0)
    twentypc := le / 5
    for i := 0; i < iterations; i++ {
        for len(pile) > 0 {
            cards := 1 + rand.Intn(twentypc)
            if cards > len(pile) {
                cards = len(pile)
            }
            temp := make([]int, cards)
            copy(temp, pile[:cards])
            pile2 = append(temp, pile2...)
            pile = pile[cards:]
        }
        pile = append(pile, pile2...)
        pile2 = pile2[:0]
    }
    return pile
}

func main() {
    rand.Seed(time.Now().UnixNano())
    fmt.Println("Starting deck:")
    deck := make([]int, 20)
    for i := 0; i < 20; i++ {
        deck[i] = i + 1
    }
    fmt.Println(deck)
    const iterations = 10
    fmt.Println("\nRiffle shuffle with", iterations, "iterations:")
    fmt.Println(riffle(deck, iterations))
    fmt.Println("\nOverhand shuffle with", iterations, "iterations:")
    fmt.Println(overhand(deck, iterations))
    fmt.Println("\nStandard library shuffle with 1 iteration:")
    rand.Shuffle(len(deck), func(i, j int) {
        deck[i], deck[j] = deck[j], deck[i] 
    })
    fmt.Println(deck)
}