Advertisement
Guest User

Cube Counter

a guest
Sep 10th, 2015
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.66 KB | None | 0 0
  1. #/usr/bin/python
  2. # -*- coding: utf8 -*-
  3.  
  4. def build_rotations():
  5.   # base table provides rotations that map each axis onto the X axis in both
  6.   # orientations
  7.   base_rotations = [
  8.     [0, 1, 2,  1,  1,  1],
  9.     [0, 1, 2, -1, -1,  1], # 180° rotation about Z
  10.     [1, 0, 2,  1, -1,  1], # +90° rotation about Z
  11.     [1, 0, 2, -1,  1,  1], # -90° rotation about Z
  12.     [2, 1, 0,  1,  1, -1], # +90° rotation about Y
  13.     [2, 1, 0, -1,  1,  1]] # -90° rotation about Y
  14.  
  15.   all_rotations = []
  16.   # now that we've established the X axis, spin about the X axis to explore the
  17.   # mappings onto the Y and Z axes.
  18.   for r in base_rotations:
  19.     all_rotations += [[r[0], r[1], r[2], r[3],  r[4],  r[5]]]   # no rotation
  20.     all_rotations += [[r[0], r[2], r[1], r[3],  r[4], -r[5]]]  # +90° rotation about X
  21.     all_rotations += [[r[0], r[1], r[2], r[3], -r[4], -r[5]]] # 180° rotation about X
  22.     all_rotations += [[r[0], r[2], r[1], r[3], -r[4],  r[5]]]  # -90° rotation about X
  23.  
  24.   return all_rotations
  25.  
  26. rotation_table = build_rotations()
  27.  
  28. face_size = 8
  29. offset_join_size = 6
  30.  
  31. def canonicalize_placement(placement):
  32.   minima = [min([p[i] for p in placement]) for i in range(3)]
  33.   maxima = [max([p[i] for p in placement]) for i in range(3)]
  34.   size = [maxima[i] - minima[i] for i in range(3)]
  35.   center = [(maxima[i] + minima[i])//2 for i in range(3)]
  36.  
  37.   placement = [[p[i] - center[i] for i in range(3)] for p in placement]
  38.  
  39.   best_str = None
  40.   best = None
  41.   best_count = 1
  42.  
  43.   for rotation in rotation_table:
  44.     map = rotation[0:3]
  45.     scale = rotation[3:6]
  46.  
  47.     rotated = sorted([tuple([p[map[i]] * scale[i] for i in range(3)]) for p in placement])
  48.  
  49.     rotated_str = str(rotated)
  50.  
  51.     if best is None or rotated_str < best_str:
  52.       best = rotated
  53.       best_str = rotated_str
  54.       best_count = 1
  55.     elif rotated_str == best_str:
  56.       best_count += 1
  57.  
  58.   return (best, best_count)
  59.  
  60. def collides(placement, new_location):
  61.   for p in placement:
  62.     dist = [abs(p[i] - new_location[i]) for i in range(3)]
  63.     if max(dist) < face_size:
  64.       return True
  65.   return False
  66.  
  67. def neighbor_locations(base_location):
  68.   for face_axis in range(3):
  69.     axis2 = (face_axis+1)%3
  70.     axis3 = (face_axis+2)%3
  71.     for face_axis_dir in [-1,1]:
  72.       delta = [0,0,0]
  73.       delta[face_axis] = face_axis_dir * face_size
  74.       yield tuple([base_location[i] + delta[i] for i in range(3)])
  75.       delta[axis2] = +offset_join_size
  76.       yield tuple([base_location[i] + delta[i] for i in range(3)])
  77.       delta[axis2] = -offset_join_size
  78.       yield tuple([base_location[i] + delta[i] for i in range(3)])
  79.       delta[axis2] = 0
  80.       delta[axis3] = +offset_join_size
  81.       yield tuple([base_location[i] + delta[i] for i in range(3)])
  82.       delta[axis3] = -offset_join_size
  83.       yield tuple([base_location[i] + delta[i] for i in range(3)])
  84.  
  85. def count_placements(count):
  86.   prev_placements = {}
  87.   for n in range(1,count+1):
  88.     placements = {}
  89.     if n == 1:
  90.       (placement, count) = canonicalize_placement([(0,0,0)])
  91.       placements[str(placement)] = (placement, count)
  92.     else:
  93.       for base,unused in prev_placements.values():
  94.         for neighbor_base in base:
  95.           for new_loc in neighbor_locations(neighbor_base):
  96.             if not collides(base, new_loc):
  97.               (placement, count) = canonicalize_placement(base + [new_loc])
  98.               placement_str = str(placement)
  99.               if not placement_str in placements:
  100.                 placements[placement_str] = (placement, count)
  101.               #  print '%s: %d'%(placement_str, count)
  102.       print '%d: %s'%(n, len(placements))
  103.     prev_placements = placements
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement