All Elements in Two Binary Search Trees - go

I wrote a code for All Elements in Two Binary Search Trees problem on leetcode:
https://leetcode.com/problems/all-elements-in-two-binary-search-trees/
I couldn't find anyone else trying to solve it this way. I know that this code could be improved with helper() function, but the main problem is sorting, is there some elegant way to avoid it while walking both trees at the same time? See line with sort.Ints(curr).
What I'm looking for is a way to walk 2 trees at the same time and fill the answer array directly in sorted order, without additional arrays.
func getAllElements(root1 *TreeNode, root2 *TreeNode) []int {
if root1 == nil && root2 == nil {
return []int{}
} else if root1 != nil && root2 != nil {
curr := getAllElements(root1.Left, root2.Left)
if root1.Val < root2.Val {
curr = append(curr, root1.Val)
curr = append(curr, root2.Val)
} else {
curr = append(curr, root2.Val)
curr = append(curr, root1.Val)
}
curr = append(curr, getAllElements(root1.Right, root2.Right)...)
sort.Ints(curr) //no TLE, but how to walk both trees at the same time, like in this code, to avoid this sorting?
return curr
} else if root1 != nil {
curr := getAllElements(root1.Left, nil)
curr = append(curr, root1.Val)
curr = append(curr, getAllElements(root1.Right, nil)...)
return curr
} else if root2 != nil {
curr := getAllElements(nil, root2.Left)
curr = append(curr, root2.Val)
curr = append(curr, getAllElements(nil, root2.Right)...)
return curr
}
return []int{}
}

This is a solution for 1305. All Elements in Two Binary Search Trees
func getAllElements(root1 *TreeNode, root2 *TreeNode) []int {
if root1 == nil && root2 == nil {
return nil
}
var list1 []int
if root1 != nil {
list1 = inOrder(root1, list1)
}
var list2 []int
if root2 != nil {
list2 = inOrder(root2, list2)
}
if len(list1) == 0 {
return list2
}
if len(list2) == 0 {
return list1
}
var list3 []int
for i, j := 0, 0;; {
var elem1 int
if len(list1) > i {
elem1 = list1[i]
} else {
// we add the remaining elements from list2 into list3
// there are no elements in list1
if len(list2) > j {
list3 = append(list3, list2[j:]...)
break
}
}
var elem2 int
if len(list2) > j {
elem2 = list2[j]
} else {
// we add the remaining elements from list1 into list3
// there are no elements in list2
if len(list1) > i {
list3 = append(list3, list1[i:]...)
break
}
}
if elem1 < elem2 {
list3 = append(list3, elem1)
i++
} else {
list3 = append(list3, elem2)
j++
}
}
return list3
}
func inOrder(node *TreeNode, list []int) []int {
if node.Left != nil {
list = inOrder(node.Left, list)
}
list = append(list, node.Val)
if node.Right != nil {
return inOrder(node.Right, list)
}
return list
}

Why would you need to do any sorting at all? By definition, binary trees are ordered. All you have to do is
Walk each tree, producing a list containing that tree's contents.
You now have two ordered lists.
Merge them to produce a single, ordered list.
Let us assume we have a tree struct, thus:
type tree *struct {
left tree
right tree
payload int
}
Walking such a binary tree to produce an ordered list is trivial:
func treeToSlice(root tree) []int {
arr := make([]int, 0)
var visit func(tree)
visit = func(curr tree) {
if curr.left != nil {
visit(curr.left)
}
arr = append(arr, curr.payload)
if curr.right != nil {
visit(curr.right)
}
}
visit(root)
return arr
}
Merging two such ordered lists is likewise trivial:
func merge( a []int, b []int ) []int {
c := make([]int, len(a)+len(b)) // merged list to be returned
i := 0 // current element of A
j := 0 // current element of B
k := 0 // current element of C
// while we have both A and B...
for ; i < len(a) && j < len(b) ; k++ {
if a[i] <= b[j] {
c[k] = a[i]
i++
} else {
c[k] = b[j]
j++
}
}
// if we have any As left....
for ; i < len(a) ; k++ {
c[k] = a[i]
i++
}
// if we have any Bs left...
for ; j < len(b) ; k++ {
c[k] = b[j]
j++
}
return c
}
And with those, converting two binary trees into a single ordered list is... triviality itself:
func twoBTreesToOrderedSlice( t1 tree, t2 tree ) []int {
return merge(
treeToSlice( t1 ),
treeToSlice( t2 ),
)
}
While you could use goroutines and channels to walk the trees in parallel, but the code is no more "elegant", and due to channel overhead and the cost of synchronization, it's virtually guaranteed to be less performant than the simpler "walk each tree to build ordered lists and then merge the two ordered lists.
I suppose, though, it probably saves a little space.
type tree *struct {
left tree
right tree
payload int
}
func walkTree( root tree, ch chan int ) {
var visit func(tree)
visit = func(node tree) {
if node != nil {
visit(node.left)
ch <- node.payload
visit(node.right)
}
}
visit(root)
close(ch)
}
func btreesToOrderedSlice( t1 tree, t2 tree ) []int {
arr := make([]int, 0)
ch1 := make(chan int)
ch2 := make(chan int)
go walkTree(t1, ch1)
go walkTree(t2, ch2)
x, haveX := <-ch1
y, haveY := <-ch2
for haveX && haveY {
if x <= y {
arr = append(arr, x)
x, haveX = <-ch1
} else {
arr = append(arr, y)
y, haveY = <-ch2
}
}
for x = range ch1 {
arr = append(arr, x)
}
for y = range ch2 {
arr = append(arr, y)
}
return arr
}

Related

Climbing The Leaderboard Hackerrank Solutions in Golang

Clue :
An arcade game player wants to climb to the top of the leaderboard and track their ranking. The game uses Dense Ranking, so its leaderboard works like this:
The player with the highest score is ranked number 1 on the leaderboard.
Players who have equal scores receive the same ranking number, and the next player(s) receive the immediately following ranking number.
This is my code solution for climbing the leaderboard, 8/12 test case is passed. but 4 case is timeout. any solution for boosting the performance of my code?
func contains(s []int32, e int32) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func remove(slice []int32, s int) []int32 {
return append(slice[:s], slice[s+1:]...)
}
func climbingLeaderboard(ranked []int32, player []int32) []int32 {
// Write your code here
for i := 0; i < len(ranked); i++ {
if contains(ranked[i+1:], ranked[i]) {
ranked = remove(ranked, i)
i--
}
}
sort.Slice(ranked, func(i, j int) bool { return ranked[i] < ranked[j] })
var result = make([]int32, len(player))
if len(ranked) == 1 {
for i := 0; i < len(player); i++ {
if player[i] > ranked[0] {
result[i] = 1
} else if player[0] == ranked[0] {
result[i] = 1
} else if player[0] < ranked[0] {
result[i] = 2
}
}
} else {
for i := 0; i < len(player); i++ {
l := len(ranked)
l32 := int32(l)
p := player[i]
var temp int32
for j := 1; j < l; j++ {
if p > ranked[j] {
temp = 1
} else if p > ranked[j-1] && p < ranked[j] {
temp = l32 - int32(j) + 1
break
} else if p == ranked[j-1] {
temp = l32 - int32(j) + 1
break
} else if p < ranked[j-1] {
temp = l32 + 1
break
}
}
result[i] = temp
temp = 0
}
}
return result
}
Your code to dedupe ranked is very inefficient.
func contains(s []int32, e int32) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func remove(slice []int32, s int) []int32 {
return append(slice[:s], slice[s+1:]...)
}
for i := 0; i < len(ranked); i++ {
if contains(ranked[i+1:], ranked[i]) {
ranked = remove(ranked, i)
i--
}
}
sort.Slice(ranked, func(i, j int) bool { return ranked[i] < ranked[j] })
Your code to search for player game ranks is not efficient.
Efficiency is not just what you do, it's also how many times you do it.
Your code is too complicated.
Here is some simple code that solves the challenge without triggering a timeout.
import (
"sort"
)
func climbingLeaderboard(ranked []int32, player []int32) []int32 {
ranks := ranked[:1]
last := ranks[0]
for _, score := range ranked[1:] {
if score != last {
ranks = append(ranks, score)
}
last = score
}
climb := make([]int32, 0, len(player))
for _, score := range player {
rank := sort.Search(
len(ranks),
func(i int) bool { return ranks[i] <= score },
)
climb = append(climb, int32(rank+1))
}
return climb
}

LeetCode question Path Sum II: Recursive solution bug

