-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathmain.py
More file actions
107 lines (83 loc) · 3.02 KB
/
main.py
File metadata and controls
107 lines (83 loc) · 3.02 KB
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
# FIXME codeval does not allow you to use numpy
import numpy
import sys
SEGMENTS = 10
SAMPLE_INTERVAL = 0.00005
MAX_NOISE_PERCENTAGE = 0.1
def zero(data):
"""
Given a signal, zero it out by finding a best fit curve and subtracting out the average value
of the signal.
"""
result = []
[m, b] = numpy.polyfit(list(range(0, len(data))), data, 1)
for i in range(0, len(data)):
result.append(data[i] - m * i + b)
a = sum(result)/len(result)
result = [a - r for r in result]
return result
def normalize(data, segments):
"""
Break a signal into segments, average out the segments, and normalize the amplitude of each
segment using that average.
"""
segment_length = len(data) / segments
for i in range(0, segments):
segment = data[i * segment_length : (i+1) * segment_length]
segment_abs_max = max([abs(s) for s in segment])
for j in range(0, segment_length):
data[i * segment_length + j] /= segment_abs_max
return data
def truncate_to_nearest_10(x):
return x - (x % 10)
def remove_adjacent_repeated(data):
result = [data[0]]
for i in range(1, len(data)):
if data[i] != data[i-1]:
result.append(data[i])
return result
def determine_frequency(data, max_noise_percentage, sample_interval):
"""
Count the number of times a signal crosses the zero level. Take into consideration noise with
some maximum amplitude as a percentage of the data amplitude.
Assume the given signal is zeroed and normalized.
"""
states = []
for d in data:
if d < max_noise_percentage:
states.append(-1)
elif d > max_noise_percentage:
states.append(1)
else:
states.append(0)
# Some sneaky logic to make sure that we exclude the little bits at the beginning and end of the
# signal, so our frequency is as accurate as possible.
start = 0
for i in range(0, len(states)-1):
if (states[i] == 0 or states[i] == -1) and states[i+1] == 1:
start = i
break
end = len(states)-1
for i in range(len(states)-1, 0, -1):
if (states[i-1] == 0 or states[i-1] == -1) and states[i] == 1:
# Important: trim the end.
end = i-1
break
length = end - start + 1
states = remove_adjacent_repeated([s for s in states[start:end+1] if s != 0])
state_changes = len(states)
total_seconds = length * sample_interval
return truncate_to_nearest_10(int(state_changes / total_seconds / 2.0))
def main():
test_cases = open(sys.argv[1], 'r')
for test in test_cases:
test = test.strip()
if len(test) == 0: continue
data = zero([float(x) for x in test.split(' ')])
data = normalize(data, SEGMENTS)
print(determine_frequency(data,
max_noise_percentage=MAX_NOISE_PERCENTAGE,
sample_interval=SAMPLE_INTERVAL))
test_cases.close()
if __name__ == '__main__':
main()