10194 - moocHW6b   

Description

同樣是以範例程式,完成其中缺少的 unzip函數。這個函數的作用是將 a list of pairs 變成 a pair of lists。
底下的表示法,方括號 [] 代表 list,圓括弧 () 代表 pair。
譬如原本的 list of pairs 是 [(1,"a"),(2,"b"),(3,"c")],經過 unzip 之後變成 ([1,2,3],["a","b","c"])。
如果有兩個 lists [1,2,3] 和]["a","b","c"],先做第一題描述的兩次 zip,變成
[("a",(1,"a")),("b",(2,"b")),("c",(3,"c"))] 之後,如果再做一次 unzip 就變成
(["a","b","c"],[(1,"a"),(2,"b"),(3,"c")])

這一題要做的就是,輸入兩個 lists,經過 N 次 zip 之後,再做一次 unzip,然後輸出最後產生的 pair。
上述的操作已經寫在範例程式中,只要將 unzip 正確寫出,就能產生上述的執行結果。

範例程式:

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


#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)
#define STR_LEN 20

/* incomplete struct Atom */
struct Atom;

/* a pair of atom */
typedef struct Pair {
    struct Atom *left;
    struct Atom *right;
} Pair;

/* a list of atoms */
typedef struct List {
    struct Atom *data;
    struct List *next;
} List;

/* an atom can be a string, an int, a pair of atoms, or a list */
typedef struct Atom {
    char str[STR_LEN+1];
    int val;
    Pair *pair;
    List *lst;
    int dtype; /* 0 for string, 1 for int, 2 for pair, 3 for list*/
} Atom;



/* functions for creating an atom */
Atom* atom_str(char *str);
Atom* atom_val(int val);

Atom* copy_atom(Atom *aptr);
void print_atom(Atom *aptr);
void free_atom(Atom *atpr);

/* convert an atom to a single-atom list */
List* atom_to_list(Atom *a);

/* this function is important */
/* useful for creating a new copy of an existing list */
List* cons(Atom *a, List *b);

void print_list(List *lptr);
void free_list(List *lptr);
int length(List *lptr);
List* read_list_helper(List *l, int n);
List* read_list(void);

Atom* head(List *lptr);
List* tail(List *lptr);

List* zip(List *lptr1, List *lptr2);
Pair* unzip(List *lptr);

List* take(int n, List *l);
List* drop(int n, List *l);

Pair* pair_list(List *lptr1, List *lptr2);
Pair* split_at(int n, List *l);

void print_pair(Pair* p);
void free_pair(Pair* p);

int main(void)
{
    List *s1, *s2, *s3;
    Pair *p;
    int N, i;

    s1 = read_list();
    s2 = read_list();

    scanf("%d", &N);
    for (i=0; istr[0] = 'Θ';
    } else {
        strncpy(aptr->str, str, STR_LEN);
    }
    aptr->val = 0;
    aptr->pair = NULL;
    aptr->lst = NULL;
    aptr->dtype = 0;
    return aptr;
}

/* Given a value, create a new atom */
Atom* atom_val(int val)
{
    Atom *aptr = (Atom*) malloc(sizeof(Atom));
    aptr->str[0] = 'Θ';
    aptr->val = val;
    aptr->pair = NULL;
    aptr->lst = NULL;
    aptr->dtype = 1;
    return aptr;
}


Atom* copy_atom(Atom *aptr)
{
    Atom *aptr_new;

    aptr_new = (Atom*) malloc(sizeof(Atom));

    if (aptr_new==NULL) return NULL;
    if (aptr==NULL) return NULL;

    aptr_new->dtype = aptr->dtype;

    if (aptr->dtype == 0) {
        strncpy(aptr_new->str, aptr->str, STR_LEN);
    } else if (aptr->dtype == 1) {
        aptr_new->val = aptr->val;
    } else if (aptr->dtype == 2) {
        if (aptr->pair == NULL) {
            aptr_new->pair = NULL;
        } else {
            aptr_new->pair = (Pair *) malloc(sizeof(Pair));
            aptr_new->pair->left = copy_atom(aptr->pair->left);
            aptr_new->pair->right = copy_atom(aptr->pair->right);
        }
    } else if (aptr->dtype == 3) {
        if (aptr->lst==NULL) {
            aptr_new->lst = NULL;
        } else {
            aptr_new->lst = cons(head(aptr->lst), tail(aptr->lst));
        }
    }
    return aptr_new;
}

