-
Notifications
You must be signed in to change notification settings - Fork 0
/
find_ip_address_primes.py
147 lines (132 loc) · 5.72 KB
/
find_ip_address_primes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# find_ip_address_primes.py
# Originally written by Jonathan Ellenberger (http://respondcreate.com/)
import argparse, itertools
def is_prime(num):
"""
Returns 'True' if passed integer `num` is prime, 'False' if it isn't.
Found here: http://stackoverflow.com/questions/4114167/checking-if-a-number-is-a-prime-number-in-python/4117879#4117879
"""
return all(num % x for x in xrange(2, num))
def construct_ip_address_range(start='10.0.0.0', end='10.255.255.255'):
"""
Returns a list of IP (as strings).
Takes two strings (`start` and `end`) that are formatted like an IP address
(i.e. 'int.int.int.int') that represent a range of IP addresses
"""
ip_start_split = start.split('.')
ip_end_split = end.split('.')
# Ensure IP addresses pair together (i.e. they have the same number of 'segments' once split)
if len(ip_start_split) != len(ip_end_split):
raise Exception('The IP addresses passed to `start` (%s) and end (%s) represent an invalid IP range.' % (start, end))
else:
# Now, ensure IP address segments are ready for processing
# i.e. the string passed to `start` is lower in the IP range
# than the string passed to `end`
for counter, ip_segment in enumerate(ip_start_split):
if int(ip_segment) > int(ip_end_split[counter]):
raise Exception('A segment (%s) passed to `start` (%s) is higher than its corresponding segment (%s) passed to `end` (%s)' % (ip_segment, start, ip_end_split[counter], end))
return [
# Here's where the magic happens.
# `segments` is a tuple of ip address segments as created by itertools.product()
'.'.join([str(segment) for segment in segments])
# itertools.product() produces a cartesian product of iterables passed to it
# More info here: http://docs.python.org/2/library/itertools.html#itertools.product
for segments in itertools.product(*[
# Here's the list of iterables we're passing to itertools.product()
# It is constructed by creating a list (via `range()`) of all numbers
# between the corresponding segments in `start` and `end`
range(int(ip_segment), int(ip_end_split[counter])+1)
for counter, ip_segment in enumerate(ip_start_split)
])
]
def find_primes_in_ip_range(list_of_ip_strings, start, end):
"""
Returns a list of prime IP addresses from a list of IP addresses (`list_of_ip_strings`).
`start` and `end` provide slicing capability since prime calculation is processor intensive
"""
try:
x = list_of_ip_strings[end]
except (IndexError, TypeError):
end = len(list_of_ip_strings)-1
index_of_primes = [
# This list will be comprised of indexes for where a prime IP appears in
# in the list passed to `list_of_ip_strings`
counter
# Iterate over the counter (provided by enumerate)
# `start` and `end` allow slicing the list since prime calculation
# for a large set of numbers can take quite a long time (or a lot of horsepower) to process
for counter, ip_as_string in enumerate(list_of_ip_strings[start:end])
if is_prime(int(ip_as_string.replace('.', '')))
]
return [
string
for index, string in enumerate(list_of_ip_strings)
if index in index_of_primes
]
############ Command Line Scripting Support ############
# Define the arguments that can be passed to this script from the command line
parser = argparse.ArgumentParser(description='Find primes in a range of IP addresses.')
parser.add_argument(
'ip_range_start',
type=str,
help='The start of the IP range'
)
parser.add_argument(
'ip_range_end',
type=str,
help='The end of the IP range'
)
parser.add_argument(
'-s',
'--slice-start',
type=int,
default=0,
help='The point in the IP range list where prime processing should start.'
)
parser.add_argument(
'-e',
'--slice-end',
type=int,
default=None,
help='The point in the IP range list where prime processing should end.'
)
# Process any arguments passed by the user from the command line
args = parser.parse_args()
# Figure out what range of IP addresses needs to be processed
ip_range = construct_ip_address_range(args.ip_range_start, args.ip_range_end)
# Ensure the values passed to `slice_start` and `slice_end` are valid
# indexes in the `ip_range` list.
try:
slice_start = ip_range[args.slice_start]
except (IndexError, TypeError):
slice_start = 0
else:
slice_start = args.slice_start
try:
slice_end = ip_range[args.slice_end]
except (IndexError, TypeError):
slice_end = -1
else:
slice_end = args.slice_end
# Construct the output title
output_title = "Prime IP Addresses Between %s and %s" % (ip_range[slice_start], ip_range[slice_end])
# Build a horizontal rule that's the same length as the output title
horizontal_rule = "="*len(output_title)
# Print out the title and rule
print horizontal_rule
print output_title
# Ascertain whether or not the slice range of IP addresses is different than the IP
# addresses originally passed to `args.ip_range_start` and `args.ip_range_end`
if (ip_range[slice_start] != args.ip_range_start) or (ip_range[slice_end] != args.ip_range_end):
# If they are, print an appropriate 'sub title' since the output range is different
# Than the values passed to `args.ip_range_start` and `args.ip_range_end`
print '-'*len(output_title)
print "(A Slice From IP Range: %s - %s)" % (args.ip_range_start, args.ip_range_end)
print horizontal_rule
# Finally, print out the range of prime IPs
for ip in find_primes_in_ip_range(
ip_range,
args.slice_start,
args.slice_end
):
print ip