I have submitted the below solution for the question in golang and it fails for the base case. I am not able to figure out why it is failing.
var answer[][]int
func hasPathSum(root *TreeNode, sum int, path []int){
if root == nil {
return
}
newPath := append(path, root.Val)
sum = sum - root.Val
if root.Left == nil && root.Right == nil && sum == 0 {
answer = append(answer, newPath)
fmt.Println(answer)
return
}
if root.Left != nil {
hasPathSum(root.Left, sum, newPath)
}
if root.Right != nil {
hasPathSum(root.Right, sum, newPath)
}
}
func pathSum(root *TreeNode, sum int) [][]int {
var path []int
answer = [][]int{}
hasPathSum(root, sum, path)
return answer
}
And when I avoid declaring newPath it passes the base check. Like this:
var answer[][]int
func hasPathSum(root *TreeNode, sum int, path []int){
if root == nil {
return
}
sum = sum - root.Val
if root.Left == nil && root.Right == nil && sum == 0 {
answer = append(answer, append(path, root.Val))
fmt.Println(answer)
return
}
if root.Left != nil {
hasPathSum(root.Left, sum, append(path, root.Val))
}
if root.Right != nil {
hasPathSum(root.Right, sum, append(path, root.Val))
}
}
func pathSum(root *TreeNode, sum int) [][]int {
var path []int
answer = [][]int{}
hasPathSum(root, sum, path)
return answer
}
I am not able to figure out what is the difference between the two solutions. Both solutions are the same from the recursion point of view. Furthermore, a similar solution in C++ passes all the checks.
The problem occurs because slices refer to an underlying array, and append does not re-allocate a new array if there's space. See https://blog.golang.org/slices-intro
That means when you append(path, root.Val), the new slice will sometimes share the backing array with path. That can be a problem, for example:
if root.Left != nil {
hasPathSum(root.Left, sum, append(path, root.Val))
}
if root.Right != nil {
hasPathSum(root.Right, sum, append(path, root.Val))
}
Here, both branches may be using the same backing array. That's a problem, because when executing the first hasPathSum it may add a slice to answer, but the underlying array of that slice may still be used in the second call to hasPathSum, which will change its contents.
Both versions of the code have the same problem, but because the second is less likely to cause problems because if append(path, root.Val) needs to reallocate, then you get two different copies in the two branches of hasPathSum. This means the bug will happen at a lower frequency.
I'm not sure about fmt.Println(answer), you'd probably just need to return answer.
This'll pass:
func pathSum(root *TreeNode, sum int) [][]int {
var paths [][]int
if root == nil {
return paths
}
if root.Left == nil && root.Right == nil {
if sum == root.Val {
return append(paths, []int{ root.Val })
}
return paths
}
for _, path := range pathSum(root.Left, sum - root.Val) {
paths = append(paths, append([]int{ root.Val}, path... ))
}
for _, path := range pathSum(root.Right, sum - root.Val) {
paths = append(paths, append([]int{ root.Val}, path... ))
}
return paths
}
Here is LeetCode's Java solution with comments:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
private void recurseTree(TreeNode node, int remainingSum, List<Integer> pathNodes, List<List<Integer>> pathsList) {
if (node == null) {
return;
}
// Add the current node to the path's list
pathNodes.add(node.val);
// Check if the current node is a leaf and also, if it
// equals our remaining sum. If it does, we add the path to
// our list of paths
if (remainingSum == node.val && node.left == null && node.right == null) {
pathsList.add(new ArrayList<>(pathNodes));
} else {
// Else, we will recurse on the left and the right children
this.recurseTree(node.left, remainingSum - node.val, pathNodes, pathsList);
this.recurseTree(node.right, remainingSum - node.val, pathNodes, pathsList);
}
// We need to pop the node once we are done processing ALL of it's
// subtrees.
pathNodes.remove(pathNodes.size() - 1);
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> pathsList = new ArrayList<List<Integer>>();
List<Integer> pathNodes = new ArrayList<Integer>();
this.recurseTree(root, sum, pathNodes, pathsList);
return pathsList;
}
}
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.

Heapsort implementation in Go

