Skip to content
This repository was archived by the owner on Dec 12, 2023. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions solutions/go/string-permutations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import (
"fmt"
"sort"
)

/****************************************************************************
Generates permutations of sortable sequence changing it in place.
****************************************************************************/

// PermutationsIter returns a closure, each call to the returned function
// generates the next permutations of the sequence (changing it in place).
// Uses Non-recursive lexicographic order (Knuth's L-Algorithm), thus
// the sequence passed as argument must be sortable.
func PermutationsIter(a sort.Interface) func() bool {
current := int64(0)
n := a.Len()
return func() bool {
if current == 0 {
sort.Sort(a)
current++
return true
}
// Find largest index k such that a[k] < a[k + 1]
k := -1
for j := n - 2; j >= 0; j-- {
if a.Less(j, j+1) {
k = j
break
}
}
if k == -1 { // if k not found, all done
return false
}
// Find largest index l greater than k such that a[k] < a[l]
l := -1
for j := n - 1; j >= k+1; j-- {
if a.Less(k, j) {
l = j
break
}
}
// swap a[k] <-> a[l]
a.Swap(k, l)
// Reverse a[k+1:n]
for i, j := k+1, n-1; i < j; i, j = i+1, j-1 {
a.Swap(i, j)
}
current++
return true
}
}

/*************** Create a sortable type ***************/

// MyPermSeq satisfy interface sort.Interface
type MyPermSeq []byte

// Len of the sequence
func (ps MyPermSeq) Len() int {
return len(ps)
}

// Less implements <
func (ps MyPermSeq) Less(i, j int) bool {
return ps[i] < ps[j]
}

// Swap in place
func (ps MyPermSeq) Swap(i, j int) {
ps[i], ps[j] = ps[j], ps[i]
}

func main() {

// Let's permutate ABCD in-place: output will be ordered in lexicographical order
mySeq := MyPermSeq([]byte("ABCD"))
next := PermutationsIter(mySeq)
fmt.Println("Generating permutations for", string(mySeq), ": ")
for next() {
fmt.Print(string(mySeq), " ")
}
fmt.Println("")

// Let's permutate ABBB in-place: shows algorithm handles repeated elements well
mySeq = MyPermSeq([]byte("ABBB"))
next = PermutationsIter(mySeq)
fmt.Println("Generating permutations for", string(mySeq), ": ")
for next() {
fmt.Print(string(mySeq), " ")
}
fmt.Println("")

}