Skip to content

Stateless, parallelizable, keyed, random accesible, reversible shuffle module.

License

Notifications You must be signed in to change notification settings

vmunoz82/shuffle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

shuffle

This golang module should be used to produce a shuffled set using a Feistel network.

The algorithm has the following features:

  • Performs the shuffle in a complete stateless form (ie.: there is no need for an input, even neither an out set), as you can traverse a channel with each of the output elements.
  • It can run it safely in parallel which is not possible with algorithms that need to perform swap to elements of an array.
  • It is keyed so you can provide a seed (in form of a Feistel function and round keys) to recall the shuffle order.
  • It is random accessible so if you need very few shuffles elements of a large set you only ask those.
  • It is reversible so given a shuffled value you can obtain the original unshuffled value.

Installation

go get github.com/vmunoz82/shuffle

Examples

To shuffle elements of the range [1000, 1020)

package main

import (
        "github.com/vmunoz82/shuffle"
        "fmt"
)

var keys = []shuffle.FeistelWord{
        0xA45CF355C3B1CD88,
        0x8B9271CC2FC9365A,
        0x33CD458F23C816B1,
        0xC026F9D152DE23A9}

/* Function for each round, could be anything don't need to be reversible */
func roundFunction(v, key shuffle.FeistelWord) shuffle.FeistelWord {
        return (v * 941083987) ^ (key >> (v & 7) * 104729)
}

func main() {
        s, _ := shuffle.Shuffle(1000, 1020, shuffle.NewFeistel(keys, roundFunction))
        for v := range s {
                fmt.Println(v)
        }
}

This will output

1003
1005
1006
1009
1004
1011
1008
1016
1010
1001
1017
1000
1013
1012
1015
1014
1007
1002
1018
1019

In this example it will generate the first shuffled value for the range [0, 1000), that is the value 846, and next we made the inverse operation, given the value 846 asks for which element of the original set produce it.

package main

import (
        "fmt"
        "github.com/vmunoz82/shuffle"
)

var keys = []shuffle.FeistelWord{
        0xA45CF355C3B1CD88,
        0x8B9271CC2FC9365A,
        0x33CD458F23C816B1,
        0xC026F9D152DE23A9}

/* Function for each round, could be anything don't need to be reversible */
func roundFunction(v, key shuffle.FeistelWord) shuffle.FeistelWord {
        return (v * 941083987) ^ (key >> (v & 7) * 104729)
}

func main() {
        fn := shuffle.NewFeistel(keys, roundFunction)
        v, _ := shuffle.RandomIndex(0, 1000, fn)
        fmt.Println(v)
        v, _ = shuffle.GetIndex(846, 1000, fn)
        fmt.Println(v)
}

This example will output

846
0

About

Stateless, parallelizable, keyed, random accesible, reversible shuffle module.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages