import numpy as np
import matplotlib.pyplot as plt

def simpson_38_plot(f, a, b, n):
    """
    Κανόνας Simpson 3/8 για αριθμητική ολοκλήρωση με γραφική απεικόνιση
    
    f : συνάρτηση προς ολοκλήρωση
    a : κάτω όριο
    b : πάνω όριο
    n : αριθμός υποδιαστημάτων (ΠΡΕΠΕΙ ΝΑ ΕΙΝΑΙ ΠΟΛΑΠΛΑΣΙΟ ΤΟΥ 3)
    """
    if n % 3 != 0:
        raise ValueError("n πρέπει να είναι πολλαπλάσιο του 3")

    # Βήμα
    h = (b - a) / n

    # Σημεία x
    x = np.array([a + i * h for i in range(n + 1)])
    fx = f(x)

    # Αρχικοποίηση συνόλου
    total = fx[0] + fx[-1]

    # Εκτύπωση πίνακα
    print(f"h = {h}\n")
    print("i\t x_i\t f(x_i)\t συντελεστής\t όρος")
    print("-" * 50)

    # Εσωτερικά σημεία
    for i in range(1, n):
        if i % 3 == 0:
            coeff = 2
        else:
            coeff = 3
        term = coeff * fx[i]
        total += term
        print(f"{i}\t {x[i]:.4f}\t {fx[i]:.4f}\t {coeff}\t\t {term:.4f}")

    # Πρώτο και τελευταίο σημείο
    print(f"0\t {x[0]:.4f}\t {fx[0]:.4f}\t 1\t\t {fx[0]:.4f}")
    print(f"{n}\t {x[-1]:.4f}\t {fx[-1]:.4f}\t 1\t\t {fx[-1]:.4f}")

    # Τελικό αποτέλεσμα
    result = (3 * h / 8) * total
    print("\nΠροσεγγιστικό ολοκλήρωμα:", result)

    # Γραφική απεικόνιση
    x_fine = np.linspace(a, b, 200)
    y_fine = f(x_fine)

    plt.figure(figsize=(8,5))
    plt.plot(x_fine, y_fine, label='f(x)', color='blue')
    plt.plot(x, fx, 'ro', label='Σημεία Simpson 3/8')  # σημεία
    plt.title('Ολοκλήρωση με Simpson 3/8')
    plt.xlabel('x')
    plt.ylabel('f(x)')
    plt.legend()
    plt.grid(True)
    plt.show()

    return result

# Παράδειγμα χρήσης
def f(x):
    return x**2

simpson_38_plot(f, 0, 3, 3)