void print_atom(Atom *aptr)
{
    if (aptr==NULL) {
        printf("Empty");
        return;
    }
    switch (aptr->dtype) {
    case 0:
        printf("\"%s\"", aptr->str);
        break;
    case 1:
        printf("%d", aptr->val);
        break;
    case 2:
        print_pair(aptr->pair);
        break;
    case 3:
        print_list(aptr->lst);
        break;
    default:
        printf("Undefined.");
    }

}
/* Given an atom, create a list containing the atom. */
List* atom_to_list(Atom *a)
{
    List *b;
    b = (List*) malloc(sizeof(List));
    b->next = NULL;
    b->data = copy_atom(a);
    return b;
}

/* create a new list and add the atom to the head */
List* cons(Atom *a, List *b)
{
    List *c;

    c = atom_to_list(a);
    if (b!=NULL) {
        c->next = cons(head(b), tail(b));
    }

    return c;
}

void print_list(List *lptr)
{
    printf("[");
    while (lptr!=NULL) {
        print_atom(lptr->data);
        if (lptr->next != NULL)
            printf(",");
        lptr = lptr->next;
    }
    printf("]");
}

int len_helper(List *lptr, int len)
{
    if (lptr==NULL) return len;
    else return len_helper(lptr->next, len+1);
}
int length(List *lptr)
{
    return len_helper(lptr, 0);
}

void free_atom(Atom *aptr)
{
    if (aptr != NULL) {
        if (aptr->dtype==2) {
            free_pair(aptr->pair);
        } else if (aptr->dtype==3) {
            free_list(aptr->lst);
        }
        free(aptr);
    }
}

void free_list(List *lptr)
{
    List *p;
    if (lptr!=NULL) {
        p = tail(lptr);
        if (head(lptr)!=NULL) {
            free_atom(head(lptr));
        }
        free_list(p);
    }
}

Atom* head(List *lptr)
{
    return lptr->data;
}

List* tail(List *lptr)
{
    return (lptr==NULL) ? NULL : lptr->next;
}

/* create a new list combining a string list and a value list
If the two input lists have different lengths, the new list will be
of the same length as the shorter one.
*/

List* zip(List *lptr1, List *lptr2)
{
    Atom a;
    List *l1, *l2;

    if ( ??? ) { //lptr1 或 lptr2 兩者有一個是 NULL
        return NULL;
    } else {
        a.pair = ???; // malloc 取得一塊 Pair 空間
        a.pair->left = ???; // 利用  copy_atom  複製 lptr1 的開頭第一個 atom
        a.pair->right = ???; // 利用  copy_atom  複製 lptr2 的開頭第一個 atom
        a.dtype = 2;
        l1 = ??? // 利用 zip 處理剩下的 lists  (提示: 用遞迴)
        l2 = cons(&a, l1); // 利用 cons 造出新的 list
        free_pair(a.pair);
        free_list(l1);
        return l2;
    }
}


Pair* unzip(List *lptr)
{
    Atom *h;
    Pair *p, *newp;
    List *l1, *l2;
    if (lptr==NULL) {
        newp = pair_list(NULL, NULL);
        return newp;
    }

    h = ???; // // 取出 lptr 的開頭第一個 atom
    p = ???; // 利用 unzip 對剩下的 lptr 遞迴繼續處理
    l1 = ???; // 兩個 lists 分別來自兩個 cons
    l2 = ???; // 一個 cons 組合左邊的 list 另一個組合右邊的 list
    newp = ???; // // 利用 pair_list 從兩個 lists 產生新的 pair
    free_list(l1);
    free_list(l2);
    free_pair(p);
    return newp;
}


Pair* pair_list(List *lptr1, List *lptr2)
{
    Pair *p;
    Atom a;

    p = (Pair*)malloc(sizeof(Pair));
    a.dtype = 3;

    a.lst = lptr1;
    p->left = copy_atom(&a);

    a.lst = lptr2;
    p->right = copy_atom(&a);

    return p;
}



void print_pair(Pair *p)
{
    printf("(");
    print_atom(p->left);
    printf(",");
    print_atom(p->right);
    printf(")");
}

void free_pair(Pair* p)
{
    if (p!=NULL) {
        free_atom(p->left);
        free_atom(p->right);
        free(p);
    }
}

Input

與第一題相同。輸入資料會有五行。
第一行是一個整數 M1,代表第一個 list 包含的資料筆數,第二行則是 M1 筆資料,每筆用空白隔開。
第三行是一個整數 M2,代表第二個 list 包含的資料筆數,第四行則是 M2 筆資料,每筆用空白隔開。
第五行則是一個整數 N。代表執行 zip 的次數。

Output

輸出只有一行,列出經過 N次 zip 之後再做一次 upzip 得到的 pair 內容。最後有換行。

Sample Input  Download

Sample Output  Download

Tags




Discuss