The example below is working however, if more zeros (empty cells) are added to the sudoku grid g, it takes longer to run, if it ever finishes. Not asking for a code review here, just I might've overlooked something, and I'd appreciate pointing it out.
def is_solved(grid):
for row, col in zip(grid, [*zip(*grid)]):
for i in range(1, 10):
if (i not in row) or (i not in col):
return False
return True
def square_available(rows, x, y, n):
if 0 <= x < 3:
rows = rows[:3]
elif 3 <= x < 6:
rows = rows[3:6]
else:
rows = rows[6:]
if 0 <= y < 3:
return not any([n in r[:3] for r in rows])
elif 3 <= y < 6:
return not any([n in r[3:6] for r in rows])
else:
return not any([n in r[6:] for r in rows])
def is_valid(grid, x, y, n):
columns = [*zip(*grid)]
return (
square_available(grid, x, y, n) and n not in grid[x] and (n not in columns[y])
)
def solve(grid, empty_cells):
if is_solved(grid):
return grid
for x, y in empty_cells:
for n in range(1, 10):
if is_valid(grid, x, y, n):
grid[x][y] = n
empty_cells.remove((x, y))
if solve(grid, empty_cells):
return grid
else:
grid[x][y] = 0
empty_cells.append((x, y))
if __name__ == '__main__':
solution = [
[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 7],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9],
]
g = [
[0, 0, 0, 6, 0, 8, 9, 1, 0],
[6, 0, 2, 0, 9, 0, 3, 4, 0],
[1, 9, 8, 3, 0, 0, 0, 6, 7],
[0, 5, 9, 0, 0, 0, 4, 2, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 1, 3, 0, 2, 0, 8, 0, 0],
[9, 6, 0, 5, 3, 7, 2, 8, 0],
[2, 0, 0, 4, 1, 0, 0, 3, 0],
[3, 4, 0, 2, 8, 0, 1, 7, 9],
]
empty = []
for i in range(9):
for j in range(9):
if not g[i][j]:
empty.append((i, j))
solved = solve(g, empty)
assert g == solution
I tried reimplementing the whole thing as shown below, and the results got worse. It's not even capable of solving what's already possible with the implementation above.
from collections import defaultdict
def get_possibilities(rows, columns, x, y, visited):
if (x, y) in visited:
return visited[x, y]
x0 = (x // 3) * 3
x1 = x0 + 3
y0 = (y // 3) * 3
y1 = y0 + 3
possibilities = set()
for n in range(1, 10):
square_rows = rows[x0:x1]
for row in square_rows:
if n in row[y0:y1]:
continue
if (n not in rows[x]) and (n not in columns[y]):
visited[x, y].add(n)
possibilities.add(n)
return possibilities
def solve(rows, columns, empty_cells, visited):
if not empty_cells:
return rows
for x, y in empty_cells:
for n in get_possibilities(rows, columns, x, y, visited):
rows[x][y] = n
columns[y][x] = n
visited[x, y].remove(n)
if solve(rows, columns, empty_cells - {(x, y)}, visited):
return rows
else:
rows[x][y] = 0
columns[y][x] = 0
visited[x, y].add(n)
if __name__ == '__main__':
solution = [
[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 7],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9],
]
r = [
[0, 0, 0, 6, 0, 8, 9, 1, 0],
[6, 0, 2, 0, 9, 0, 3, 4, 0],
[1, 9, 8, 3, 0, 0, 0, 6, 7],
[0, 5, 9, 0, 0, 0, 4, 2, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 1, 3, 0, 2, 0, 8, 0, 0],
[9, 6, 0, 5, 3, 7, 2, 8, 0],
[2, 0, 0, 4, 1, 0, 0, 3, 0],
[3, 4, 0, 2, 8, 0, 1, 7, 9],
]
c = [list(r) for r in [*zip(*r)]]
cells = set()
for i in range(9):
for j in range(9):
if not r[i][j]:
cells.add((i, j))
v = defaultdict(set)
solved = solve(r, c, cells, v)
assert r == solution
Looking only at the first version of your code, there are a few things you can improve in the solve function:
(A problem also in the second version:) You shouldn't loop over all empty_cells. Instead consider that you must find a solution for the first empty cell, and if after doing all of the recursive effort there is no good value for this first empty cell, then it makes no sense to continue with other empty cells. The first one represents a problem that is unsolvable, so any effort on any other empty cell is useless. So remove that for loop, and just work with one empty cell per recursion level.
You don't need to call is_solved to know that the grid has been completed. You did this better in the second version. Just test not empty_cells or something similar.
Don't call empty_cells.remove and append in each iteration of the inner loop as it is always the same that is removed and added again. Moreover, remove is overkill as you don't really want to search for the entry -- you know at which index it sits. Just do the removal at the start of the process, and add it again at the very end.
With the above changes the performance will greatly improve. Still some little improvements are possible:
Leave the empty_cells list unmutated, and instead pass along an index in that list. We can assume that all empty cells before that index have been filled in, and the others are still to do.
Instead of calling is_valid on each digit, collect the valid moves -- an idea you tried to implement in the second version.
Here is the improved version:
def valid_moves(grid, x, y):
ybox = y - y % 3
xbox = x - x % 3
return set(range(1, 10)).difference(
grid[x]
).difference(
(row[y] for row in grid)
).difference(
(num for row in grid[xbox: xbox + 3]
for num in row[ybox: ybox + 3])
)
def solve(grid, empty_cells, i=0):
if i >= len(empty_cells):
return grid
x, y = empty_cells[i]
i += 1
for n in valid_moves(grid, x, y):
grid[x][y] = n
if solve(grid, empty_cells, i):
return grid
grid[x][y] = 0
Related
so,I have a list [5. 5. 5. 5. 0. 0.] I want to check if it contains same elements in straight row (atleast 4 )
I came up with this
for i in list:
w = []
for x in range(len(i)-4):
if (i[x] == i[x+1] == i[x+2] == i[x+3] != 0) :
print(i[x])
break
I gives me desired output,
but , what would the efficient way to achieving the same result ,without much looping ?
In numpy it's worth to find indices of value changes and return every index that preceeds another index that differs not less than 4.
x = np.array([6,6,6,6,7,7,8,8,4,4,4,4,4,4,4,3,3,3,3])
div_points = np.flatnonzero(np.diff(x, prepend=x[0]+1, append=x[-1]+1))
idx = np.r_[np.diff(div_points)>=4, False]
x[div_points[idx]]
>>> array([6, 4, 3])
And if you're quite lazy, you could just 'slide' all the comparisons:
view = np.lib.stride_tricks.sliding_window_view(x, 4)
view
array([[6, 6, 6, 6],
[6, 6, 6, 7],
[6, 6, 7, 7],
[6, 7, 7, 8],
[7, 7, 8, 8],
[7, 8, 8, 4],
[8, 8, 4, 4],
[8, 4, 4, 4],
[4, 4, 4, 4],
[4, 4, 4, 4],
[4, 4, 4, 4],
[4, 4, 4, 4],
[4, 4, 4, 3],
[4, 4, 3, 3],
[4, 3, 3, 3],
[3, 3, 3, 3]])
r = np.all(x[:-3, None] == view, axis=1)
x[:-3][r]
>>> array([6, 4, 4, 4, 4, 3])
Here's a one-liner that will return the indexes of all items in the specified 1D array that are identical to the next N items. Note that it requires the array be of floats because it uses NaN.
import functools as ft
N = 3
indexes = np.where(ft.reduce(lambda prev, cur: prev.astype(bool) & (cur == a), [np.pad(a, (0,i), constant_values=np.nan)[i:] for i in range(1, N+1)]))[0]
Example:
>>> import functools as ft
>>> a = np.array([1, 2, 3, 3, 3, 3, 4, 5, 10, 10, 10, 10, 10, 2, 4], dtype=float)
>>> N = 3
>>> indexes = np.where(ft.reduce(lambda prev, cur: prev.astype(bool) & (cur == a), [np.pad(a, (0,i), constant_values=np.nan)[i:] for i in range(1, N+1)]))[0]
>>> indexes
array([2, 8, 9])
Now, if we look at the array and the indexes:
[1, 2, 3, 3, 3, 3, 4, 5, 10, 10, 10, 10, 10, 2, 4]
^ 2 ^^ 8
^^ 9
Try this:
lst = [3, 5, 5, 5, 5, 0, 0]
for i in range(4, len(lst)):
if len(set(lst[i-4:i]))==1:
print(lst[i-4])
If you want to solve this problem without any library, you can iterate the list and count the Continuous elements:
a = [
[5, 5, 5, 5, 0, 0],
[1, 2, 3, 4, 5, 6],
[0, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0],
[0, 1, 2, 2, 2, 2],
[1, 1, 1, 1]
]
def contains_n(n, l):
c = 0
last = ""
for v in l:
if v == last:
c += 1
else:
c = 1
last = v
if c == n:
return True
return False
for v in a:
print(contains_n(4, v))
The output will be:
True
False
False
True
True
True
I got this code
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 9]
B = [0 for b in range(16)]
skipped = 0
for i in range(16):
if A[i] == A[i-1]:
skipped += 1
else:
B[i-skipped] = A[i]
print(B)
The output:
[1, 2, 3, 4, 5, 2, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0]
it eliminates the doubles. But if i got an array where doubles are at more random index it fails, like:
The Array#2:
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 2, 2, 2, 7, 8, 8, 9]
The output#2
[1, 2, 3, 4, 5, 2, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0]
In the output#2 there is the value 2 at index 1 and index 5, but i just want to eliminate all the doubles.
Sum:
So basically my algorithm should copy the values from Array A to Array B and eliminate all doubles independent from their index.
EDIT: i have to put it in pseudocode so i cant use convert methods or functions like SET
You can use set to do it:
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 9]
B = set(A)
print(B)
This code returns a set. To convert set to list you can write some_list = list(B).
Another way to do what you need:
A = [1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 9]
B = []
for x in A:
if x not in B:
B.append(x)
print(B)
As title mentioned. Obviously, the code stoped at the second ROW of the output board.I have been checking it for more than a hundred times but I still could not find where it goes wrong. I would be so grateful if you guys can tell me where I did wrong. Below is my code.
def solve(board):
if not find_zero(board):
return True
else:
row, col = find_zero(board)
for value in range(1, 10):
if is_valid(board, row, col, value):
board[row][col] = value
if solve(board):
return True
board[row][col] == 0
return False
def find_zero(board):
for i in range(9):
for j in range(9):
if board[i][j] == 0:
return i, j
return None, None
def is_valid(board, row, col, value):
# Check the row
if value in board[row]:
return False
# Check the column
col_vals = [board[i][col] for i in range(9)]
if value in col_vals:
return False
# Check the grid
x = (row // 3) * 3
y = (col // 3) * 3
for i in range(x, x + 3):
for j in range(y, y + 3):
if board[i][j] == value:
return False
return True
Here is the board and the output of my code.
board = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9],
]
False
[5, 3, 1, 2, 7, 6, 8, 9, 4],
[6, 2, 4, 1, 9, 5, 7, 3, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
In addition to the problem Conor pointed out. There also is the problem that board is mutable and you change the board in potentially invalid ways that need to be rolled back. If you make a deepcopy of it every time you pass it to solve it works. Since I only changed the solve method I will post just that:
import copy
def solve(board):
if find_zero(board)[0] is None:
for row in board:
print(row)
return True
else:
row, col = find_zero(board)
for value in range(1, 10):
if is_valid(board, row, col, value):
new_board = copy.deepcopy(board)
new_board[row][col] = value
if solve(new_board):
return True
return False
In the end you get
[5, 3, 4, 6, 7, 8, 9, 1, 2]
[6, 7, 2, 1, 9, 5, 3, 4, 8]
[1, 9, 8, 3, 4, 2, 5, 6, 7]
[8, 5, 9, 7, 6, 1, 4, 2, 3]
[4, 2, 6, 8, 5, 3, 7, 9, 1]
[7, 1, 3, 9, 2, 4, 8, 5, 6]
[9, 6, 1, 5, 3, 7, 2, 8, 4]
[2, 8, 7, 4, 1, 9, 6, 3, 5]
[3, 4, 5, 2, 8, 6, 1, 7, 9]
True
The find_zero method returns a tuple of length 2. A non-zero length tuple will always evaluate to True, irrespective of its contents, so the conditional at the start of the solve method can never return True.
Thus your code will never recognise a valid solution. You should return None or False from find_zero if it doesn't find any.
I need to calculate the sum of elementwise subtracts from the vector from the following equitation:
sum(y(i) - y(j)) at i!=j
y is given as a numpy array
One option is to iterate through the double loop:
dev = 0
for i in range(y.shape[0]):
for j in range(y.shape[0]):
if i == j:
continue
dev += y[i, j] - y[i, j]
That is definitely not the optimal solution.
How it can be optimized using vectorized operations with numpy vectors?
Say y is flat, e.g.
>>> y = np.arange(10)
>>> y
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> y.shape
(10,)
You could compute the "cartesian differences" as follows
>>> m = np.abs(y[:, None] - y[None, :])
>>> m
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 0, 1, 2, 3, 4, 5, 6, 7, 8],
[2, 1, 0, 1, 2, 3, 4, 5, 6, 7],
[3, 2, 1, 0, 1, 2, 3, 4, 5, 6],
[4, 3, 2, 1, 0, 1, 2, 3, 4, 5],
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4],
[6, 5, 4, 3, 2, 1, 0, 1, 2, 3],
[7, 6, 5, 4, 3, 2, 1, 0, 1, 2],
[8, 7, 6, 5, 4, 3, 2, 1, 0, 1],
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]])
and finally
>>> dev = m.sum()/2
>>> dev
165.0
using itertools combination:
import itertools
sum([x2 - x1 for x1, x2 in itertools.combinations(y, 2)])
using np.subtract.outer
np.abs(np.subtract.outer(y,y)).sum()/2
Time Comparison:
Method 1 (Using Itertools):
Wall time: 18.9 s
Method 2 (Using KeepAlive's cartesian differences):
Wall time: 491 ms
Method 3 (Using np.subtract.outer):
Wall time: 467 ms
This IS a homework problem, but I've been working on it for a while and I don't understand what I am doing wrong. Any help would be appreciated.
Count the number of ways that N dinner guests can arrange themselves around a round table, according to the following rules:
Initially, all guests are seated at a round table with no empty seats. To encourage conversations, the host asks each guest to stand up, and then sit in one of three chairs: the original chair, one to the left or one to the right.
All guests must sit down.
How many different arrangements of dinner guests are there?
Two arrangements are different if the chair number for any guest differs from one arrangement to the other.
ABCD is different from DABC. However, no one person can move more than two places,
I.E BCAD would be invalid because A has moved two place.
The partial solutions are:
3 guests can sit in 6 different ways
4 guests can sit in 9 different ways
5 guests can sit in 13 different ways
6 guests can sit in 20 different ways
7 guests can sit in 31 different ways
My code is working for up to 5 guests, but for 6 guests, I am getting 19 different arrangements. For 7 guests, I am getting 28 arrangements. I am guessing there is something off with my logic but I can not figure it out.
Here's my code:
def dinner_party_arrangements(N):
import itertools
if N > 10:
return('This function is not built for N > 10.')
else:
import math
result=math.factorial(N)
baseL=[]
main=list(range(N))
L=list(range(N+1))
L.remove(0)
combos=(list(itertools.permutations(L)))
for stuff in combos:
baseL.append(stuff)
for guests in baseL:
resultL=list(guests)
#looks at single tuple
for num in main:
a=num
b=num+1
c=num+2
if resultL[num] == a or resultL[num] == b or resultL[num] == c:
pass
else:
result=(result-1)
break
if N<3:
return(result)
else:
return(result+N)
Here's the refactored version of your code, for a better understanding:
import itertools
import math
def dinner_party_arrangements(N):
assert N <= 10, 'This function is not built for N > 10.'
result = math.factorial(N)
if N < 3:
return result
for guests in itertools.permutations(range(1, N+1)):
for num in range(N):
if guests[num] not in (num, num+1, num+2):
result -= 1
break
return result+N
I think the problem is that you don't manage the "edges", i.e. position 0 can be occupied by guest 1 (no change), guest 2, (right neighbour) or guest N (the last one, which is the left neighbour). The same goes for the last position on the table. Therefore, the following will work (leaving imports aside):
def dinner_party_arrangements(N):
assert N <= 10, 'This function is not built for N > 10.'
if N < 3:
return math.factorial(N)
allguests = list(itertools.permutations(range(1,N+1)))
result = len(allguests)
for guests in allguests:
for num in range(N):
if guests[num] not in (N if num==0 else num, num+1, 1 if num==N-1 else num+2):
result -= 1
break
return result
Also note that I don't use factorial in N>2; I just count the number of permutations that are correct.
Even better, the following uses the lazy nature of the permutations function:
def dinner_party_arrangements(N):
assert N <= 10, 'This function is not built for N > 10.'
if N < 3:
return math.factorial(N)
result = 0
for guests in itertools.permutations(range(1,N+1)):
for num in range(N):
if guests[num] not in (N if num==0 else num, num+1, 1 if num==N-1 else num+2):
break
else:
result += 1
return result
Finally, here's a recursive solution for this. As opposed to your (and other peoples) approach I don't generate every permutation and then eliminate the wrong ones; I create the solutions from scratch. Also, I use 0-based numbering which seems more natural to me:
def dinner(gst):
assert gst > 2 # alogorith doesn't work for < 3 people
res = [] # result, the list of all possible combinations
def sub(current, pers):
if pers == gst: # base case of recursion; no more person to sit
res.append(current) # found one combo, add it to result
return # and stop here
for offset in (-1, 0, +1): # for each move (left, stay, right)
newpos = (pers + offset) % gst # compute new position
if current[newpos] is None: # seat is not yet taken
newcurrent = current[:] # create a copy of current (incomplete) combination
newcurrent[newpos] = pers # sit person pos at position newpos
sub(newcurrent, pers + 1) # and recurse for the other persons
sub([None]*gst, 0) # initialize a combi
return res
then
for i in range(3, 8):
combos = dinner(i)
print(i, "guests can sit in", len(combos), "ways", combos)
yields
3 guests can sit in 6 ways [[1, 2, 0], [2, 1, 0], [0, 1, 2], [0, 2, 1], [1, 0, 2], [2, 0, 1]]
4 guests can sit in 9 ways [[1, 2, 3, 0], [3, 1, 2, 0], [3, 2, 1, 0], [0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [1, 0, 2, 3], [1, 0, 3, 2], [3, 0, 1, 2]]
5 guests can sit in 13 ways [[1, 2, 3, 4, 0], [4, 1, 2, 3, 0], [4, 1, 3, 2, 0], [4, 2, 1, 3, 0], [0, 1, 2, 3, 4], [0, 1, 2, 4, 3], [0, 1, 3, 2, 4], [0, 2, 1, 3, 4], [0, 2, 1, 4, 3], [1, 0, 2, 3, 4], [1, 0, 2, 4, 3], [1, 0, 3, 2, 4], [4, 0, 1, 2, 3]]
6 guests can sit in 20 ways [[1, 2, 3, 4, 5, 0], [5, 1, 2, 3, 4, 0], [5, 1, 2, 4, 3, 0], [5, 1, 3, 2, 4, 0], [5, 2, 1, 3, 4, 0], [5, 2, 1, 4, 3, 0], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 5, 4], [0, 1, 2, 4, 3, 5], [0, 1, 3, 2, 4, 5], [0, 1, 3, 2, 5, 4], [0, 2, 1, 3, 4, 5], [0, 2, 1, 3, 5, 4], [0, 2, 1, 4, 3, 5], [1, 0, 2, 3, 4, 5], [1, 0, 2, 3, 5, 4], [1, 0, 2, 4, 3, 5], [1, 0, 3, 2, 4, 5], [1, 0, 3, 2, 5, 4], [5, 0, 1, 2, 3, 4]]
7 guests can sit in 31 ways [[1, 2, 3, 4, 5, 6, 0], [6, 1, 2, 3, 4, 5, 0], [6, 1, 2, 3, 5, 4, 0], [6, 1, 2, 4, 3, 5, 0], [6, 1, 3, 2, 4, 5, 0], [6, 1, 3, 2, 5, 4, 0], [6, 2, 1, 3, 4, 5, 0], [6, 2, 1, 3, 5, 4, 0], [6, 2, 1, 4, 3, 5, 0], [0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 6, 5], [0, 1, 2, 3, 5, 4, 6], [0, 1, 2, 4, 3, 5, 6], [0, 1, 2, 4, 3, 6, 5], [0, 1, 3, 2, 4, 5, 6], [0, 1, 3, 2, 4, 6, 5], [0, 1, 3, 2, 5, 4, 6], [0, 2, 1, 3, 4, 5, 6], [0, 2, 1, 3, 4, 6, 5], [0, 2, 1, 3, 5, 4, 6], [0, 2, 1, 4, 3, 5, 6], [0, 2, 1, 4, 3, 6, 5], [1, 0, 2, 3, 4, 5, 6], [1, 0, 2, 3, 4, 6, 5], [1, 0, 2, 3, 5, 4, 6], [1, 0, 2, 4, 3, 5, 6], [1, 0, 2, 4, 3, 6, 5], [1, 0, 3, 2, 4, 5, 6], [1, 0, 3, 2, 4, 6, 5], [1, 0, 3, 2, 5, 4, 6], [6, 0, 1, 2, 3, 4, 5]]
I hope this helps.
Here's my approach. It's really slow for large n, but it works.
from itertools import permutations
def arrange( n ):
# First, place all your guests (0 - n) into an array
positions = range( n )
arrangements = 0
# Iterate over every possible arrangement of guests
for arrangement in permutations( positions ):
# begin by assuming the iteration is "valid", that is, no guest
# hopped more than one spot
is_valid = True
# Now iterate over all your guests
for i in range( n ):
# If the guest moved more than one spot, this permutation is
# invalid and we can throw it out
pos_dif = abs( arrangement.index( i ) - positions.index( i ) )
if pos_dif > 1 and pos_dif != n-1:
is_valid = False
break
# Otherwise, the iteration is valid and we can increment our count
if is_valid:
arrangements += 1
return arrangements
My approach was similar to the above post:
def mydin(n):
import itertools
initial_table = range(n)
poss_tables = set(itertools.permutations(initial_table))
validTables = []
for table in poss_tables:
if isValid(initial_table,table):
validTables.append(table)
print len(validTables)
return len(validTables)
def isValid(initial_table,arrangement):
size = initial_table[-1]
for i in range(len(initial_table)):
if i == size:
if arrangement[i] in (initial_table[i-1],initial_table[i],initial_table[0]):
continue
else:
return False
elif arrangement[i] in [initial_table[i-1],initial_table[i],initial_table[i+1]]:
continue
else:
return False
return True
for n in range(3,11):
mydin(n)
and for my output I got
6
9
13
20
31
49
78
125