#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define N 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2
int state[N];
sem_t mutex;
sem_t S[N];
void test(int i)
{
    if (state[i] == HUNGRY &&
        state[(i + 4) % N] != EATING &&
        state[(i + 1) % N] != EATING)
    {
        state[i] = EATING;
        printf("Philosopher %d takes forks and starts eating\n", i);
        sem_post(&S[i]);
    }
}
void take_forks(int i)
{
sem_wait(&mutex);
 state[i] = HUNGRY;
    printf("Philosopher %d is HUNGRY\n", i);
 test(i);
 sem_post(&mutex);
    sem_wait(&S[i]);
}
void put_forks(int i)
{
    sem_wait(&mutex);
 state[i] = THINKING;
    printf("Philosopher %d puts down forks and starts THINKING\n", i);
 test((i + 4) % N);
    test((i + 1) % N);
sem_post(&mutex);
}
void *philosopher(void *num)
{
    int i = *(int *)num;
 for (int j = 0; j < 2; j++)
    {
        printf("Philosopher %d is THINKING\n", i);
        sleep(1);
 take_forks(i);
  sleep(1);
printf("Philosopher %d finishes eating\n", i);
  put_forks(i);
    }
   return NULL;
}
int main()
{
    pthread_t thread[N];
    int id[N];
sem_init(&mutex, 0, 1);
for (int i = 0; i < N; i++)
    {
        state[i] = THINKING;
        sem_init(&S[i], 0, 0);
    }
  for (int i = 0; i < N; i++)
    {
        id[i] = i;
        pthread_create(&thread[i], NULL, philosopher, &id[i]);
    }
  for (int i = 0; i < N; i++)
    {
        pthread_join(thread[i], NULL);
    }
 sem_destroy(&mutex);
 for (int i = 0; i < N; i++)
        sem_destroy(&S[i]);
 return 0;
}
