Setup¶

In [1]:
from itertools import permutations as nPp
import math
from math import pi as pi
from math import atan as invT
from math import sqrt as SR
import matplotlib
import matplotlib.pyplot as plt
import moviepy.video.io.ImageSequenceClip
import os
import pandas as pd

Constants & Functions¶

In [2]:
def createDF(m) :
    #(x,y), distance, and angle with x-axis
    data = pd.DataFrame(columns=['X', 'Y', 'D', 'A'])
    for x in range(1, m+1) :
        for y in range(1, m+1) :
            #Angle with x-axis.
            a = 180*invT(y/x)/pi
            #If the angle does not exist, add it to the df.
            if not data['A'].isin([a]).any() :
                data.loc[len(data)] = [x, y, SR(x**2 + y**2), a]

    #See only up to m units.            
    data = data[(data['D'] <= m)].sort_values(by = 'A')
    #Get the difference.
    data['dA'] = data['A'].diff()
    data.sort_values(by = 'A', inplace = True)
    data.reset_index(inplace = True, drop = True)
    return(data)



#Clear axes.
def clearAx(ax):
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["bottom"].set_visible(False)
    ax.spines["left"].set_visible(False)
    ax.set_xticks([])
    ax.set_yticks([])
    return(ax)




def plotForest(ax, m) :

    df = createDF(m)
    for i in range(len(df)) :
        ax.plot([0, df.at[i, 'X']], [0, df.at[i, 'Y']], lw = 0.5, c = 'r')  
    
    X = []
    Y = []
    for x in range(0, m+1) :
        for y in range(0, m+1) :
            if SR(x**2 + y**2) <= m :
                X.append(x)
                Y.append(y)
    ax.scatter(X, Y, lw = 2, c = 'k', zorder = 2)

Fiddler¶

In [3]:
def animateForest(m) :
    
    fig = plt.figure(figsize = (8, 8))  
    ax = fig.add_subplot(xlim = (-0.1, m+0.1),
                         ylim = (-0.1, m+0.1))
    fig.subplots_adjust(left = 0.02, bottom = 0.02, right = 0.98, top = 0.98)
    
    #Remove axes and ticks.
    ax = clearAx(ax)
    
    plotForest(ax, m)
In [4]:
data = createDF(7)
data[data['A'] <= 45].sort_values('dA').tail(4)
Out[4]:
X Y D A dA
3 3.0 1.0 3.162278 18.434949 4.398705
5 2.0 1.0 2.236068 26.565051 4.763642
10 1.0 1.0 1.414214 45.000000 6.340192
0 6.0 1.0 6.082763 9.462322 NaN

3rd Pair¶

In [5]:
data = createDF(8)
data[data['A'] <= 45].sort_values('dA').tail(6)
Out[5]:
X Y D A dA
11 4.0 3.0 5.000000 36.869898 3.179830
6 5.0 2.0 5.385165 21.801409 3.366461
8 2.0 1.0 2.236068 26.565051 3.366461
9 5.0 3.0 5.830952 30.963757 4.398705
14 1.0 1.0 1.414214 45.000000 5.194429
0 7.0 1.0 7.071068 8.130102 NaN
In [6]:
data = createDF(20)
data[data['A'] <= 45].sort_values('dA').tail(6)
Out[6]:
X Y D A dA
71 3.0 2.0 3.605551 33.690068 0.954841
40 17.0 6.0 18.027756 19.440035 1.005086
57 17.0 9.0 19.235384 27.897271 1.332220
56 2.0 1.0 2.236068 26.565051 1.363928
95 1.0 1.0 1.414214 45.000000 2.121096
0 19.0 1.0 19.026298 3.012788 NaN

4th Pair¶

In [7]:
data = createDF(21)
data[data['A'] <= 45].sort_values('dA').tail(8)
Out[7]:
X Y D A dA
30 4.0 1.0 4.123106 14.036243 0.795724
77 16.0 11.0 19.416488 34.508523 0.818455
41 3.0 1.0 3.162278 18.434949 0.909380
42 17.0 6.0 18.027756 19.440035 1.005086
61 17.0 9.0 19.235384 27.897271 1.332220
60 2.0 1.0 2.236068 26.565051 1.363928
103 1.0 1.0 1.414214 45.000000 1.974934
0 20.0 1.0 20.024984 2.862405 NaN

5th & 6th Pair¶

In [8]:
data = createDF(22)
data[data['A'] <= 45].sort_values('dA').tail(12)
Out[8]:
X Y D A dA
55 17.0 7.0 18.384776 22.380135 0.578726
94 4.0 3.0 5.000000 36.869898 0.616060
34 4.0 1.0 4.123106 14.036243 0.643746
35 19.0 5.0 19.646883 14.743563 0.707319
86 3.0 2.0 3.605551 33.690068 0.784825
87 16.0 11.0 19.416488 34.508523 0.818455
46 20.0 7.0 21.189620 19.290046 0.855097
45 3.0 1.0 3.162278 18.434949 0.909380
68 19.0 10.0 21.470911 27.758541 1.193489
67 2.0 1.0 2.236068 26.565051 1.218875
115 1.0 1.0 1.414214 45.000000 1.847610
0 21.0 1.0 21.023796 2.726311 NaN
In [9]:
data = createDF(194)
data[data['A'] <= 45].sort_values('dA').tail(12)
Out[9]:
X Y D A dA
2254 5.0 1.0 5.099020 11.309932 0.059251
7361 153.0 115.0 191.400104 36.929768 0.059870
2798 187.0 47.0 192.815974 14.108314 0.072070
2797 4.0 1.0 4.123106 14.036243 0.072895
6723 3.0 2.0 3.605551 33.690068 0.082203
6724 160.0 107.0 192.481168 33.772626 0.082559
3677 3.0 1.0 3.162278 18.434949 0.093468
3678 182.0 61.0 191.950514 18.529340 0.094392
5303 173.0 87.0 193.644003 26.697374 0.132323
5302 2.0 1.0 2.236068 26.565051 0.132629
8983 1.0 1.0 1.414214 45.000000 0.209874
0 193.0 1.0 193.002591 0.296867 NaN

7th & 8th Pair¶

In [10]:
data = createDF(195)
data[data['A'] <= 45].sort_values('dA').tail(14)
Out[10]:
X Y D A dA
2279 5.0 1.0 5.099020 11.309932 0.057700
2280 189.0 38.0 192.782261 11.368219 0.058287
7434 4.0 3.0 5.000000 36.869898 0.059190
7435 153.0 115.0 191.400104 36.929768 0.059870
2828 4.0 1.0 4.123106 14.036243 0.071352
2829 187.0 47.0 192.815974 14.108314 0.072070
6790 3.0 2.0 3.605551 33.690068 0.082203
6791 160.0 107.0 192.481168 33.772626 0.082559
3715 3.0 1.0 3.162278 18.434949 0.093468
3716 182.0 61.0 191.950514 18.529340 0.094392
5356 173.0 87.0 193.644003 26.697374 0.132323
5355 2.0 1.0 2.236068 26.565051 0.132629
9072 1.0 1.0 1.414214 45.000000 0.208347
0 194.0 1.0 194.002577 0.295336 NaN
Rohan Lewis¶

2025.04.28¶