在c中随机选择5行

时间:2017-11-22 08:20:29

标签: c

我希望能够在C

中随机选择5行

感谢。

2 个答案:

答案 0 :(得分:0)

让我们大声思考。

如果您只需要选择5个任意数字,而这些数字恰好总和低于给定 N 的数字,您可以作弊并选择5个最小的数字;如果它们总和大于 N 的数字,选择任何其他数字也不会有帮助,并且您注册了错误。

如果你希望你的数字总结得非常接近 N (用户问20分钟,你尝试提供19分钟而不是5分钟),它就成了一个背包问题,这是很难,但也许各种近似的解决方法可能有所帮助。

如果您只想选择总计 N 的5个随机数,您可以随机选择5个数字(歌曲)并进行检查。您必须限制完成的尝试次数和/或花费的时间,并准备好报告失败。

以某种方式更有效的算法将保留到目前为止所选择的歌曲列表,以及它们的长度之和 s 。它会尝试添加长度≤ N - s 的随机歌曲。如果在几次尝试后失败,它将从列表中删除最长的歌曲并重复。它必须准备好承认失败,这取决于所做的尝试总次数和/或花费的时间。

我不认为简单的SQL查询可以有效地解决这个问题。但是,您可以将上面的算法编码为非常复杂的SQL查询。我宁愿用Python编码它,因为本地SQLite查找非常快,前提是你的歌曲按长度索引。

答案 1 :(得分:0)

一种可能的解决方案是仅选择个别长度<1的歌曲。 500.然后你尽可能多地保留它们。如果您的小于5或总时间<1。 500,然后你迭代或递归,找到未使用时间的一些歌曲。

def createtimeplay(timee, tot = None, tot_time = 0):
    if tot is None: tot= []  # at first call initialize the result list
    # exclude previously selected songs from the search
    qry = "SELECT * FROM songs WHERE length <= ?"
    if len(tot) > 0:
        qry += " and name not in (" + ','.join(['?'] * len(tot)) + ')'
    qry += " ORDER BY RANDOM() LIMIT 5 "
    curs = c.execute(qry, [timee] + [song[0] for song in tot])
    cur = (curs.fetchall())
    if len(cur) == 0: return tot   # no song were found: we can return
    # keep songs that fit in allowed time
    cur_time = 0
    for song in cur:
        if cur_time + song[1] <= timee:
            cur_time += song[1]
            tot.append(song)
            if (len(tot) == 5) return tot  # never more than 5 songs
    tot_time += cur_time                           # total songs time
    if len(tot) != 5 and cur_time != timee:        # if not all recurse
        createtimeplay(timee - tot_time, tot, tot_time)
    return tot

诀窍是我们传递一个可修改对象的列表,因此所有递归调用都会将歌曲添加到同一列表中。

然后您可以使用:

>>> print(createtimeplay(500))
[('Song 18', 350, 'Country', 'z'), ('Song 4', 150, 'Pop', 'x')]
>>> print(createtimeplay(500))
[('Song 12', 200, 'Country', 'z'), ('Song 3', 100, 'Country', 'z'), ('Song 14', 200, 'Rap', 'y')]
>>> print(createtimeplay(500))
[('Song 5', 300, 'Rap', 'y'), ('Song 7', 200, 'Pop', 'x')]
>>>

但是之前的解决方案效率非常低:当每个查询都是全表扫描时,它需要多个查询,因为顺序是random(),并且当它可以轻松避免时使用递归。只在sqlite级别进行全表扫描,在sqlite或Python中对结果进行混洗,然后只扫描一次完整的随机歌曲列表,保持最大数量为5,并且约束为sqlite,这样既简单又高效。总长度。

代码现在变得更加简单:

def createtimeplay(tim, n, con):
    songs = c.execute("""SELECT name, length, genre, artist
        FROM songs
        WHERE length < ? ORDER BY RANDOM()""", (tim,)).fetchall()
    result = []
    tot = 0
    for song in songs:
        if song[1] <= tim:
            tim -= song[1]
            result.append(song)
            if len(result) == n or tim == 0: break
    return result

在这段代码中,我选择将最大数量和光标或连接传递给sqlite数据库作为参数。