A drone's propellers shake its frame at a frequency f (in hertz), and a cheap vibration logger samples the frame fs times per second. If f is below the Nyquist frequency fs / 2, the logger sees it as it is. Above that, the samples are exactly the samples of a slower wave (aliasing), and the spectrum shows a peak at that slower apparent frequency instead.
The apparent frequency is found by folding:
- Adding or removing whole multiples of
fschanges nothing at the sampling moments (each sample moves on by whole cycles), so first taker = f % fs, between0andfs. - A wave at
fs - rgives the same samples as one atr(the same wave run backwards in phase), so ifris abovefs / 2, the apparent frequency isfs - r. Otherwise it isr.
Write apparent_frequency(f, fs) that returns the frequency in hertz, between 0 and fs / 2, at which the logger's spectrum shows the tone. Press Run with plot([apparent_frequency(f, 100) for f in range(400)]) to see the zigzag that gives folding its name.
Examples
Input: f = 30, fs = 100
Output: 30
Explanation: below the Nyquist frequency of 50 Hz, nothing changes.
Input: f = 70, fs = 100
Output: 30
Explanation: 70 Hz is 20 Hz above 50 Hz and folds to 20 Hz below it.
Input: f = 260, fs = 100
Output: 40
Explanation: 260 % 100 = 60, which is above 50, so 100 - 60 = 40.
Constraints
0 <= f <= 10**6,1 <= fs <= 10**5; either may be a float- answers are compared with a tolerance of
1e-6, so30and30.0are both fine
Goals
- Predict the frequency a too-slow sampler reports for a fast tone
- Fold a frequency into the range from 0 to fs / 2
- See why the folded frequency cannot be told apart from the true one