package main

import "fmt"

func searchSubsets(k, n int, subset []int) {
	if k == n+1 {
		// process subset
		fmt.Println(subset)
	} else {
		// include k in the subset
		subset = append(subset, k)
		searchSubsets(k+1, n, subset)
		subset = subset[:len(subset)-1]
		// don’t include k in the subset
		searchSubsets(k+1, n, subset)
	}
}

func searchPermutations(n int, permutation []int, chosen []bool) {
	if len(permutation) == n {
		// process permutation
		fmt.Println(permutation)
	} else {
		for i := 1; i <= n; i++ {
			if chosen[i] {
				continue
			}
			chosen[i] = true
			permutation = append(permutation, i)
			searchPermutations(n, permutation, chosen)
			chosen[i] = false
			permutation = permutation[:len(permutation)-1]
		}
	}
}

func searchQueens(y, n int, col, diag1, diag2 []bool) int {
	if y == n {
		return 1
	}

	count := 0
	for x := 0; x < n; x++ {
		if col[x] || diag1[x+y] || diag2[x-y+n-1] {
			continue
		}
		col[x], diag1[x+y], diag2[x-y+n-1] = true, true, true
		count += searchQueens(y+1, n, col, diag1, diag2)
		col[x], diag1[x+y], diag2[x-y+n-1] = false, false, false
	}
	return count
}

func main() {
	searchSubsets(1, 4, []int{})
	searchPermutations(4, []int{}, make([]bool, 4+1))
	const NB_QUEENS = 16
	count := searchQueens(0, NB_QUEENS, make([]bool, NB_QUEENS*NB_QUEENS), make([]bool, NB_QUEENS*NB_QUEENS), make([]bool, NB_QUEENS*NB_QUEENS))
	fmt.Println(count)
}
