import numpy as np
import matplotlib.pyplot as plt
import random

plt.style.use('dark_background')

# --- Random slopes ---
m1 = random.randint(1, 5)      # positive slope
m2 = random.randint(-5, -1)    # negative slope

print(f"Line A (through 0,0) slope: {m1}")
print(f"Line B (through 1,0) slope: {m2}")

# --- Define the two lines ---
# Line A: y = m1 * x
# Line B: passes through (1,0)
#         slope m2 => y - 0 = m2 (x - 1) => y = m2(x - 1)

def lineA(x): return m1 * x
def lineB(x): return m2 * (x - 1)

# --- Find intersections with the x-axis (y = 0) ---
# Line A hits at x = 0
xA = 0

# Line B hits at x = 1
xB = 1

# --- Find intersection between lines A and B ---
# Solve: m1*x = m2(x - 1)
# m1*x = m2*x - m2  => (m1 - m2)x = -m2
# x = -m2 / (m1 - m2)
xI = -m2 / (m1 - m2)
yI = lineA(xI)

# --- Plotting range: capture whole triangle ---
xmin = min(xA, xB, xI) - 1
xmax = max(xA, xB, xI) + 1
x = np.linspace(xmin, xmax, 400)

# --- Plot ---
plt.figure(figsize=(8,6))
plt.plot(x, lineA(x), label=f"Line A: y = {m1}x")
plt.plot(x, lineB(x), label=f"Line B: y = {m2}(x - 1)")

# --- Highlight triangle ---
plt.fill([xA, xB, xI], [0, 0, yI], alpha=0.2, color='#FDBA74', label="Triangle")

# Axes and formatting
plt.axhline(0, color='white', linewidth=0.8)
plt.axvline(0, color='white', linewidth=0.8)

plt.scatter([xA, xB, xI], [0, 0, yI], color='#FB7185')

plt.xlabel("x")
plt.ylabel("y")
plt.title("Two Random Lines Forming a Triangle with the X-Axis")
plt.legend()
plt.grid(True)
plt.show()
Line A (through 0,0) slope: 1
Line B (through 1,0) slope: -4

import numpy as np
import matplotlib.pyplot as plt
import random

plt.style.use('dark_background')

# --- Random slopes ---
m1 = random.randint(1, 15)      # positive slope
m2 = random.randint(1, 15)    # negative slope

print(f"Line A (through 0,0) slope: {m1}")
print(f"Line B (through 1,0) slope: {m2}")

# --- Define the two lines ---
def lineA(x):
    return m1 * x              # passes through (0,0)

def lineB(x):
    return m2 * (x - 1)        # passes through (1,0)

# --- Intersection with x-axis ---
xA = 0
xB = 1

# --- Intersection between A and B ---
xI = -m2 / (m1 - m2)
yI = lineA(xI)

# --- LERP curve on x ∈ [0,1] ---
t = np.linspace(0, 1, 400)

# linear interpolation between lineA(t) and lineB(t)
curve = (1 - t) * lineA(t) + t * lineB(t)

# --- Plotting window ---
xmin = min(xA, xB, xI) - 1
xmax = max(xA, xB, xI) + 1
x_plot = np.linspace(xmin, xmax, 400)

plt.figure(figsize=(9,7))

# Lines
plt.plot(x_plot, lineA(x_plot), label=f"Line A: y = {m1}x")
plt.plot(x_plot, lineB(x_plot), label=f"Line B: y = {m2}(x - 1)")

# LERP curve
plt.plot(t, curve, color='#FF6ECB', linewidth=3,
         label="LERP between lineA and lineB on [0,1]")

# Triangle
plt.fill([xA, xB, xI], [0, 0, yI], alpha=0.2, color='#FDBA74', label="Triangle")
plt.scatter([xA, xB, xI], [0, 0, yI], color='#FB7185')

plt.axhline(0, color='white', linewidth=0.8)
plt.axvline(0, color='white', linewidth=0.8)

plt.xlabel("x")
plt.ylabel("y")
plt.title("Two Random Lines + LERP Between Lines on [0,1]")
plt.legend()
plt.grid(True)
plt.show()
Line A (through 0,0) slope: 15
Line B (through 1,0) slope: 4

import numpy as np
import matplotlib.pyplot as plt
import random

plt.style.use('dark_background')

# ---------------------------------------------------
# 1. Choose 5 random gradients for integer points 0..4
# ---------------------------------------------------
gradients = [random.uniform(-1, 1) for _ in range(5)]
print("Gradients:", gradients)

# Gradient function g_i influences are defined as:
# influence = gradient * (x - i)


