Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from argparse import ArgumentParser, Action
- import re
- class RangeAction(Action):
- def __call__(self, parser, namespace, values, option_string=None):
- xs = []
- for v in values:
- try:
- m = re.match(r'(\d+)(?:\.\.(\d+))?$', v)
- if m:
- start = m.group(1)
- end = m.group(2) or start
- xs.extend(list(range(int(start, 10), int(end, 10) + 1)))
- else:
- xs.append(int(v))
- except ValueError:
- continue
- flat_xs = sorted(list(set(xs)))
- flat_xs.reverse()
- setattr(namespace, self.dest, flat_xs)
- def run():
- parser = ArgumentParser(description='Calculate brochure pages.')
- parser.add_argument('--xs', metavar='N', action=RangeAction, nargs='*',
- help='integers for the accumulator')
- args = parser.parse_args()
- print(calc(args.xs))
- # duplex short side!
- # 3, 51..101
- def calc(pages):
- n0 = len(pages)
- last = pages[-1]
- # ensure pages is divisible by 4
- n = n0 if n0 % 4 == 0 else (n0 // 4 + 1) * 4
- xs = pages + [last] * (n - n0)
- return split(xs, True)
- # xs is guaranteed to have 4k elements
- def split(xs, duplex=False):
- n = (len(xs) + 1) // 2
- if not duplex:
- # xs[1::2] starting from 1 iterating by 2
- (front, back) = split_fb(xs)
- zs = flatten([[x, y] for (x, y) in zip(front, back)])
- return zs[:n], zs[n:]
- else:
- # [1,2,3,4,5,6,7,8] -> ([8,7,6,5],[1,2,3,4])
- (front, back) = reversed(xs[n:]), xs[:n]
- (front2, back2) = list(pairwise(front)), list(pairwise(back))
- f = lambda zs1, zs2: [zs1[0], zs2[0], zs2[1], zs1[1]]
- blocks = [f(zs1, zs2) for (zs1, zs2) in zip(front2, back2)]
- zs = flatten(blocks)
- return zs
- def split_fb(xs):
- (x2s, y2s) = xs[1::2], xs[::2]
- return list(reversed(y2s)), list(x2s)
- def pairwise(xs):
- p = []
- for x in xs:
- if len(p) < 2:
- p.append(x)
- else:
- yield p[:]
- p = [x]
- yield p
- def flatten(xs):
- return [x for x0s in xs for x in x0s]
- if __name__ == "__main__":
- run()
Add Comment
Please, Sign In to add comment