import numpy as np

def target_distribution(x):
    # define the target distribution to sample from
    return np.exp(-x**2) + np.exp(-(x-5)**2)

def importance_sampling(n_samples, proposal_distribution):
    samples = np.zeros(n_samples)
    weights = np.zeros(n_samples)
    for i in range(n_samples):
        # sample from the proposal distribution
        samples[i] = proposal_distribution(n_samples=1)
        # compute the importance weight for the sample
        weights[i] = target_distribution(samples[i]) / proposal_distribution(n_samples=1)
    # normalize the weights
    weights /= np.sum(weights)
    return samples, weights

# define the proposal distribution as a normal distribution
proposal_distribution = lambda n_samples: np.random.normal(2.5, 1, n_samples)

# generate samples using importance sampling
samples, weights = importance_sampling(n_samples=10000, proposal_distribution=proposal_distribution)

# estimate the mean of the target distribution
mean_estimate = np.sum(weights * samples)

print("Mean estimate:", mean_estimate)