- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
一位 friend 最近要求我编写一个算法,该算法需要 n 个“人”并生成 n-1 x n/2 网格,其中每个可能的对都出现一次,并且在每个 n/2 部分中,不允许任何人出现两次。 (即 person1 与 person 2 匹配,person1 与 person3 匹配无效)。
如果这没有意义,请想象一下:对于 100 个人,创建 99 轮 session ,每个人在每一轮中都会遇到新的人,但没有人在一轮中会面超过一次。这样每轮发生 50 次独特的 session ,共 99 轮,总计 4950 次独特的 session 。
我已经使用递归回溯在 Python 中编写了这个代码(不确定这是否是最好的方法。这个问题让我想起了数独,这是解决数独的一种流行方法)即使对于较小的数字,这也会花费大量时间(例如 50)。是否有更快的编码方法,或者我是否可以添加增强功能以使其运行得更快?
代码在这里:https://pastebin.com/iyr2wdkz
import random
from itertools import combinations
import time as t
import sys
sys.setrecursionlimit(15000)
def isPrime(num):
"""Checks num for primality. Returns bool."""
if num == 2:
return True
elif num < 2 or not num % 2: # even numbers > 2 not prime
return False
# factor can be no larger than the square root of num
for i in range(3, int(num ** .5 + 1), 2):
if not num % i: return False
return True
def generatePrimes(n):
"""Returns a list of prime numbers with length n"""
primes = [2,]
noOfPrimes = 1 # cache length of primes for speed
testNum = 3 # number to test for primality
while noOfPrimes < n:
if isPrime(testNum):
primes.append(testNum)
noOfPrimes += 1
testNum += 2
return primes
class Person:
def __init__(self, name, ID):
self.name = name
self.primeID = ID
def __eq__(self, other):
return self.primeID == other
def __repr__(self):
return '%d' % (self.name)
class Schedule:
def __init__(self, numberofpeople):
self.x = 0 #current x pos
self.y = 0 #current y pos
self.fill = 0 #number of slots filled
self.board = [] #get initialized to an n-1 x n/2 grid to hold links
self.failed = [] #same as board but holds a list of failed links in each cell
self.uniqueLinks = [] #list of unique links, a link is the product of two primes
self.availableLinks = [] #links not yet placed in the grid
self.personList = [] #list of Person. A person is a name and a unique prime number
self.primeList = generatePrimes(numberofpeople) #list of the first n prime numbers
random.shuffle(self.primeList)
#initializes the empty lists
for i in range(numberofpeople):
self.personList.append(Person(i, self.primeList[i]))
self.uniqueLinks = list(map(lambda x: x[0] * x[1], combinations(self.primeList, 2)))
for i in self.uniqueLinks:
self.availableLinks.append(i)
tmp = len(self.uniqueLinks)
for i in range(tmp // (numberofpeople // 2)):
self.board.append(list())
self.failed.append(list())
for i in range(len(self.board)):
for j in range(numberofpeople//2):
self.board[i].append(None)
self.failed[i].append(list())
#checks if the candidate is valid in current position
def isValid(self, candidate):
factor1, factor2 = self.getFactor(candidate)
for i in self.board[self.x]:
if not i:
return True
if ((i % factor1) == 0) or ((i % factor2) == 0):
return False
return True
#moves to the next non-None value, return True if successful
def nextpos(self):
for i in range(len(self.board)):
for j in range(len(self.board[0])):
if not self.board[i][j]:
self.x = i
self.y = j
return True
return False
#sets the last non-None value to None and adds that value to availableLinks and the failed tracker
def prevpos(self):
for i in range(len(self.board)-1, -1, -1):
for j in range(len(self.board[0])-1, -1, -1):
if self.board[i][j]:
self.x = i
self.y = j
tmp = self.board[self.x][self.y]
self.availableLinks.append(tmp)
self.board[i][j] = None
self.failed[i][j].append(tmp)
self.fill -= 1
random.shuffle(self.availableLinks)
return True
#returns the prime factors of num
def getFactor(self, num):
for i in self.primeList:
if num % i == 0:
return i, num/i
#recursive backtracking solving algorithm
def solve(self):
print('%d links placed, %d remaining, pos is %d, %d' % (self.fill, len(self.availableLinks), self.x, self.y))
if not self.nextpos():
return True
for i in self.availableLinks:
if self.isValid(i): and self.checkFail(i):
self.fill += 1
self.board[self.x][self.y] = i
self.availableLinks.remove(i)
if self.solve():
return True
else:
self.prevpos()
return False
#replaces prime products with formatted names of people in the board
def decompose(self):
for i in range(len(self.board)):
for j in range(len(self.board[0])):
num1, num2 = self.getFactor(self.board[i][j])
for k in self.personList:
if k == num1:
person1 = str(k)
if k == num2:
person2 = str(k)
self.board[i][j] = person1 + '<-->' + person2
# checks if num has already been tried at current pos, returns false if is has.
def checkFail(self, num):
if num in self.failed[self.x][self.y]:
return False
else:
return True
# verifies that the board has no duplicate values
def verify(self):
visited = []
for i in self.board:
for j in i:
if j in visited:
print('Verification failed %s occurs twice'% j)
return False
visited.append(j)
print('Successfully verified')
return True
s =Schedule(50)
s.solve()
s.verify()
s.decompose()
print(s.board)
最佳答案
多么可观的代码量!
这是 scala 中的一个解决方案。我只使用 Ints,您可以将其映射到 Person.ID:
def greetAsMad (persons: List [Int]) : List [(Int, Int)] =
if (persons.size < 2) Nil else
persons.tail.map (p=> (persons.head, p)) ::: greetAsMad (persons.tail)
对于 100 人,它立即返回(< 200 毫秒)。
为了准备更多的人,我会把它变成一个尾递归函数。
想法是,第 1 个人向所有人打招呼,然后离开房间。然后第 2 个人跟大家打招呼,也离开了。最后,第 99 个人与第 100 个人打招呼,两人都离开了房间。
然后他们开始吃喝。
这是一个非递归的方法:
for (i <- 1 to 99;
j <- i + 1 to 100) yield (i, j)
关于python - 优化匹配算法运行时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48554542/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!