Sunday, December 4, 2011

101 - The Blocks Problem - in C

Problem 101 - The Blocks Problem, from the UVa Online Judge. Not the most elegant but it works...
#include <stdio.h>
#include <stdlib.h>

#define N 25

void printBlocks(int blocks[][N], int n);
void printPos(int pos[], int n);
void push(int blocks[][N], int a, int p);
void moveOnto(int blocks[][N], int pos[], int a, int b);
void moveOver(int blocks[][N], int pos[], int a, int b);
void pileOnto(int blocks[][N], int pos[], int a, int b);
void pileOver(int blocks[][N], int pos[], int a, int b);

int main ()
{
    int blocks[N][N];
    int pos[N];
    int n = 10;

    char com1[10];
    char com2[10];

    int a, b;

    int i, j, result;
    for (i=0; i<N; i++)
    {
        for (j=0; j<N; j++)
        {
            if (j==0)
                blocks[i][j] = i;
            else
                blocks[i][j] = -1;
        }
        
        pos[i] = i;
    }

    scanf("%d", &n);
    result = 1;
    while(result)
    {
        scanf("%s", com1);
        if(com1[0] == 'q')
            break;
        else {
            scanf("%d %s %d", &a, com2, &b);
            if (com1[0] == 'm' && com2[1] == 'n')
                /*printf("move %d onto %d\n", a, b);*/
                moveOnto(blocks, pos, a, b);
            else if (com1[0] == 'm' && com2[1] == 'v')
                /*printf("move %d over %d\n", a, b);*/
                moveOver(blocks, pos, a, b);
            else if (com1[0] == 'p' && com2[1] == 'n')
                /*printf("pile %d onto %d\n", a, b);*/
                pileOnto(blocks, pos, a, b);
            else if (com1[0] == 'p' && com2[1] == 'v')
                /*printf("pile %d over %d\n", a, b);*/
                pileOver(blocks, pos, a, b);
            else
                ;
        }
    }

    printBlocks(blocks, n);

    /*
    moveOnto(blocks, pos, 9, 1);
    printBlocks(blocks, n);
    moveOver(blocks, pos, 8, 1);
    printBlocks(blocks, n);
    moveOver(blocks, pos, 7, 1);
    printBlocks(blocks, n);
    moveOver(blocks, pos, 6, 1);
    printBlocks(blocks, n);
    pileOver(blocks, pos, 8, 6);
    printBlocks(blocks, n);
    pileOver(blocks, pos, 8, 5);
    printBlocks(blocks, n);
    moveOver(blocks, pos, 2, 1);
    printBlocks(blocks, n);
    moveOver(blocks, pos, 4, 9);
    printBlocks(blocks, n);
    */

    return 0;
}

void printBlocks(int blocks[][N], int n)
{
    int i, j;
    for (i=0; i<n; i++)
    {
        printf("%d:", i);
        for (j=0; j<n; j++)
        {
            if (blocks[i][j] < 0)
            {
                printf("\n");
                break;
            }
            else
                printf(" %d", blocks[i][j]);
        }
    }
}

void printPos(int pos[], int n)
{
    int i;
    printf("Positions: ");
    for (i=0; i<n; i++)
        printf("%d ", pos[i]);
    printf("\n");
}

void push(int blocks[][N], int a, int p)
{
    int i=0;
    while(blocks[p][i] >= 0)
        i++;
    blocks[p][i] = a;
}

void moveOnto(int blocks[][N], int pos[], int a, int b)
{
    /*printf("Move block %d onto block %d\n", a, b);*/
    if (a == b || pos[a] == pos[b])
        ;
    else {
        /*first move blocks from on top of block "a"*/
        int i=0, bl;
        while ( blocks[pos[a]][i] != a)
            i++;
        blocks[pos[a]][i] = -1;
        i++;
        bl = blocks[pos[a]][i];
        while ( bl >= 0)
        {
            /*move these blocks back to original positions*/
            push(blocks, bl, bl);
            blocks[pos[a]][i] = -1;
            /*update positions*/
            pos[bl] = bl;
            i++;
            bl = blocks[pos[a]][i];
        }
        /*now move the blocks on top of block "b"*/
        i=0;
        while ( blocks[pos[b]][i] != b)
            i++;
        /*leave b where it is*/
        i++;
        bl = blocks[pos[b]][i];
        while ( bl >= 0)
        {
            /*move to original position*/
            push(blocks, bl, bl);
            /*remove from current*/
            blocks[pos[b]][i] = -1;
            pos[bl] = bl;
            i++;
            bl = blocks[pos[b]][i];
        }
        /*now push a on to b*/
        push(blocks, a, pos[b]);
        pos[a] = pos[b];
    }
}

void moveOver(int blocks[][N], int pos[], int a, int b)
{
    /*printf("Move block %d over block %d\n", a, b);*/
    /*first move blocks from on top of block "a"*/
    if (a == b || pos[a] == pos[b])
        ;
    else {
        int i=0, bl;
        while ( blocks[pos[a]][i] != a)
            i++;
        blocks[pos[a]][i] = -1;
        i++;
        bl = blocks[pos[a]][i];
        while ( bl >= 0)
        {
            /*move these blocks back to original positions*/
            push(blocks, bl, bl);
            blocks[pos[a]][i] = -1;
            /*update positions*/
            pos[bl] = bl;
            i++;
            bl = blocks[pos[a]][i];
        }
        /*now push a on to b*/
        push(blocks, a, pos[b]);
        pos[a] = pos[b];
    }
}

void pileOnto(int blocks[][N], int pos[], int a, int b)
{
    /*printf("Pile block %d onto block %d\n", a, b);*/

    if (a == b || pos[a] == pos[b])
        ;
    else {
        /*move the blocks on top of block "b"*/
        int i=0, bl;
        while ( blocks[pos[b]][i] != b)
            i++;
        /*leave b where it is*/
        i++;
        bl = blocks[pos[b]][i];
        while (bl >= 0)
        {
            /*move to original position*/
            push(blocks, bl, bl);
            /*remove from current*/
            blocks[pos[b]][i] = -1;
            pos[bl] = bl;
            i++;
            bl = blocks[pos[b]][i];
        }
        /*now move pile of a over*/
        int start_pos_a = pos[a];
        i=0;
        while ( blocks[start_pos_a][i] != a)
            i++;
        bl = blocks[start_pos_a][i];
        while (bl >= 0)
        {
            /*move these blocks back to b*/
            push(blocks, bl, pos[b]);
            blocks[start_pos_a][i] = -1;
            /*update positions*/
            pos[bl] = pos[b];
            i++;
            bl = blocks[start_pos_a][i];
        }
    }
}


void pileOver(int blocks[][N], int pos[], int a, int b)
{
    /*printf("Pile block %d over block %d\n", a, b);*/
    int i=0, bl;

    if (a == b || pos[a] == pos[b])
        ;
    else {
        /*move pile of a over*/
        int start_pos_a = pos[a];
        while ( blocks[start_pos_a][i] != a)
            i++;
        bl = blocks[start_pos_a][i];
        while (bl >= 0)
        {
            /*move these blocks back to b*/
            push(blocks, bl, pos[b]);
            blocks[start_pos_a][i] = -1;
            /*update positions*/
            pos[bl] = pos[b];
            i++;
            bl = blocks[start_pos_a][i];
        }
    }
}