Skip to content

Instantly share code, notes, and snippets.

@Linux-cpp-lisp
Last active May 29, 2019 20:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Linux-cpp-lisp/736591d4dd3b6b905b30cb7863191532 to your computer and use it in GitHub Desktop.
Save Linux-cpp-lisp/736591d4dd3b6b905b30cb7863191532 to your computer and use it in GitHub Desktop.
Flexible, configurable generation of natural numbers in a spiral

 Generate and print a spiral of natural numbers up to N with fully configurable shape and spacing.

Examples:

$ python3 spiral.py 50 square 2 
                                     
                                     
     32 31 30 29 28 27 26 25         
     33                   24         
     34     8  7  6  5    23         
     35     9        4    22         
     36    10     0  3    21         
     37    11     1  2    20         
     38    12             19         
     39    13 14 15 16 17 18         
     40                              
     41 42 43 44 45 46 47 48 49      
                                     
                                     
$ python3 spiral.py 200 square 5
                                                                                                                          
                                                                                                                          
       162 161 160 159 158 157 156 155 154 153 152 151 150 149 148 147 146 145 144 143 142 141 140 139 138 137 136        
       163                                                                                                     135        
       164                                                                                                     134        
       165                                                                                                     133        
       166                                                                                                     132        
       167                  68  67  66  65  64  63  62  61  60  59  58  57  56  55  54  53  52                 131        
       168                  69                                                              51                 130        
       169                  70                                                              50                 129        
       170                  71                                                              49                 128        
       171                  72                                                              48                 127        
       172                  73                  14  13  12  11  10   9   8                  47                 126        
       173                  74                  15                       7                  46                 125        
       174                  75                  16                       6                  45                 124        
       175                  76                  17                       5                  44                 123        
       176                  77                  18                       4                  43                 122        
       177                  78                  19                   0   3                  42                 121        
       178                  79                  20                   1   2                  41                 120        
       179                  80                  21                                          40                 119        
       180                  81                  22                                          39                 118        
       181                  82                  23                                          38                 117        
       182                  83                  24                                          37                 116        
       183                  84                  25  26  27  28  29  30  31  32  33  34  35  36                 115        
       184                  85                                                                                 114        
       185                  86                                                                                 113        
       186                  87                                                                                 112        
       187                  88                                                                                 111        
       188                  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110        
       189                                                                                                                
       190                                                                                                                
       191                                                                                                                
       192                                                                                                                
       193 194 195 196 197 198 199                                                                                        
                                                                                                                          
                                                                                                                          
$ python3 spiral.py 50 diamond 2
                                                                
                                                                
                          25                                    
                       26    24                                 
                    27          23                              
                 28                22                           
              29           5          21                        
           30           6     4          20                     
        31           7           3          19                  
     32           8           0     2          18               
        33           9           1          17          49      
           34          10                16          48         
              35          11          15          47            
                 36          12    14          46               
                    37          13          45                  
                       38                44                     
                          39          43                        
                             40    42                           
                                41                              
                                                                
                                                                
$ python3 spiral.py 50 wide_diamond 2
                                                                
                                                                
                          25                                    
                                                                
                       26    24                                 
                                                                
                    27          23                              
                                                                
                 28                22                           
                                                                
              29           5          21                        
                                                                
           30           6     4          20                     
                                                                
        31           7           3          19                  
                                                                
     32           8           0     2          18               
                                                                
        33           9           1          17          49      
                                                                
           34          10                16          48         
                                                                
              35          11          15          47            
                                                                
                 36          12    14          46               
                                                                
                    37          13          45                  
                                                                
                       38                44                     
                                                                
                          39          43                        
                                                                
                             40    42                           
                                                                
                                41                              
                                                                
                                                                
$ python3 spiral.py 50 wide_diamond 1
                                                 
                                                 
                       36                        
                                                 
                    37    35                     
                                                 
                 38    16    34                  
                                                 
              39    17    15    33               
                                                 
           40    18     4    14    32            
                                                 
        41    19     5     3    13    31         
                                                 
     42    20     6     0     2    12    30      
                                                 
        43    21     7     1    11    29         
                                                 
           44    22     8    10    28            
                                                 
              45    23     9    27               
                                                 
                 46    24    26                  
                                                 
                    47    25                     
                                                 
                       48                        
                                                 
                          49                     
                                                 
                                                 
import numpy as np
import sys
# - Input
shapes = {
'square' : [(1, 0), (0, 1), (-1, 0), (0, -1)], # A typical horezontal and vertical line spiral
'diamond' : [(1, 1), (-1, 1), (-1, -1), (1, -1)], # A "diamond" spiral consisting of diagonal lines
'wide_diamond' : [(2, 1), (-2, 1), (-2, -1), (2, -1)] # A stretched diamond spiral
}
if not len(sys.argv) == 4:
print("spiral.py [N] [shape] [spacing]")
print(" Valid shapes: %s" % str(list(shapes.keys())))
sys.exit(-1)
N = int(sys.argv[1])
shape = sys.argv[2]
spacing = int(sys.argv[3]) # Determines the "tightness" of the spiral. A value of 1 gives a dense spiral, 2 with some space between lines
# - Parameters
margin = 4
assert(margin % 2 == 0)
directions = shapes[shape]
# etc.
curr_dir = 0
curr_len = 1
assert(spacing >= 1)
# - Setup
positions = np.empty(shape = (N, 2), dtype = np.int)
curr_pos = np.array([0, 0])
i = -1
# - Create spiral
for n in range(N):
positions[n] = curr_pos
i += 1
if i == curr_len:
curr_dir = (curr_dir + 1) % len(directions)
i = 0
if curr_dir % 2 == 0:
curr_len += spacing
curr_pos = (curr_pos[0] + directions[curr_dir][0],
curr_pos[1] + directions[curr_dir][1])
# - Determine size of canvas
mins = np.min(positions, axis = 0)
size = np.ptp(positions, axis = 0) + 1 + margin
positions -= mins
positions += margin // 2
# - Create canvas
grid = np.empty(shape = tuple(size), dtype = np.int)
grid.fill(-1)
grid[positions[:, 0], positions[:, 1]] = np.arange(N)
ndigit = int(np.ceil(np.log10(N)))
# - Draw canvas
for row in grid:
print(" ".join(' '*ndigit if e == -1 else ('%' + str(ndigit) + 'i') % e for e in row))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment