MIME type


The aim of this puzzle is to match files with their MIME type by reading their extensions. It involves without naming it a peculiar data structure : dictionaries. Let us see a simple implementation in C, and how to use standards in Java and Python.

C

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

// Represents an association between an extension, and its mime type
struct pair { char *ext; char *mime; };

// A dictionnary can be implented very simply as a pair array
struct dict {
    int size;
    struct pair *elmts;
};

/* Returns the MIME type of label 'ext' in dictionnary 'dict'
   or "UNKNOWN" if there is no matching extension */
char *assoc (struct dict *d, char *ext) {
    for (int i = 0; i < d->size; i++)
        if (strcmp(d->elmts[i].ext, ext) == 0)
            return d->elmts[i].mime;
    return "UNKNOWN";
}

// Replaces all uppercase chars of 'str' by the corresponding lowercase chars
void toLower (char *str) {
    for (; *str != '\0'; str++)
        *str = tolower(*str);
}

// Returns a pointer on the first char of the extension of 'str' if it has one
// or NULL else
char *getExt (char *str) {
    for (char *ext = str+strlen(str); ext != str; ext--)
        if (*(ext-1) == '.')
            return ext;
    return NULL;
}

int main(int argc, char** argv)
{
    int dictSize, nbFiles;
    scanf("%d\n%d\n", &dictSize, &nbFiles);

    // Initializes the dictionary extension-MIME type
    struct dict d;
    struct pair *p;
    d.size = dictSize;
    d.elmts = malloc(d.size*sizeof(struct pair));
    for (int i = 0; i < dictSize; i++) {
        p = d.elmts+i;
        p->ext = malloc(11*sizeof(char));
        p->mime = malloc(51*sizeof(char));
        // here using scanf is quite safe because maximal lengths are known
        scanf("%s %s\n", p->ext, p->mime);
        toLower(p->ext);
    }

    // processes file 1 by 1, by isolating ext and matching it with a MIME type
    char file[257];
    char *ext;
    for (int i = 0; i < nbFiles; i++) {
        gets(file);
        toLower(file);
        ext = getExt(file);
        printf("%s\n", assoc(&d, ext?ext:""));
    }

    for (int i = 0; i < dictSize; i++) {
        p = d.elmts+i;
        free(p->ext);
        free(p->mime);
    }
    free(d.elmts);

    return EXIT_SUCCESS;
}
            

Java

import java.util.*;

class Solution {
    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);

        int nbAssociations = in.nextInt();
        int nbFiles = in.nextInt();
        in.nextLine();
        
        // assoc associates to each file extension the corresponding MIME type
        Map assoc = new HashMap();
        for (int i = 0; i < nbAssociations; i++) {
            assoc.put(in.next().toLowerCase(), in.next());
            in.nextLine();
        }

        for (int i = 0; i < nbFiles; i++) {
            // isolates the extension, which is the part after the last . 
            String fileName = in.nextLine().toLowerCase();
            int pos = fileName.lastIndexOf('.');
            String extension = (pos == -1) ? "" : fileName.substring(pos+1, fileName.length());
            // prints the corresponding MIME type, or UNKNOWN
            System.out.println((String)(assoc.getOrDefault(extension, "UNKNOWN")));
        }
    }
}
            

Python 3

import sys

nbAssociations, nbFiles = int(input()), int(input())

# assoc associates to each file extension the corresponding MIME type
assoc = {}
for i in range(nbAssociations):
    ext, mime = input().split()
    assoc[ext.lower()] = mime

for i in range(nbFiles):
    name = input().lower().split('.') 
    ext = name[-1] if len(name) != 1 else None
    print(assoc[ext] if ext in assoc else "UNKNOWN")