Получение конечных точек наборов через диапазон - PullRequest
0 голосов
/ 29 сентября 2011

Для жизни я не могу понять, как это сделать. Мне нужно собрать непересекающиеся конечные точки нескольких наборов в диапазоне чисел с помощью Python.

Например, пользователь может ввести диапазон 10 и два набора 2 и 3. Мне нужно получить конечные точки этих наборов в этом диапазоне, так что:

set 2 groupings: 1-2,6-7
set 3 groupings: 3-5,8-10

Диапазон, количество наборов и размер любого отдельного набора является произвольным. Я не могу выйти за пределы диапазона, поэтому нет половины подходов.

Я продолжаю думать, что для этого должна быть простая формула, но я не могу ее придумать.

Редактировать

В соответствии с запросом для примера ввода диапазона 12 и наборов 1, 2 и 3, вывод должен быть:

set 1: 1,7
set 2: 2-3,8-9
set 3: 4-6,10-12

Насколько я понимаю, я смотрю на какую-то модель аккумулятора. Примерно такой код псевдо:

for each miniRange in range:
    for each set in sets:
        listOfCurrSetEndpoints.append((start, end))

Ответы [ 2 ]

2 голосов
/ 29 сентября 2011

Я не думаю, что есть хорошее встроенное решение для этого.(Было бы проще, если бы был встроенный эквивалент функции scan на Haskell.) Но это достаточно лаконично:

>>> import itertools
>>> from collections import defaultdict
>>> partition_lengths = [1, 2, 3]
>>> range_start = 1
>>> range_end = 12
>>> endpoints = defaultdict(list)
>>> for p_len in itertools.cycle(partition_lengths):
...     end = range_start + p_len - 1
...     if end > range_end: break
...     endpoints[p_len].append((range_start, end))
...     range_start += p_len
... 
>>> endpoints
defaultdict(<type 'list'>, {1: [(1, 1), (7, 7)], 2: [(2, 3), (8, 9)], 3: [(4, 6), (10, 12)]})

Теперь вы можете отформатировать словарь endpoints для вывода так, как вам нравится..

Кроме того, я действительно смущен тем, что вы использовали "set" в этом вопросе, поэтому я использовал вместо него "partition".

0 голосов
/ 29 сентября 2011

Я не совсем доволен этим, но я получил рабочую программу.Если кто-то может придумать лучший ответ, я с радостью приму его.

import argparse, sys

if __name__ == "__main__":

    parser = argparse.ArgumentParser(description='Take a number of pages, and the pages in several sets, to produce an output for copy and paste into the print file downloader', version='%(prog)s 2.0')
    parser.add_argument('pages', type=int, help='Total number of pages to break into sets')
    parser.add_argument('stapleset', nargs='+', type=int, help='number of pages in each set')
    args = parser.parse_args()

    data = {}
    for c,s in enumerate(args.stapleset):
        data[c] = []

    currPage = 0
    while currPage <= args.pages:
        for c,s in enumerate(args.stapleset):
            if currPage + 1 > args.pages:
                pass
            elif currPage + s > args.pages:
                data[c].append((currPage+1,args.pages))
            else:
                data[c].append((currPage+1,currPage+s))
            currPage = currPage + s

    for key in sorted(data.iterkeys()):
        for c,t in enumerate(data[key]):
            if c > 0:
                sys.stdout.write(",")
            sys.stdout.write("{0}-{1}".format(t[0],t[1]))
        sys.stdout.write("\n\n")
...