Advertisement
Guest User

Matching Algorithm

a guest
Jan 31st, 2018
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.68 KB | None | 0 0
  1. import random
  2. from itertools import combinations
  3. import time as t
  4. import sys
  5. sys.setrecursionlimit(15000)
  6.  
  7. def isPrime(num):
  8.     """Checks num for primality. Returns bool."""
  9.     if num == 2:
  10.         return True
  11.     elif num < 2 or not num % 2: # even numbers > 2 not prime
  12.         return False
  13.         # factor can be no larger than the square root of num
  14.     for i in range(3, int(num ** .5 + 1), 2):
  15.         if not num % i: return False
  16.     return True
  17.  
  18. def generatePrimes(n):
  19.     """Returns a list of prime numbers with length n"""
  20.     primes = [2,]
  21.     noOfPrimes = 1  # cache length of primes for speed
  22.     testNum = 3 # number to test for primality
  23.     while noOfPrimes < n:
  24.         if isPrime(testNum):
  25.             primes.append(testNum)
  26.             noOfPrimes += 1
  27.         testNum += 2
  28.     return primes
  29.  
  30.  
  31.  
  32. class Person:
  33.     def __init__(self, name, ID):
  34.         self.name = name
  35.         self.primeID = ID
  36.  
  37.     def __eq__(self, other):
  38.         return self.primeID == other
  39.  
  40.     def __repr__(self):
  41.         return '%d' % (self.name)
  42.  
  43. class Schedule:
  44.     def __init__(self, numberofpeople):
  45.         self.x = 0 #current x pos
  46.         self.y = 0 #current y pos
  47.         self.fill = 0 #number of slots filled
  48.         self.board = [] #get initialized to an n-1 x n/2 grid  to hold links
  49.         self.failed = [] #same as board but holds a list of failed links in each cell
  50.         self.uniqueLinks = [] #list of unique links, a link is the product of two primes
  51.         self.availableLinks = [] #links not yet placed in the grid
  52.         self.personList = [] #list of Person. A person is a name and a unique prime number
  53.         self.primeList = generatePrimes(numberofpeople) #list of the first n prime numbers
  54.         random.shuffle(self.primeList)
  55.  
  56.         #initializes the empty lists
  57.         for i in range(numberofpeople):
  58.             self.personList.append(Person(i, self.primeList[i]))
  59.         self.uniqueLinks = list(map(lambda x: x[0] * x[1], combinations(self.primeList, 2)))
  60.         for i in self.uniqueLinks:
  61.             self.availableLinks.append(i)
  62.         tmp = len(self.uniqueLinks)
  63.         for i in range(tmp // (numberofpeople // 2)):
  64.             self.board.append(list())
  65.             self.failed.append(list())
  66.         for i in range(len(self.board)):
  67.             for j in range(numberofpeople//2):
  68.                 self.board[i].append(None)
  69.                 self.failed[i].append(list())
  70.  
  71.     #checks if the candidate is valid in current position
  72.     def isValid(self, candidate):
  73.         factor1, factor2 = self.getFactor(candidate)
  74.         for i in self.board[self.x]:
  75.             if not i:
  76.                 return True
  77.             if ((i % factor1) == 0) or ((i % factor2) == 0):
  78.                 return False
  79.         return True
  80.  
  81.     #moves to the next non-None value, return True if successful
  82.     def nextpos(self):
  83.         for i in range(len(self.board)):
  84.             for j in range(len(self.board[0])):
  85.                 if not self.board[i][j]:
  86.                     self.x = i
  87.                     self.y = j
  88.                     return True
  89.         return False
  90.  
  91.     #sets the last non-None value to None and adds that value to availableLinks and the failed tracker
  92.     def prevpos(self):
  93.         for i in range(len(self.board)-1, -1, -1):
  94.             for j in range(len(self.board[0])-1, -1, -1):
  95.                 if self.board[i][j]:
  96.                     self.x = i
  97.                     self.y = j
  98.                     tmp = self.board[self.x][self.y]
  99.                     self.availableLinks.append(tmp)
  100.                     self.board[i][j] = None
  101.                     self.failed[i][j].append(tmp)
  102.                     self.fill -= 1
  103.                     random.shuffle(self.availableLinks)
  104.                     return True
  105.  
  106.  
  107.     #returns the prime factors of num
  108.     def getFactor(self, num):
  109.         for i in self.primeList:
  110.             if num % i == 0:
  111.                 return i, num/i
  112.  
  113.  
  114.     #recursive backtracking solving algorithm
  115.     def solve(self):
  116.         print('%d links placed, %d remaining, pos is %d, %d' % (self.fill, len(self.availableLinks), self.x, self.y))
  117.         if not self.nextpos():
  118.             return True
  119.         for i in self.availableLinks:
  120.             if self.isValid(i): and self.checkFail(i):
  121.                 self.fill += 1
  122.                 self.board[self.x][self.y] = i
  123.                 self.availableLinks.remove(i)
  124.                 if self.solve():
  125.                     return True
  126.                 else:
  127.                     self.prevpos()
  128.         return False
  129.  
  130.     #replaces prime products with formatted names of people in the board
  131.     def decompose(self):
  132.         for i in range(len(self.board)):
  133.             for j in range(len(self.board[0])):
  134.                 num1, num2 = self.getFactor(self.board[i][j])
  135.                 for k in self.personList:
  136.                     if k == num1:
  137.                         person1 = str(k)
  138.                     if k == num2:
  139.                         person2 = str(k)
  140.                 self.board[i][j] = person1 + '<-->' + person2
  141.  
  142.  
  143.     # checks if num has already been tried at current pos, returns false if is has.
  144.     def checkFail(self, num):
  145.         if num in self.failed[self.x][self.y]:
  146.             return False
  147.         else:
  148.             return True
  149.  
  150.     # verifies that the board has no duplicate values
  151.     def verify(self):
  152.         visited = []
  153.         for i in self.board:
  154.             for j in i:
  155.                 if j in visited:
  156.                     print('Verification failed %s occurs twice'% j)
  157.                     return False
  158.                 visited.append(j)
  159.         print('Successfully verified')
  160.         return True
  161.  
  162.  
  163. s =Schedule(50)
  164. s.solve()
  165. s.verify()
  166. s.decompose()
  167. print(s.board)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement