/* CSE513: fixed textbook snapshot; no scheduling or real resource allocation. */
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define N 5
#define M 3
typedef struct { int available[M], allocation[N][M], maximum[N][M]; } State;
static const State initial = {{3,3,2},{{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}},
    {{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}}};
static int safe(const State *s, int sequence[N]) {
    int work[M],finish[N]={0},done=0;memcpy(work,s->available,sizeof work);
    while (done<N) {
        int progress=0;
        for (int i=0;i<N;++i) if (!finish[i]) {
            int fits=1;
            for (int j=0;j<M;++j)
                if (s->maximum[i][j]-s->allocation[i][j]>work[j]) fits=0;
            if (!fits) continue;
            for (int j=0;j<M;++j) work[j]+=s->allocation[i][j];
            finish[i]=1;sequence[done++]=i;progress=1;
        }
        if (!progress) return 0;
    }
    return 1;
}
/* Return 0=granted, 1=above maximum, 2=unavailable, 3=unsafe. */
static int request(State *s,int i,const int req[M]) {
    for (int j=0;j<M;++j)
        if (req[j]<0 || req[j]>s->maximum[i][j]-s->allocation[i][j]) return 1;
    for (int j=0;j<M;++j) if (req[j]>s->available[j]) return 2;
    State trial=*s;int seq[N];
    for (int j=0;j<M;++j) {trial.available[j]-=req[j];trial.allocation[i][j]+=req[j];}
    if (!safe(&trial,seq)) return 3;
    *s=trial;return 0;
}
static void show(const char *label,const State *s) {
    int seq[N];printf("%s: ",label);
    if (!safe(s,seq)) {puts("unsafe");return;}
    printf("safe sequence:");for (int i=0;i<N;++i) printf(" T%d",seq[i]);puts("");
}
int main(void) {
    State s=initial;show("initial",&s);
    const int a[M]={1,0,2},b[M]={3,3,0},c[M]={0,2,0},d[M]={0,3,0};
    assert(request(&s,1,a)==0);show("after T1 (1,0,2)",&s);State before=s;
    assert(request(&s,4,b)==2);assert(!memcmp(&s,&before,sizeof s));puts("T4 (3,3,0): unavailable; unchanged");
    assert(request(&s,0,c)==3);assert(!memcmp(&s,&before,sizeof s));puts("T0 (0,2,0): unsafe; unchanged");
    assert(request(&s,1,d)==1);assert(!memcmp(&s,&before,sizeof s));puts("T1 (0,3,0): above maximum; unchanged");
    for(int j=0;j<M;++j) {int sum=s.available[j];for(int i=0;i<N;++i)sum+=s.allocation[i][j];assert(sum==((int[]){10,5,7})[j]);}
    puts("all checks passed");return 0;
}