I'm trying to implement code from Sedgewick's Algorithms textbook. The idea is to implement heapsort with the root of the heap stored in position 1 in the array.
Given the input S O R T E X A M P L E I expect a sorted output of A E E L M O P R S T X.
I'm having a bit of trouble implementing this, even when directly trying to translate the referenced Java code. This is what I have so far, which returns the following output:
package main
import (
"bufio"
"fmt"
"os"
"reflect"
"strings"
)
type Heap struct {
PQ []interface{}
}
func (h *Heap) Sort(pq []interface{}) {
n := len(pq)
for k := n / 2; k >= 1; k-- {
Sink(pq, k, n)
}
for n > 1 {
Exchange(pq, 1, n)
n = n - 1
Sink(pq, 1, n)
}
}
func Sink(pq []interface{}, k, n int) {
fmt.Println(k, n, pq)
for 2*k <= n {
j := 2 * k
if j < n && Less(pq, j, j+1) {
j = j + 1
}
Exchange(pq, k, j)
k = j
}
}
func Exchange(pq []interface{}, j, k int) {
curr := pq[j-1]
pq[j-1] = pq[k-1]
pq[k-1] = curr
}
func Less(pq []interface{}, j, k int) bool {
x, y := pq[j-1], pq[k-1]
if reflect.TypeOf(x) != reflect.TypeOf(y) {
fmt.Println("mismatched inputs", x, y)
panic("mismatched inputs")
}
switch x.(type) {
case int:
a, b := x.(int), y.(int)
if a > b {
return false
}
case float32:
a, b := x.(int), y.(int)
if a > b {
return false
}
case float64:
a, b := x.(int), y.(int)
if a > b {
return false
}
case string:
a, b := x.(string), y.(string)
if a > b {
return false
}
default:
panic("unhandled types, please add case.")
}
return true
}
func main() {
a := readStdin()
var h *Heap = new(Heap)
h.PQ = a
h.Sort(h.PQ)
fmt.Println(h.PQ)
}
func readStdin() []interface{} {
scanner := bufio.NewScanner(os.Stdin)
var items []interface{}
for scanner.Scan() {
item := scanner.Text()
tmp := strings.SplitAfter(item, " ")
items = make([]interface{}, len(tmp)+1)
for i, item := range tmp {
items[i+1] = item
}
}
if err := scanner.Err(); err != nil {
panic(err)
}
return items
}
mismatched inputs E <nil>
panic: mismatched inputs
which panics as expected because of the comparison between nil value at index 0 and the currents slice value from 1..n. Perhaps I'm looking at this problem a bit too closely, or more than likely, I am missing a key point in the heapsort implementation altogether. Thoughts?
The standard library contains a heap package that you can use to directly implement this.
Even if you want to re-implement it yourself, the idea of using an interface to access the underlying slice is a good one -- allowing you to focus on the abstract heap operations without the mess of dealing with various types.
Here's a complete working example of heapsort, running on a slice of runes. Note that *runeSlice type implements heap.Interface by defining the three methods of sort.Interface: Len, Less, Swap, and the additional two methods from heap.Interface: Push and Pop.
package main
import (
"container/heap"
"fmt"
)
type runeSlice []rune
func (r runeSlice) Len() int { return len(r) }
func (r runeSlice) Less(i, j int) bool { return r[i] > r[j] }
func (r runeSlice) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r *runeSlice) Push(x interface{}) {
*r = append(*r, x.(rune))
}
func (r *runeSlice) Pop() interface{} {
x := (*r)[len(*r)-1]
*r = (*r)[:len(*r)-1]
return x
}
func main() {
a := []rune("SORTEXAMPLE")
h := runeSlice(a)
heap.Init(&h)
for i := len(a) - 1; i >= 0; i-- {
a[0], a[i] = a[i], a[0]
h = h[:i]
heap.Fix(&h, 0)
}
fmt.Println(string(a))
}

panic: runtime error: invalid memory address or nil pointer dereference [signal 0xc0000005 code=0x0 addr=0x8 pc=0x48be5c] goroutine 1 [running]:

