NLinker

Calculate brochure (booklet) pages

Dec 1st, 2017 (edited)
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.24 KB | None | 0 0
  1. from argparse import ArgumentParser, Action
  2. import re
  3.  
  4.  
  5. class RangeAction(Action):
  6.     def __call__(self, parser, namespace, values, option_string=None):
  7.         xs = []
  8.         for v in values:
  9.             try:
  10.                 m = re.match(r'(\d+)(?:\.\.(\d+))?$', v)
  11.                 if m:
  12.                     start = m.group(1)
  13.                     end = m.group(2) or start
  14.                     xs.extend(list(range(int(start, 10), int(end, 10) + 1)))
  15.                 else:
  16.                     xs.append(int(v))
  17.             except ValueError:
  18.                 continue
  19.         flat_xs = sorted(list(set(xs)))
  20.         flat_xs.reverse()
  21.         setattr(namespace, self.dest, flat_xs)
  22.  
  23.  
  24. def run():
  25.     parser = ArgumentParser(description='Calculate brochure pages.')
  26.     parser.add_argument('--xs', metavar='N', action=RangeAction, nargs='*',
  27.                         help='integers for the accumulator')
  28.     args = parser.parse_args()
  29.     print(calc(args.xs))
  30.  
  31.  
  32. # duplex short side!
  33. # 3, 51..101
  34. def calc(pages):
  35.     n0 = len(pages)
  36.     last = pages[-1]
  37.     # ensure pages is divisible by 4
  38.     n = n0 if n0 % 4 == 0 else (n0 // 4 + 1) * 4
  39.     xs = pages + [last] * (n - n0)
  40.     return split(xs, True)
  41.  
  42.  
  43. # xs is guaranteed to have 4k elements
  44. def split(xs, duplex=False):
  45.     n = (len(xs) + 1) // 2
  46.     if not duplex:
  47.         # xs[1::2]  starting from 1 iterating by 2
  48.         (front, back) = split_fb(xs)
  49.         zs = flatten([[x, y] for (x, y) in zip(front, back)])
  50.         return zs[:n], zs[n:]
  51.     else:
  52.         # [1,2,3,4,5,6,7,8] -> ([8,7,6,5],[1,2,3,4])
  53.         (front, back) = reversed(xs[n:]), xs[:n]
  54.         (front2, back2) = list(pairwise(front)), list(pairwise(back))
  55.         f = lambda zs1, zs2: [zs1[0], zs2[0], zs2[1], zs1[1]]
  56.         blocks = [f(zs1, zs2) for (zs1, zs2) in zip(front2, back2)]
  57.         zs = flatten(blocks)
  58.         return zs
  59.  
  60.  
  61. def split_fb(xs):
  62.     (x2s, y2s) = xs[1::2], xs[::2]
  63.     return list(reversed(y2s)), list(x2s)
  64.  
  65.  
  66. def pairwise(xs):
  67.     p = []
  68.     for x in xs:
  69.         if len(p) < 2:
  70.             p.append(x)
  71.         else:
  72.             yield p[:]
  73.             p = [x]
  74.     yield p
  75.  
  76.  
  77. def flatten(xs):
  78.     return [x for x0s in xs for x in x0s]
  79.  
  80.  
  81. if __name__ == "__main__":
  82.     run()
Add Comment
Please, Sign In to add comment