# ---------------------------------------------------
# 2. Define Perlin-style gradient noise WITHOUT smoothing
# ---------------------------------------------------
def perlin_no_fade(x):
    x0 = int(np.floor(x))
    t = x - x0

    if x0 < 0: 
        x0 = 0
    if x0 > 3:  # only intervals 0-1,1-2,2-3,3-4
        x0 = 3

    g0 = gradients[x0]
    g1 = gradients[x0 + 1]

    # distances
    d0 = t
    d1 = t - 1

    # influences
    v0 = g0 * d0
    v1 = g1 * d1

    # no smoothing: raw linear interpolation
    return v0 + (v1 - v0) * t


# ---------------------------------------------------
# 3. Plot gradient lines and the resulting noise
# ---------------------------------------------------
x_plot = np.linspace(0, 4, 800)
noise = np.array([perlin_no_fade(x) for x in x_plot])

fig, ax = plt.subplots(figsize=(10,6))

# Plot noise
ax.plot(x_plot, noise, label="Perlin Noise (No Fade)", color="#FF6ECB")

# Plot each gradient line in its interval
for i in range(4):
    xs = np.linspace(i, i+1, 200)
    g = gradients[i]
    ys = g * (xs - i)   # gradient line influence
    ax.plot(xs, ys, '--', label=f"Gradient line at {i}: g={g:.2f}")

# Visual reference lines at integer grid points
for i in range(5):
    ax.axvline(i, color="white", linewidth=0.5)

ax.set_xlabel("x")
ax.set_ylabel("noise / gradient influence")
ax.set_title("1D Perlin Gradient Noise (No Fade) + Gradient Lines")
ax.legend()
ax.grid(True)

plt.show()
Gradients: [0.028909420197587465, -0.8163175351804153, -0.3985089577489964, 0.6408093955119749, 0.5084240981111465]

import numpy as np
import matplotlib.pyplot as plt
import random

plt.style.use('dark_background')

# ---------------------------------------------------
# 1. Choose 5 random gradients for integer points 0..4
# ---------------------------------------------------
gradients = [random.uniform(-1, 1) for _ in range(5)]
print("Gradients:", gradients)

# Gradient influence function:
# influence_i(x) = gradients[i] * (x - i)


# ---------------------------------------------------
# 2. Fade (smoothstep) function for proper Perlin noise
# ---------------------------------------------------
def fade(t):
    return 6*t**5 - 15*t**4 + 10*t**3


# ---------------------------------------------------
# 3. Perlin noise WITHOUT smoothing
# ---------------------------------------------------
def perlin_no_fade(x):
    x0 = int(np.floor(x))

    # clamp because we only have gradients[0..4]
    if x0 < 0:
        x0 = 0
    if x0 > 3:
        x0 = 3

    t = x - x0
    g0 = gradients[x0]
    g1 = gradients[x0 + 1]

    d0 = t
    d1 = t - 1

    v0 = g0 * d0
    v1 = g1 * d1

    return v0 + (v1 - v0) * t


# ---------------------------------------------------
# 4. Proper Perlin noise WITH smoothing (fade function)
# ---------------------------------------------------
def perlin_fade(x):
    x0 = int(np.floor(x))

    if x0 < 0:
        x0 = 0
    if x0 > 3:
        x0 = 3

    t = x - x0
    g0 = gradients[x0]
    g1 = gradients[x0 + 1]

    d0 = t
    d1 = t - 1

    v0 = g0 * d0
    v1 = g1 * d1

    # apply fade(t) instead of raw t
    u = fade(t)
    return v0 + (v1 - v0) * u


# ---------------------------------------------------
# 5. Plot everything together
# ---------------------------------------------------
x_plot = np.linspace(0, 4, 800)
noise_no_fade = np.array([perlin_no_fade(x) for x in x_plot])
noise_fade    = np.array([perlin_fade(x) for x in x_plot])

fig, ax = plt.subplots(figsize=(10,6))

# Proper Perlin noise
ax.plot(x_plot, noise_fade, color="#60A5FA", linewidth=2.5,
        label="Proper Perlin Noise (with fade)")

# Noise without fade (linear interpolation)
ax.plot(x_plot, noise_no_fade, color="#FF6ECB", linestyle="--",
        label="Perlin Noise (no fade)")

# Gradient influence lines
for i in range(4):
    xs = np.linspace(i, i+1, 200)
    g = gradients[i]
    ys = g * (xs - i)
    ax.plot(xs, ys, linestyle=":", linewidth=1.5,
            label=f"Gradient at {i}: g={g:.2f}")

# Vertical grid boundaries
for i in range(5):
    ax.axvline(i, color="white", linewidth=0.4)

ax.set_xlabel("x")
ax.set_ylabel("value")
ax.set_title("1D Perlin Noise: Gradient Lines, No-Fade Noise, and Proper Noise")
ax.legend()
ax.grid(True)
plt.show()
Gradients: [-0.7022986475572608, 0.17335353469399672, 0.1075493026575225, -0.07356656019115815, 0.8524175376834833]