I am trying to implement addition of polynomials using linked list. The program adds the power 0 coefficients successfully but after the first traversal it panics. Here is the code I have written so far. after initializing temp1!= nil the loop iterates over else but doesn't enter if loop when powers are different and goes into panic state
package main
import (
"fmt"
)
type Node struct {
coefficient int
power int
next *Node
}
type list struct {
head *Node
count int
}
func main() {
list1 := &list{}
list1.addVariable(5, 2)
list1.addVariable(4, 1)
list1.addVariable(3, 0)
list1.print()
list2 := &list{}
list2.addVariable(4, 1)
list2.addVariable(2, 0)
list2.print()
list4 := addLists(list1, list2)
list4.print()
}
func (lst *list) print() {
temp := lst.head
for temp != nil {
fmt.Print(temp.coefficient, "x", "^", temp.power, "+")
temp = temp.next
}
fmt.Println("\n")
}
func (lst *list) addVariable(coefficient int, power int) {
lst.head = &Node{coefficient, power, lst.head}
lst.count++
}
func addLists(list1 *list, list2 *list) *list {
list3 := &list{}
temp1 := list1.head
temp2 := list2.head
fmt.Println("reached") // for debugging purposes
if list1.count > list2.count {
fmt.Println("\nreached 2") // for debugging purposes
for temp1 != nil {
fmt.Println("reached3") // for debugging purposes
if temp1.power != temp2.power {
fmt.Println("reached4") // for debugging purposes
list3.normalAdd(temp1, temp2)
temp1 = temp1.next
} else {
fmt.Println("reached5") // for debugging purposes
node4 := add(temp1, temp2)
list3.exlusiveAdd(node4)
temp1 = temp1.next
temp2 = temp2.next
}
}
}
return list3
}
func (lst *list) normalAdd(node6 *Node, node7 *Node) {
node6.next = lst.head
lst.head = node6
node7.next = lst.head
lst.head = node7
lst.count += 2
}
func (lst *list) exlusiveAdd(node5 *Node) {
node5.next = lst.head
lst.head = node5
lst.count++
}
func add(node1, node2 *Node) *Node {
node3 := &Node{}
node3.coefficient = node1.coefficient + node2.coefficient
node3.power = node1.power
return node3
}
Output when the program is run:
3x^0+4x^1+5x^2+
2x^0+4x^1+
reached
reached 2
reached3
reached5
reached3
reached5
reached3
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0xd48e6]
goroutine 1 [running]:
main.addLists(0x41c7a8, 0x41c7a0, 0x40c120, 0x1d)
/tmp/sandbox520212269/main.go:56 +0x186
main.main()
/tmp/sandbox520212269/main.go:28 +0x220
playground here
Update: Thanks for the solution but I have successfully written the code for above problem. here it is.
package main
import (
"fmt"
)
type Node struct {
coefficient int
power int
next *Node
}
type list struct {
head *Node
count int
}
func main() {
list1 := &list{}
list1.addVariable(5, 2)
list1.addVariable(4, 1)
list1.addVariable(3, 0)
list1.print()
list2 := &list{}
list2.addVariable(4, 1)
list2.addVariable(2, 0)
list2.print()
poly := addPoly(list1, list2)
poly.print()
}
func (lst *list) print() {
temp := lst.head
for temp != nil {
fmt.Print(temp.coefficient, "x", "^", temp.power, "+")
temp = temp.next
}
fmt.Println("\n")
}
func (lst *list) addVariable(coefficient int, power int) {
lst.head = &Node{coefficient, power, lst.head}
lst.count++
}
func addPoly(list_1 *list, list_2 *list) *list {
list_3 := &list{}
temp_1 := list_1.head
temp_2 := list_2.head
if list_1.count > list_2.count {
for temp_1 != nil && temp_2 != nil {
if temp_1.power == temp_2.power {
new_coefficient := temp_1.coefficient + temp_2.coefficient
new_power := temp_1.power
list_3.addVariable(new_coefficient, new_power)
temp_1 = temp_1.next
temp_2 = temp_2.next
} else if temp_1.power != temp_2.power {
list_3.addVariable(temp_1.coefficient, temp_1.power)
list_3.addVariable(temp_2.coefficient, temp_2.power)
temp_1 = temp_1.next
temp_2 = temp_2.next
}
}
}
for temp_1 != nil {
list_3.addVariable(temp_1.coefficient, temp_1.power)
temp_1 = temp_1.next
}
return list_3
}
The error occur because you tried to access .power property from nil object in code below. Both temp1 and temp2 are nil.
if temp1.power != temp2.power {
// ...
}
The .head property on list struct has pointer data type. The zero value of pointer data type is nil. In your code, both list1 and list2 has nil value on its .head property.
What you need to do: initialise the value of .head property explicitly during creation of both list1 and list2. Then the panic error will disappear and your code will work properly.
list1 := &list{head: new(Node)}
// ...
list2 := &list{head: new(Node)}
// ...
Playground: https://play.golang.org/p/vPK3pYKht3E
You have a lot of mistakes in your code like the first answer posted. Also, why is there a need to keep track of the number of terms? I would suggest you take a simpler approach.
type Node struct {
Coeff int
Power int
next *Node
}
// Add coeff^power to a polynomial
func (n *Node) AddTerm(coeff int, power int) {
for t := n; t != nil; t = t.next {
if t.Power == power {
t.Coeff += coeff
return
}
}
n.next = &Node{coeff, power, n.next}
}
// Add a polynomial m to the polynomial
func (n *Node) AddPolynomial(m *Node) {
for t := m; t != nil; t = t.next {
n.AddTerm(t.Coeff, t.Power)
}
}
// The string representation of the polynomial
func (n *Node) String() string {
buff := strings.Builder{}
for t := n; t != nil; t = t.next {
fmt.Fprintf(&buff, " + %d^%d", t.Coeff, t.Power)
}
return buff.String()[3:]
}
// Add two polynomials together creating a new one
func Add(a *Node, b *Node) *Node {
c := &Node{}
c.AddPolynomial(a)
c.AddPolynomial(b)
return c
}
func main() {
p1 := &Node{}
p1.AddTerm(5, 2)
p1.AddTerm(4, 1)
p1.AddTerm(3, 0)
fmt.Println(p1)
p2 := &Node{}
p2.AddTerm(4, 1)
p2.AddTerm(2, 0)
fmt.Println(p2)
p3 := Add(p1, p2)
fmt.Println(p3)
}
Playground
Just check your libraries. There are some redundant ones.

