How to generate a Binary Tree from a Labyrinth? - binary-tree

A matrix of 150x150 size will describe our labyrinth, so for example if the matrix were only 10x10 we would have something like this:
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 1 0 0<-F
1 0 1 1 0 1 0 1 0 1
1 1 1 1 0 1 0 0 0 1
1 1 1 1 0 1 1 1 1 1
1 0 0 0 0 1 1 1 1 1
1 0 1 1 0 1 1 1 1 1
1 0 1 0 0 0 0 1 1 1
S->0 0 1 1 1 1 0 1 1 1
1 1 1 1 1 1 1 1 1 1
Where S marks the starting point and F the exit of the labyrinth.
The purpose of this program is to generate a Binary Tree that will describe all the paths we traveled while trying to find the exit.
How would you acomplish that? I'm really lost this time, I don't really know where to start that's why I'm not posting anything I've tried but if you could please give me a direction I would be really really grateful.
John Smith.

you might want to try backtracking
here's a complete example of how to solve this problem... however: it can't operate on a maze with "islands" in it as it would be necessary to aditionally track where you have been already. but i think you can figure out how to do this as well...
the output should be:
right, up, up, up, right, right, right, up, up, up, up, right, right, down, down, right, right, up, up, right, finish!
import java.awt.Point;
public class Maze {
enum Direction {
up, right, down, left
}
static Direction[] dirs = Direction.values();
int[][] maze = { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, { 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
{ 1, 1, 1, 1, 0, 1, 0, 0, 0, 1 }, { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 }, { 1, 0, 1, 1, 0, 1, 1, 1, 1, 1 },
{ 1, 0, 1, 0, 0, 0, 0, 1, 1, 1 }, { 0, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
Point start = new Point(0, 8);
Point finish = new Point(9, 1);
Point go(Direction dir, Point from) {
Point result = new Point(from);
switch (dir) {
case up:
if ((from.y == 0) || (maze[from.y - 1][from.x] != 0))
return null;
result.translate(0, -1);
break;
case right:
if ((from.x == maze[0].length) || (maze[from.y][from.x + 1] != 0))
return null;
result.translate(1, 0);
break;
case down:
if ((from.y == maze.length) || (maze[from.y + 1][from.x] != 0))
return null;
result.translate(0, 1);
break;
case left:
if ((from.x == 0) || (maze[from.y][from.x - 1] != 0))
return null;
result.translate(-1, 0);
break;
}
return result;
}
String tryToGo(Direction dir, Point from) {
String result;
Point newPosition = go(dir, from);
if (newPosition == null)
return null;
else if (newPosition.equals(start))
return null;
else if (newPosition.equals(finish))
return "finish!";
else {
for (Direction newDir : dirs) {
switch (newDir) {
case up:
if (dir == Direction.down)
continue;
break;
case down:
if (dir == Direction.up)
continue;
break;
case left:
if (dir == Direction.right)
continue;
break;
case right:
if (dir == Direction.left)
continue;
break;
}
result = tryToGo(newDir, newPosition);
if (result == null)
continue;
else
return newDir + ", " + result;
}
return null;
}
}
public static void main(String[] args) {
Maze maze = new Maze();
System.out.println("right" + maze.tryToGo(Direction.right, maze.start));
}
}

Related

How to check if a specific point is within a figure in a matrix?

So I need a check function to see if a specific point in a matrix, say arr[3][4], is within a border, or a figure of characters. For clarification, imagine matrix char arr[10][10] below:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 1 0 0 0 1 0 0
0 0 0 1 0 0 0 1 0 0
0 0 0 1 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
As you can see, the '1' characters form a square of side length 5. I would like a bool function to return that true for arr[5][5] (0-indexed) because it is within the figure, but false for arr[1][1] because it is not. If relevant, the total size of the matrix will always be a constant 100*100, no matter the size of the '1' figure within. Also, please note that the figure will not always be a perfect polygon like the square in the example.
I could not solve this problem because in my example above, clearly both points (arr[5][5] and arr[1][1]) have the same surrounding squares, and the space is large enough so that I cannot just check if the four directions of up, right, down, and left (yes, diagonals can be ignored here) is a '1' because the '0' inside would be next to other '0's.
EDIT: I also want to clarify according to some shortcomings of answers that the thickness of sides may vary. The shape very well could be:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 1 0 0 1 1 0
0 0 1 1 1 0 1 1 0 0
0 0 1 0 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Therefore, counting whether the '1's on top of and to the left of the point is odd would not work.
So a flood fill would work, but it is quite heavy unless you want to know all the encased points. If you just want to check one point then you could do:
Count the number of ones in the vertical segment between points (x,0) and (x,y)
Count the number of ones in the horizontal segment between points (0,y) and (x,y)
If both are odd then you are inside.
Keep in mind that overlapping shapes or shapes with holes will not work with this algorithm.
So the function would look like this:
int inside(int x, int y)
{
int x_count = 0;
for(int i=0;i<x;i++)
if(matrix[y][i])
x_count++;
int y_count = 0;
for(int i=0;i<y;i++)
if(matrix[i][x])
y_count++;
return x_count%2 && y_count%2;
};
A full test program looks like:
#include <stdio.h>
int matrix1[10][10] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
int matrix2[10][10] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 1, 0, 1, 1, 1, 1, 1, 0, 0},
{0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 1, 1, 1, 1, 1, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
int inside(int matrix[10][10],int x, int y)
{
int x_count = 0;
for(int i=0;i<x;i++)
if(matrix[y][i])
x_count++;
int y_count = 0;
for(int i=0;i<y;i++)
if(matrix[i][x])
y_count++;
return x_count%2 && y_count%2;
};
int main()
{
printf("2,2 is %s matrix1\n",inside(matrix1,2,2)?"inside":"outside");
printf("5,5 is %s matrix1\n",inside(matrix1,5,5)?"inside":"outside");
printf("8,8 is %s matrix1\n",inside(matrix1,8,8)?"inside":"outside");
printf("3,3 is %s matrix2\n",inside(matrix2,3,3)?"inside":"outside");
printf("5,5 is %s matrix2\n",inside(matrix2,5,5)?"inside":"outside");
printf("7,7 is %s matrix2\n",inside(matrix2,7,7)?"inside":"outside");
return 0;
}
Try it online https://onlinegdb.com/UkkaA3vWZ
The standard algorithm only needs to scan left to right along the row you wish to check.
First, check if the element is a 1. If it is you are “inside or on the edge”.
Otherwise, scanning from 0 to x:
If you count an odd number of edges, you are inside.
If you count an even number of edges, you are outside.
You must be careful how you count edges. An edge is one where you have a 1 both above and below in the surrounding 8 elements. Otherwise you have not crossed an edge (you have passed a point).
Likewise, if you hit a run of 1s, you must still apply the above and below for both the left and right side of the run.
BTW, the only sure way to check is the flood-fill algorithm explained by Jonathan S.. Everything else can be tricked.
Here's a simple algorithm that'll do that:
Iterate over all elements at the edges of the matrix.
Change all 0 elements at the edge of the matrix to 2. (Leave any 1 elements intact.)
Within the entire matrix, whenever a 0 borders a 2, change that 0 to a 2 as well. Repeat this until there are no 0 elements left that are adjacent to a 2.
Any elements that are still 0 now are encased by 1 elements.
This is a flood fill starting at the edges of the matrix. It gives you all "encased" elements at once.

How does this Integer pool code work

I've been trying to understand how this integer pool works. It is a lot of bit fiddling stuff I can't wrap my head around. I'm assuming there is a concept I'm missing with the m2id array and how it is or'ed with index 'n' that I don't know and would clear up a lot of my confusion. Are there are any general concepts/CS-theory that explain this seemingly-looking-simple code. I've put comments in the code to try and state my current understanding and where I am totally confused.
// Copyright 2009 The Go9p Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//Original source: https://github.com/rminnich/go9p/blob/master/clnt_pool.go
package go9p
import "sync"
var m2id = [...]uint8{ // I think this is where the magic is.
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 5,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 6,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 5,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 7,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 5,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 6,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 5,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 0,
}
type pool struct {
sync.Mutex
need int
nchan chan uint32
maxid uint32
imap []byte
}
func newPool(maxid uint32) *pool {
p := new(pool)
p.maxid = maxid
p.nchan = make(chan uint32)
return p
}
func (p *pool) getId() uint32 {
var n uint32 = 0
var ret uint32
p.Lock()
for n = 0; n < uint32(len(p.imap)); n++ {
// it looks like every 0...n position of imap will be incremented to 255.
if p.imap[n] != 0xFF {
break
}
}
if int(n) >= len(p.imap) {
// This seems to be just growing the imap slice as needed.
// I don't quite understand the constant of '8' here.
m := uint32(len(p.imap) + 32)
if uint32(m*8) > p.maxid {
m = p.maxid/8 + 1
}
b := make([]byte, m)
copy(b, p.imap)
p.imap = b
}
if n >= uint32(len(p.imap)) {
// If you get here the I'm assuming all the ID's are used up and putId will return you the next released ID.
p.need++
p.Unlock()
ret = <-p.nchan
} else {
// This part I'm having a hard time grasping.
// It seems that each index of imap is incremented
// from 0 to 255 and magically or'd with ret to increment to the next number?
ret = uint32(m2id[p.imap[n]])
p.imap[n] |= 1 << ret
ret += n * 8
p.Unlock()
}
return ret
}
func (p *pool) putId(id uint32) {
p.Lock()
if p.need > 0 {
p.nchan <- id
p.need--
p.Unlock()
return
}
// This doesn't play well with what I thought was going on. I though that.
// I was thinking that imap[0] would always somehow magically return all the
// values from 0 to 255 and imap[1] would return 256 += 255 and so on.
// How does this work?
p.imap[id/8] &= ^(1 << (id % 8))
p.Unlock()
}
Optimization often leads to obscurity. Start with the basic concept. The pool of available Ids is represented by the underlying bit array of a slice of bytes. Id 19 is represented by left-to-right byte 2 (19 / 8) and right-to-left bit 3 (19 % 8).
Here's a simple implementation, ignoring details like locking and growing the bit array.
package main
import "fmt"
// The Id pool is represented by the underlying bit array of a slice of bytes.
var idPool = make([]byte, 4)
// Get the next available Id from the pool.
func getId() int {
// Get next available byte
for i := 0; i < len(idPool); i++ {
b := idPool[i]
if b != 0xFF {
// Get next available bit in the byte
for j := 0; j < 8; j++ {
if b&(1<<uint(j)) == 0 {
// Mark Id bit as unavailable.
idPool[i] |= 1 << uint(j)
// Return Id.
return 8*i + j
}
}
}
}
panic("Insufficient Ids")
}
// Put the Id back in the pool.
func putId(id int) {
if 0 > id || id >= 8*len(idPool) {
panic("Invalid Id")
}
i := id / 8
j := id % 8
// Mark Id bit as available.
idPool[i] &^= 1 << uint(j)
}
func main() {
for i := 0; i < 16; i++ {
getId()
}
fmt.Printf("%x\n", idPool)
for i := 10; i < 12; i++ {
putId(i)
}
fmt.Printf("%x\n", idPool)
fmt.Println(getId())
fmt.Printf("%x\n", idPool)
}
Output:
ffff0000
fff30000
10
fff70000
We can optimize this loop
// Get next available bit in the byte
for j := 0; j < 8; j++ {
if b&(1<<uint(j)) == 0 {
// Mark Id bit as unavailable.
idPool[i] |= 1 << uint(j)
// Return Id.
return 8*i + j
}
}
by replacing it with a table (m2id) lookup for the bit shift value.
// Get next available bit in the byte
j := int(m2id[idPool[i]])
// Mark Id bit as unavailable.
idPool[i] |= 1 << uint(j)
// Return Id.
return 8*i + j
The m2idInit() function shows how the m2id table bit shift values are calculated.
func m2idInit() (m2id [256]uint8) {
// For all byte values.
for i := uint(0); i < 256; i++ {
// Find an unused id
for j := uint(0); j < 8; j++ {
if i&(1<<j) == 0 {
// Bit shift value
m2id[i] = uint8(j)
break
}
}
}
return m2id
}
For example,
package main
import "fmt"
// The Id pool is represented by the underlying bit array of a slice of bytes.
var idPool = make([]byte, 4)
// Get the next available Id from the pool.
func getId() int {
// Get next available byte
for i := 0; i < len(idPool); i++ {
b := idPool[i]
if b != 0xFF {
// Get next available bit in the byte
j := int(m2id[idPool[i]])
// Mark Id bit as unavailable.
idPool[i] |= 1 << uint(j)
// Return Id.
return 8*i + j
}
}
panic("Insufficient Ids")
}
// Put the Id back in the pool.
func putId(id int) {
if 0 > id || id >= 8*len(idPool) {
panic("Invalid Id")
}
i := id / 8
j := id % 8
// Mark Id bit as available.
idPool[i] &^= 1 << uint(j)
}
var m2id = m2idInit()
func m2idInit() (m2id [256]uint8) {
// For all byte values.
for i := uint(0); i < 256; i++ {
// Find an unused id
for j := uint(0); j < 8; j++ {
if i&(1<<j) == 0 {
// Bit shift value
m2id[i] = uint8(j)
break
}
}
}
return m2id
}
func main() {
for i := 0; i < 16; i++ {
getId()
}
fmt.Printf("%x\n", idPool)
for i := 10; i < 12; i++ {
putId(i)
}
fmt.Printf("%x\n", idPool)
fmt.Println(getId())
fmt.Printf("%x\n", idPool)
fmt.Println()
fmt.Println(m2id)
}
Output:
ffff0000
fff30000
10
fff70000
[0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 5
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 6
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 5
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 7
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 5
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 6
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 5
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 4
0 1 0 2 0 1 0 3
0 1 0 2 0 1 0 0]
There is no magic.
References:
Bit manipulation
The Go Programming Language Specification, Arithmetic operators

Animate map movement on bash

I have a 2d map which is an array of arrays:
map = [[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 1],
[0, 0, 0, 0, 0]]
I also have a list with moves:
moves = [[0,0], [0, 1], [1, 1]]
I want to print the movement on console (but I want every time to overwrite previous output, like this)
So the expected output should be something like this
* 0 0 0 0 0 * 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 * 0 0 0
0 1 1 1 1 --> 0 1 1 1 1 --> 0 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
I have tried some things but I can't get close to my desired output.
To clear the screen and wait for ENTER, try this:
map = [[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 1],
[0, 0, 0, 0, 0]]
loc = [0,0]
moves = [[0,0], [0, 1], [1, 1]]
def display_map(map,loc)
system 'clear'
loc.first.times { puts }
map.each { |row| print ' '*loc.last; p row }
end
moves.each do |x,y|
loc[0] += x
loc[1] += y
display_map(map,loc)
gets
end
This works on a Mac. For other OS's you may have to replace system 'clear' with system 'cls'.
[Edit: I see I misunderstood the question. I think this is what you want:
moves.each do |x,y|
system 'clear'
nrows.times do |i|
ncols.times do |j|
print (i==x && j==y) ? '*' : map[i][j]
print ' ' if j < ncols-1
end
puts
end
gets
end
You can use ANSI terminal escape codes.
Example:
# Save initial cursor position
puts "\033[s"
puts <<EOF
* 0 0 0 0
0 0 0 0 0
0 1 1 1 1
0 0 0 0 0
EOF
sleep 1
# Restore initial cursor position
puts "\033[u"
puts <<EOF
0 * 0 0 0
0 0 0 0 0
0 1 1 1 1
0 0 0 0 0
EOF
sleep 1
# Restore initial cursor position
puts "\033[u"
puts <<EOF
0 0 0 0 0
0 * 0 0 0
0 1 1 1 1
0 0 0 0 0
EOF
Following #Cary_Swoveland's solution with clearing the console, I manage to do it like this:
map = [[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 1],
[0, 0, 0, 0, 0]]
moves = [[0,0], [0, 1], [1, 1]]
def display_map(map,loc)
system "clear" or system "cls"
# loc.first.times { puts }
map.each { |row| p row }
end
moves.each do |x,y|
map[x][y] = 8
display_map(m,loc)
map[x][y] = 0
gets
end

How to sort array of 0 and 1 of length n in O(n) time and O(1) space? And can we generalize this to array of 0, 1, 2, ...?

I would like to sort an array of 0 and 1. I have to sort it in linear time and in constant space. How can I do this without explicitly counting the number of 0 and 1?
I did something like this:
sort(array):
Q0 = Queue()
Q1 = Queue()
for i in (0, n-1):
if array[i] == 0:
Q0.push(array[i])
if array[i] == 1:
Q1.push(array[i])
j = 0
while Q0:
array[j] = Q0.pop()
j += 1
while Q1:
array[j] = Q1.pop()
j += 1
I think my solution is correct and has O(n) time but I am not sure of O(1) space. Any help?
Also, can we generalize the sorting to 0, 1, 2 arrays?
Here is (tested/working) Python:
# sort array of length n containing values of only 0 or 1
# in time O(n) and space O(1)
a = [1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
first = 0
last = len(a)-1
print a
# note: don't need temp since values are only 0 and 1
while(last>first):
if a[first] == 1:
a[first] = a[last]
a[last] = 1
last -= 1
else:
first += 1
print a
The idea is to swap all the ones to the end of the array and the zeros to the beginning of the array by keeping two pointers. i points to the first index that has a 1.
Here is a pseudo-code:
i = 1
for (j = 1 to n)
if(a[j] == 0)
swap(a[i], a[j])
i++

All Possible Tic Tac Toe Winning Combinations

I had an interview were I was asked a seemingly simple algorithm question: "Write an algorithm to return me all possible winning combinations for tic tac toe." I still can't figure out an efficient way to handle this. Is there a standard algorithm or common that should be applied to similar questions like this that I'm not aware of?
This is one of those problems that's actually simple enough for brute force and, while you could use combinatorics, graph theory, or many other complex tools to solve it, I'd actually be impressed by applicants that recognise the fact there's an easier way (at least for this problem).
There are only 39, or 19,683 possible combinations of placing x, o or <blank> in the grid, and not all of those are valid.
First, a valid game position is one where the difference between x and o counts is no more than one, since they have to alternate moves.
In addition, it's impossible to have a state where both sides have three in a row, so they can be discounted as well. If both have three in a row, then one of them would have won in the previous move.
There's actually another limitation in that it's impossible for one side to have won in two different ways without a common cell (again, they would have won in a previous move), meaning that:
XXX
OOO
XXX
cannot be achieved, while:
XXX
OOX
OOX
can be. But we can actually ignore that since there's no way to win two ways without a common cell without having already violated the "maximum difference of one" rule, since you need six cells for that, with the opponent only having three.
So I would simply use brute force and, for each position where the difference is zero or one between the counts, check the eight winning possibilities for both sides. Assuming only one of them has a win, that's a legal, winning game.
Below is a proof of concept in Python, but first the output of time when run on the process sending output to /dev/null to show how fast it is:
real 0m0.169s
user 0m0.109s
sys 0m0.030s
The code:
def won(c, n):
if c[0] == n and c[1] == n and c[2] == n: return 1
if c[3] == n and c[4] == n and c[5] == n: return 1
if c[6] == n and c[7] == n and c[8] == n: return 1
if c[0] == n and c[3] == n and c[6] == n: return 1
if c[1] == n and c[4] == n and c[7] == n: return 1
if c[2] == n and c[5] == n and c[8] == n: return 1
if c[0] == n and c[4] == n and c[8] == n: return 1
if c[2] == n and c[4] == n and c[6] == n: return 1
return 0
pc = [' ', 'x', 'o']
c = [0] * 9
for c[0] in range (3):
for c[1] in range (3):
for c[2] in range (3):
for c[3] in range (3):
for c[4] in range (3):
for c[5] in range (3):
for c[6] in range (3):
for c[7] in range (3):
for c[8] in range (3):
countx = sum([1 for x in c if x == 1])
county = sum([1 for x in c if x == 2])
if abs(countx-county) < 2:
if won(c,1) + won(c,2) == 1:
print " %s | %s | %s" % (pc[c[0]],pc[c[1]],pc[c[2]])
print "---+---+---"
print " %s | %s | %s" % (pc[c[3]],pc[c[4]],pc[c[5]])
print "---+---+---"
print " %s | %s | %s" % (pc[c[6]],pc[c[7]],pc[c[8]])
print
As one commenter has pointed out, there is one more restriction. The winner for a given board cannot have less cells than the loser since that means the loser just moved, despite the fact the winner had already won on the last move.
I won't change the code to take that into account but it would be a simple matter of checking who has the most cells (the last person that moved) and ensuring the winning line belonged to them.
Another way could be to start with each of the eight winning positions,
xxx ---
--- xxx
--- --- ... etc.,
and recursively fill in all legal combinations (start with inserting 2 o's, then add an x for each o ; avoid o winning positions):
xxx xxx xxx
oo- oox oox
--- o-- oox ... etc.,
Today I had an interview with Apple and I had the same question. I couldn't think well at that moment. Later one on, before going to a meeting I wrote the function for the combinations in 15 minutes, and when I came back from the meeting I wrote the validation function again in 15 minutes. I get nervous at interviews, Apple not trusts my resume, they only trust what they see in the interview, I don't blame them, many companies are the same, I just say that something in this hiring process doesn't look quite smart.
Anyways, here is my solution in Swift 4, there are 8 lines of code for the combinations function and 17 lines of code to check a valid board.
Cheers!!!
// Not used yet: 0
// Used with x : 1
// Used with 0 : 2
// 8 lines code to get the next combination
func increment ( _ list: inout [Int], _ base: Int ) -> Bool {
for digit in 0..<list.count {
list[digit] += 1
if list[digit] < base { return true }
list[digit] = 0
}
return false
}
let incrementTicTacToe = { increment(&$0, 3) }
let win0_ = [0,1,2] // [1,1,1,0,0,0,0,0,0]
let win1_ = [3,4,5] // [0,0,0,1,1,1,0,0,0]
let win2_ = [6,7,8] // [0,0,0,0,0,0,1,1,1]
let win_0 = [0,3,6] // [1,0,0,1,0,0,1,0,0]
let win_1 = [1,4,7] // [0,1,0,0,1,0,0,1,0]
let win_2 = [2,5,8] // [0,0,1,0,0,1,0,0,1]
let win00 = [0,4,8] // [1,0,0,0,1,0,0,0,1]
let win11 = [2,4,6] // [0,0,1,0,1,0,1,0,0]
let winList = [ win0_, win1_, win2_, win_0, win_1, win_2, win00, win11]
// 16 lines to check a valid board, wihtout countin lines of comment.
func winCombination (_ tictactoe: [Int]) -> Bool {
var count = 0
for win in winList {
if tictactoe[win[0]] == tictactoe[win[1]],
tictactoe[win[1]] == tictactoe[win[2]],
tictactoe[win[2]] != 0 {
// If the combination exist increment count by 1.
count += 1
}
if count == 2 {
return false
}
}
var indexes = Array(repeating:0, count:3)
for num in tictactoe { indexes[num] += 1 }
// '0' and 'X' must be used the same times or with a diference of one.
// Must one and only one valid combination
return abs(indexes[1] - indexes[2]) <= 1 && count == 1
}
// Test
var listToIncrement = Array(repeating:0, count:9)
var combinationsCount = 1
var winCount = 0
while incrementTicTacToe(&listToIncrement) {
if winCombination(listToIncrement) == true {
winCount += 1
}
combinationsCount += 1
}
print("There is \(combinationsCount) combinations including possible and impossible ones.")
print("There is \(winCount) combinations for wining positions.")
/*
There are 19683 combinations including possible and impossible ones.
There are 2032 combinations for winning positions.
*/
listToIncrement = Array(repeating:0, count:9)
var listOfIncremented = ""
for _ in 0..<1000 { // Win combinations for the first 1000 combinations
_ = incrementTicTacToe(&listToIncrement)
if winCombination(listToIncrement) == true {
listOfIncremented += ", \(listToIncrement)"
}
}
print("List of combinations: \(listOfIncremented)")
/*
List of combinations: , [2, 2, 2, 1, 1, 0, 0, 0, 0], [1, 1, 1, 2, 2, 0, 0, 0, 0],
[2, 2, 2, 1, 0, 1, 0, 0, 0], [2, 2, 2, 0, 1, 1, 0, 0, 0], [2, 2, 0, 1, 1, 1, 0, 0, 0],
[2, 0, 2, 1, 1, 1, 0, 0, 0], [0, 2, 2, 1, 1, 1, 0, 0, 0], [1, 1, 1, 2, 0, 2, 0, 0, 0],
[1, 1, 1, 0, 2, 2, 0, 0, 0], [1, 1, 0, 2, 2, 2, 0, 0, 0], [1, 0, 1, 2, 2, 2, 0, 0, 0],
[0, 1, 1, 2, 2, 2, 0, 0, 0], [1, 2, 2, 1, 0, 0, 1, 0, 0], [2, 2, 2, 1, 0, 0, 1, 0, 0],
[2, 2, 1, 0, 1, 0, 1, 0, 0], [2, 2, 2, 0, 1, 0, 1, 0, 0], [2, 2, 2, 1, 1, 0, 1, 0, 0],
[2, 0, 1, 2, 1, 0, 1, 0, 0], [0, 2, 1, 2, 1, 0, 1, 0, 0], [2, 2, 1, 2, 1, 0, 1, 0, 0],
[1, 2, 0, 1, 2, 0, 1, 0, 0], [1, 0, 2, 1, 2, 0, 1, 0, 0], [1, 2, 2, 1, 2, 0, 1, 0, 0],
[2, 2, 2, 0, 0, 1, 1, 0, 0]
*/
This is a java equivalent code sample
package testit;
public class TicTacToe {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 0 1 2
// 3 4 5
// 6 7 8
char[] pc = {' ' ,'o', 'x' };
char[] c = new char[9];
// initialize c
for (int i = 0; i < 9; i++)
c[i] = pc[0];
for (int i = 0; i < 3; i++) {
c[0] = pc[i];
for (int j = 0; j < 3; j++) {
c[1] = pc[j];
for (int k = 0; k < 3; k++) {
c[2] = pc[k];
for (int l = 0; l < 3; l++) {
c[3] = pc[l];
for (int m = 0; m < 3; m++) {
c[4] = pc[m];
for (int n = 0; n < 3; n++) {
c[5] = pc[n];
for (int o = 0; o < 3; o++) {
c[6] = pc[o];
for (int p = 0; p < 3; p++) {
c[7] = pc[p];
for (int q = 0; q < 3; q++) {
c[8] = pc[q];
int countx = 0;
int county = 0;
for(int r = 0 ; r<9 ; r++){
if(c[r] == 'x'){
countx = countx + 1;
}
else if(c[r] == 'o'){
county = county + 1;
}
}
if(Math.abs(countx - county) < 2){
if(won(c, pc[2])+won(c, pc[1]) == 1 ){
System.out.println(c[0] + " " + c[1] + " " + c[2]);
System.out.println(c[3] + " " + c[4] + " " + c[5]);
System.out.println(c[6] + " " + c[7] + " " + c[8]);
System.out.println("*******************************************");
}
}
}
}
}
}
}
}
}
}
}
}
public static int won(char[] c, char n) {
if ((c[0] == n) && (c[1] == n) && (c[2] == n))
return 1;
else if ((c[3] == n) && (c[4] == n) && (c[5] == n))
return 1;
else if ((c[6] == n) && (c[7] == n) && (c[8] == n))
return 1;
else if ((c[0] == n) && (c[3] == n) && (c[6] == n))
return 1;
else if ((c[1] == n) && (c[4] == n) && (c[7] == n))
return 1;
else if ((c[2] == n) && (c[5] == n) && (c[8] == n))
return 1;
else if ((c[0] == n) && (c[4] == n) && (c[8] == n))
return 1;
else if ((c[2] == n) && (c[4] == n) && (c[6] == n))
return 1;
else
return 0;
}
}
`
Below Solution generates all possible combinations using recursion
It has eliminated impossible combinations and returned 888 Combinations
Below is a working code Possible winning combinations of the TIC TAC TOE game
const players = ['X', 'O'];
let gameBoard = Array.from({ length: 9 });
const winningCombination = [
[ 0, 1, 2 ],
[ 3, 4, 5 ],
[ 6, 7, 8 ],
[ 0, 3, 6 ],
[ 1, 4, 7 ],
[ 2, 5, 8 ],
[ 0, 4, 8 ],
[ 2, 4, 6 ],
];
const isWinningCombination = (board)=> {
if((Math.abs(board.filter(a => a === players[0]).length -
board.filter(a => a === players[1]).length)) > 1) {
return false
}
let winningComb = 0;
players.forEach( player => {
winningCombination.forEach( combinations => {
if (combinations.every(combination => board[combination] === player )) {
winningComb++;
}
});
});
return winningComb === 1;
}
const getCombinations = (board) => {
let currentBoard = [...board];
const firstEmptySquare = board.indexOf(undefined)
if (firstEmptySquare === -1) {
return isWinningCombination(board) ? [board] : [];
} else {
return [...players, ''].reduce((prev, next) => {
currentBoard[firstEmptySquare] = next;
if(next !== '' && board.filter(a => a === next).length > (gameBoard.length / players.length)) {
return [...prev]
}
return [board, ...prev, ...getCombinations(currentBoard)]
}, [])
}
}
const startApp = () => {
let combination = getCombinations(gameBoard).filter(board =>
board.every(item => !(item === undefined)) && isWinningCombination(board)
)
printCombination(combination)
}
const printCombination = (combination)=> {
const ulElement = document.querySelector('.combinations');
combination.forEach(comb => {
let node = document.createElement("li");
let nodePre = document.createElement("pre");
let textnode = document.createTextNode(JSON.stringify(comb));
nodePre.appendChild(textnode);
node.appendChild(nodePre);
ulElement.appendChild(node);
})
}
startApp();
This discovers all possible combinations for tic tac toe (255,168) -- written in JavaScript using recursion. It is not optimized, but gets you what you need.
const [EMPTY, O, X] = [0, 4, 1]
let count = 0
let coordinate = [
EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY
]
function reducer(arr, sumOne, sumTwo = null) {
let func = arr.reduce((sum, a) => sum + a, 0)
if((func === sumOne) || (func === sumTwo)) return true
}
function checkResult() {
let [a1, a2, a3, b1, b2, b3, c1, c2, c3] = coordinate
if(reducer([a1,a2,a3], 3, 12)) return true
if(reducer([a1,b2,c3], 3, 12)) return true
if(reducer([b1,b2,b3], 3, 12)) return true
if(reducer([c1,c2,c3], 3, 12)) return true
if(reducer([a3,b2,c1], 3, 12)) return true
if(reducer([a1,b1,c1], 3, 12)) return true
if(reducer([a2,b2,c2], 3, 12)) return true
if(reducer([a3,b3,c3], 3, 12)) return true
if(reducer([a1,a2,a3,b1,b2,b3,c1,c2,c3], 21)) return true
return false
}
function nextPiece() {
let [countX, countO] = [0, 0]
for(let i = 0; i < coordinate.length; i++) {
if(coordinate[i] === X) countX++
if(coordinate[i] === O) countO++
}
return countX === countO ? X : O
}
function countGames() {
if (checkResult()) {
count++
}else {
for (let i = 0; i < 9; i++) {
if (coordinate[i] === EMPTY) {
coordinate[i] = nextPiece()
countGames()
coordinate[i] = EMPTY
}
}
}
}
countGames()
console.log(count)
I separated out the checkResult returns in case you want to output various win conditions.
Could be solved with brute force but keep in mind the corner cases like player2 can't move when player1 has won and vice versa. Also remember Difference between moves of player1 and player can't be greater than 1 and less than 0.
I have written code for validating whether provided combination is valid or not, might soon post on github.

Resources