#include <stdio.h>
#include <stdlib.h>

typedef struct tempNo {

    int valor;
    int coluna;
    struct tempNo* prox;

} NO;

typedef NO* PONT;

typedef struct {

    PONT* A;
    int linhas;
    int colunas;

} MATRIZ;

void inicializaMatriz(MATRIZ* m, int linnha, int coluna) {

    int i;

    m->linhas = linnha;
    m->colunas = coluna;
    m->A = (PONT*) malloc(linnha*sizeof(PONT));

    for (i = 0; i < linnha ; i++){
        m->A[i] = NULL;
    }
}



int atribuirValor(MATRIZ* m, int lin, int col, int valor) {

    if (lin < 0 || lin >= m->linhas || col < 0 || col >= m->colunas ) return  1;

    PONT ant = NULL;
    PONT atual = m->A[lin];

    while(atual !=  NULL && atual->coluna < col ){
        ant = atual;
        atual = atual->prox;
    }

    if (atual != NULL && atual->coluna == col) {
        if (valor == 0) {
            if (ant == NULL) m->A[lin] = atual->prox;
            else ant->prox = atual->prox;
            free(atual);
        }
        else  atual->valor = valor;

    } else if (valor != 0){
        PONT novo = (PONT) malloc (sizeof(NO));
        novo->coluna = col;
        novo->valor = valor;
        novo->prox = atual;
        if (ant == NULL) m->A[lin] = novo;
        else ant->prox = novo;
    }
    return 0;

}


int acessarValor(MATRIZ* m, int lin , int col) {

    if (lin < 0 || lin >= m->linhas || col < 0 || col >= m->colunas ) return 0;

    PONT atual = m->A[lin];
    while (atual != NULL && atual->coluna < col )
        atual = atual->prox;
    if (atual != NULL)
        return atual->valor;
    return 0;

}

void anexarColuna(MATRIZ* m){

    int linha;
    for (linha = 0; linha < m->linhas ; linha++){

        PONT novo = malloc (sizeof(NO));
        novo->valor = 0;
        novo->prox = NULL;

        if (m->A[linha] == NULL){
            novo->coluna = 0;
            m->A[linha] = novo;
        }
        else {
            PONT atual = m->A[linha];

            while(atual->prox != NULL){
                atual=atual->prox;
            }

            novo->coluna = atual->coluna + 1;
            atual->prox = novo;
        }
    }

    m->colunas++;
}


void anexarLinha(MATRIZ* m){
    m->A = realloc(m->A, (++m->linhas*sizeof(PONT)));
}



int main()
{


    MATRIZ m;

    inicializaMatriz(&m, 3, 3);
    atribuirValor(&m, 1, 1, 10);

    printf("\nEm %d %d tem o valor %d (linhas:%d , colunas:%d)", 1, 1, acessarValor(&m,1,1), m.linhas, m.colunas);

    anexarLinha(&m);

    atribuirValor(&m, 3, 1, 15);
    printf("\nEm %d %d tem o valor %d (linhas:%d , colunas:%d)", 3, 1, acessarValor(&m,3,1),m.linhas, m.colunas);

    anexarColuna(&m);
    anexarColuna(&m);
    anexarColuna(&m);

    atribuirValor(&m, 1, 5, 20);
    printf("\nEm %d %d tem o valor %d (linhas:%d , colunas:%d)", 1, 5, acessarValor(&m,1,5),m.linhas, m.colunas);


    return 0;
}