generate combinations/permutation of specific length

The project is more complex but the blocking issue is: How to generate a sequence of words of specific length from a list?
I've found how to generate all the possible combinations(see below) but the issue is that I need only the combinations of specific length.
Wolfram working example (it uses permutations though, I need only combinations(order doesn't matter)) :
Permutations[{a, b, c, d}, {3}]
Example(pseudo go):
list := []string{"alice", "moon", "walks", "mars", "sings", "guitar", "bravo"}
var premutationOf3
premutationOf3 = premuate(list, 3)
// this should return a list of all premutations such
// [][]string{[]string{"alice", "walks", "moon"}, []string{"alice", "signs", "guitar"} ....}
Current code to premutate all the possible sequences (no length limit)
for _, perm := range permutations(list) {
fmt.Printf("%q\n", perm)
}
func permutations(arr []string) [][]string {
var helper func([]string, int)
res := [][]string{}
helper = func(arr []string, n int) {
if n == 1 {
tmp := make([]string, len(arr))
copy(tmp, arr)
res = append(res, tmp)
} else {
for i := 0; i < n; i++ {
helper(arr, n-1)
if n%2 == 1 {
tmp := arr[i]
arr[i] = arr[n-1]
arr[n-1] = tmp
} else {
tmp := arr[0]
arr[0] = arr[n-1]
arr[n-1] = tmp
}
}
}
}
helper(arr, len(arr))
return res
}
I implement twiddle algorithm for generating combination in Go. Here is my implementation:
package twiddle
// Twiddle type contains all information twiddle algorithm
// need between each iteration.
type Twiddle struct {
p []int
b []bool
end bool
}
// New creates new twiddle algorithm instance
func New(m int, n int) *Twiddle {
p := make([]int, n+2)
b := make([]bool, n)
// initiate p
p[0] = n + 1
var i int
for i = 1; i != n-m+1; i++ {
p[i] = 0
}
for i != n+1 {
p[i] = i + m - n
i++
}
p[n+1] = -2
if m == 0 {
p[1] = 1
}
// initiate b
for i = 0; i != n-m; i++ {
b[i] = false
}
for i != n {
b[i] = true
i++
}
return &Twiddle{
p: p,
b: b,
}
}
// Next creates next combination and return it.
// it returns nil on end of combinations
func (t *Twiddle) Next() []bool {
if t.end {
return nil
}
r := make([]bool, len(t.b))
for i := 0; i < len(t.b); i++ {
r[i] = t.b[i]
}
x, y, end := t.twiddle()
t.b[x] = true
t.b[y] = false
t.end = end
return r
}
func (t *Twiddle) twiddle() (int, int, bool) {
var i, j, k int
var x, y int
j = 1
for t.p[j] <= 0 {
j++
}
if t.p[j-1] == 0 {
for i = j - 1; i != 1; i-- {
t.p[i] = -1
}
t.p[j] = 0
x = 0
t.p[1] = 1
y = j - 1
} else {
if j > 1 {
t.p[j-1] = 0
}
j++
for t.p[j] > 0 {
j++
}
k = j - 1
i = j
for t.p[i] == 0 {
t.p[i] = -1
i++
}
if t.p[i] == -1 {
t.p[i] = t.p[k]
x = i - 1
y = k - 1
t.p[k] = -1
} else {
if i == t.p[0] {
return x, y, true
}
t.p[j] = t.p[i]
t.p[i] = 0
x = j - 1
y = i - 1
}
}
return x, y, false
}
you can use my tweedle package as follow:
tw := tweedle.New(1, 2)
for b := tw.Next(); b != nil; b = tw.Next() {
fmt.Println(b)
}

Resources