Programming Challenges - A List

Lets start a list of programming challenges, and include a difficulty level for each program(easy, medium, or hard). Basiclly, you need to say what the program needs to do, any special features, whatever. Please post your files as an attachment, or host it and put a link to it, so to not spoil the answers to other people. Anyone can compete, and you could use any programming language you want, but since this is a C Programming Forum (well, it is Unix, but whatever), preferably C.

This should not be an epic failure,
Octal.

If no one is willing to post anything, I'll start off with something to get us started:

Challenge: Convert English to Morse-Code and Morse-Code to English (the user can decide which). Each Morse-Coded letter should have one space seperating them, and three spaces seperating each word.

Difficulty: Easy

Helpful Information: http://upload.wikimedia.org/wikipedia/commons/9/92/Intcode.png

Bonus: Make sounds according to the actual beeps that morse code would make. Remember that '.' is a short beep, and '-' is a long beep.

I'll have my solution up in a short amount of time.

In the interest of laziness (and the fact that I am busy at work right now), here's a python version.

#!/usr/local/bin/python

morseDict=dict([('A','.-'),('B','-...'),('C','-.-.'),('D','-..'),('E','.'),('F','..-.'),('G','--.'),('H','....'),('I','..'),('J','.---'),('K','-.-'),('L','.-..'),('M','--'),('N','-.'),('O','---'),('P','.--.'),('Q','--.-'),('R','.-.'),('S','...'),('T','-'),('U','..-'),('V','...-'),('W','.--'),('X','-..-'),('Y','-.--'),('Z','--..'),('0','-----'),('1','.----'),('2','..---'),('3','...--'),('4','....-'),('5','.....'),('6','-....'),('7','--...'),('8','---..'),('9','----.')])

inputLine=raw_input()
inputLine=inputLine.upper()

for letter in inputLine:
        if letter == " ":
                print "  ",
        else:
                print morseDict[letter],

This is written on a server, so I'm not going to try for the sounds bit (there's no way for me to verify if my Solaris box is beeping away or not).

-edit
Currently handles only letters and numbers

It didn't have to handle anything else...

I can't get the array to work...I have everything else worked out. If someone wants to look at my code and help, I would appretiate it.

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

const char a[][] = { /* morse.c:5: error: array type has incomplete element type */
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
	'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
	'Y', 'Z',
	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
	' ', 
	".- ", "-.. ", "-.- ", "-.. ", ". ", "..-. ", "--. ", "....",
	"..", ".--- ", "-.- ", ".-.. ", "-- ", "-. ", "--- ", ".--. ",
	"--.- ", ".-. ", "... ", "- ", "..- ", "...- ", "...- ",
	".-- ", "-..- ", "-.-- ", "--.. ",
	".---- ", "..--- ", "...-- ", "....- ", "..... ", "-.... ",
	"--... ", "---.. ", "----. ", "----- ",
	"   "
};

void convert(char [], int);
int set_ary_num(int, int);
void help(char []);

main(int argc, char *argv[]) {
	if (argc < 3 || strstr(argv[1], "-h") != NULL) {
		help(argv[0]);
		exit(1);
	}
	if (strstr(argv[1], "-e") != NULL) {
		convert(argv[2], 0);
	} else if (strstr(argv[1], "-m") != NULL) {
		convert(argv[2], 1);
	} else {
		fprintf(stderr, "unkown option: %s\n\n", argv[1]);
		help(argv[0]);
		exit(1);
	}
	
}
void convert(char s[], int mode) {
	int i = 0, j;

	while (s != '\0') {
		j = 0;
		while (s != a[j]) {
			j++;
		}
		j = set_ary_num(j, mode);
		printf("%s", a[j+=35]);
		i++;
	}
}
int set_ary_num(int n, int mode) {
	return (mode == 0) ? (n += 35) : (n -= 35);
}
void help(char prog[]) {
	fprintf(stderr, "usage: %s [options] [string]\n"
		"options:\n\t-e\tenglish to morse\n"
		"\t-m\tmorse to english\n\t-h\tprint this\n",
		prog);
}

I've tried a few things for that, and I can't get anything to work...

That array definition is crazy. The closest legal definition to something like that might be something like:

[code]const char a[][5] = {
{ 'A', 'B', 'C', 'D', 'E' },
{ 'a', 'b', 'c', 'd', 'e' }
};

But here everything is a character. You are trying to mix characters and strings in one array. A one dimensional array of structures with each structure containing one element which is the character and a second element which is a string with the morse code might work better for you.

Here's the C code implementation. It is working, but with a wierd output:

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

struct morse {
        char letter;
        char morseCode[6];
};

int main(int argc, char *argv[]) {
        struct morse morse[36];
        char input;

        morse[0].letter='0';
        strcpy(morse[0].morseCode,"-----");
        morse[1].letter='1';
        strcpy(morse[1].morseCode,".----");
        morse[2].letter='2';
        strcpy(morse[2].morseCode,"..---");
        morse[3].letter='3';
        strcpy(morse[3].morseCode,"...--");
        morse[4].letter='4';
        strcpy(morse[4].morseCode,"....-");
        morse[5].letter='5';
        strcpy(morse[5].morseCode,".....");
        morse[6].letter='6';
        strcpy(morse[6].morseCode,"-....");
        morse[7].letter='7';
        strcpy(morse[7].morseCode,"--...");
        morse[8].letter='8';
        strcpy(morse[8].morseCode,"---..");
        morse[9].letter='9';
        strcpy(morse[9].morseCode,"----.");
        morse[10].letter='A';
        strcpy(morse[10].morseCode,".-");
        morse[11].letter='B';
        strcpy(morse[11].morseCode,"-...");
        morse[12].letter='C';
        strcpy(morse[12].morseCode,"-.-.");
        morse[13].letter='D';
        strcpy(morse[13].morseCode,"-..");
        morse[14].letter='E';
        strcpy(morse[14].morseCode,".");
        morse[15].letter='F';
        strcpy(morse[15].morseCode,"..-.");
        morse[16].letter='G';
        strcpy(morse[16].morseCode,"--.");
        morse[17].letter='H';
        strcpy(morse[17].morseCode,"....");
        morse[18].letter='I';
        strcpy(morse[18].morseCode,"..");
        morse[19].letter='J';
        strcpy(morse[19].morseCode,".---");
        morse[20].letter='K';
        strcpy(morse[20].morseCode,"-.-");
        morse[21].letter='L';
        strcpy(morse[21].morseCode,".-..");
        morse[22].letter='M';
        strcpy(morse[22].morseCode,"--");
        morse[23].letter='N';
        strcpy(morse[23].morseCode,"-.");
        morse[24].letter='O';
        strcpy(morse[24].morseCode,"---");
        morse[25].letter='P';
        strcpy(morse[25].morseCode,".--.");
        morse[26].letter='Q';
        strcpy(morse[26].morseCode,"--.-");
        morse[27].letter='R';
        strcpy(morse[27].morseCode,".-.");
        morse[28].letter='S';
        strcpy(morse[28].morseCode,"...");
        morse[29].letter='T';
        strcpy(morse[29].morseCode,"-");
        morse[30].letter='U';
        strcpy(morse[30].morseCode,"..-");
        morse[31].letter='V';
        strcpy(morse[31].morseCode,"...-");
        morse[32].letter='W';
        strcpy(morse[32].morseCode,".--");
        morse[33].letter='X';
        strcpy(morse[33].morseCode,"-..-");
        morse[34].letter='Y';
        strcpy(morse[34].morseCode,"-.--");
        morse[35].letter='Z';
        strcpy(morse[35].morseCode,"--..");

        while((input=fgetc(stdin))!=EOF) {
                if(input=='\n') fprintf(stdout,"\n");
                if(input==' ') {
                        fprintf(stdout,"   ");
                }
                if(input>47&&input<58) {
                        fprintf(stdout,"%s ",morse[input-48].morseCode);
                        continue;
                }
                input=toupper(input);
                fprintf(stdout,"%s ",morse[input-55].morseCode);
        }

}

The letter in the struct is not used because I am manipulating the array index, but if you try to add symbols, it may be necessary to actually run through the entire array every time and compare the input value with the letter and print the corresponding morse code value. And I can't understand the output that I'm getting either.

# ./a.out < test
- .... .. ...    ��� .. ...    ��� .-    ��� - . ... -    ��� ..-. .. .-.. .    ��� - . ... - .. -. --.    ��� ..-. --- .-.    ��� -- --- .-. ... .    ��� -.-. --- -.. .    ��� - .... .- -    ��� .. ...    ��� -- --- .-. ... .    ��� .- -. -..    ��� -. --- -    ��� -- --- .-. --.. . 

Why are those symbols popping up after every " " that is encountered?

Perhaps this ?

                input=toupper(input);
                fprintf(stdout,"%s ",morse[input-55].morseCode);

becomes

        else if ((input >= 65 && input <= 90) || (input >= 97 && input <= 122))
            {
                input=toupper(input);
                fprintf(stdout,"%s ",morse[input-55].morseCode);
                continue;
            }
        if (input)
            fprintf (stdout, " %c ", input);

You did not handle characters outside the set [A-Za-z].

[/tmp]$ ./morse
www.unix.com
.-- .-- .--  . ..- -. .. -..-  . -.-. --- -- 

Yes, I haven't. But I had a special condition for handling the ' ', but I forgot the 'continue' after that so it was falling through the rest of the while loop. Anyway, taken care of. Thanks

Sucessfully does english to morse, but fails with morse to english (probaly the best I'll get):

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

const char e[] = {
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
	'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
	'Y', 'Z',
	'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
	' '
};
const char *m[] = {
	".- ", "-.. ", "-.- ", "-.. ", ". ", "..-. ", "--. ", "....",
	"..", ".--- ", "-.- ", ".-.. ", "-- ", "-. ", "--- ", ".--. ",
	"--.- ", ".-. ", "... ", "- ", "..- ", "...- ", "...- ",
	".-- ", "-..- ", "-.-- ", "--.. ",
	".---- ", "..--- ", "...-- ", "....- ", "..... ", "-.... ",
	"--... ", "---.. ", "----. ", "----- ",
	"   "
};

void morse(char []);
void unmorse(char []);
void help(char []);

main(int argc, char *argv[]) {
	if (argc < 3 || strstr(argv[1], "-h") != NULL) {
		help(argv[0]);
		exit(1);
	}
	if (strstr(argv[1], "-e") != NULL) {
		morse(argv[2]);
	} else if (strstr(argv[1], "-m") != NULL) {
		unmorse(argv[2]);
	} else {
		fprintf(stderr, "unkown option: %s\n\n", argv[1]);
		help(argv[0]);
		exit(1);
	}
	
}
void morse(char s[]) {
	int i = 0, j;

	while (s != '\0') {
		j = 0;
		while (s != e[j] && s != (e[j] + 'a' - 'A')) {
			j++;
		}
		printf("%s", m[j]);
		i++;
	}
	printf("\n");
}
void unmorse(char s[]) {
	int i = 0, j;

	while (s != '\0') {
		j = 0;
		while (strstr(&s, m[j]) != NULL &&
		       strstr(m[j], &s) != NULL) {
			j++;
		}
		printf("%s", e[j]);
		i++;
	}
}
void help(char prog[]) {
	fprintf(stderr, "usage: %s [options] [string]\n"
		"options:\n\t-e\tenglish to morse\n"
		"\t-m\tmorse to english\n\t-h\tprint this\n",
		prog);
}

I got another challenge (yes, it's conversion):

Challenge: Sucessfully implement rot13: english to rot13.

Difficulty: (really) Easy

Helpful Information: http://en.wikipedia.org/wiki/ROT13

Rot was really easy (though I wasn't anal about error checking):

#include <stdio.h>

char rot(char [], int, int);
char lower(char [], int);

main(int argc, char *argv[]) {
	int i = 0;

	if (argc == 1) {
		fprintf(stderr, "usage: %s [rot] [string]\n", argv[0]);
	}
	while (argv[2] != '\0') {
		argv[2] = lower(argv[2], i);
		argv[2] = rot(argv[2], i, atoi(argv[1]));
		i++;
	}
	printf("%s\n", argv[2]);
}
char lower(char s[], int i) {
	if (s <= 90 && s >= 65)
		s += 32;
	return s;
}
char rot(char s[], int i, int rotnum) {
	return (s > 109) ? (s -= rotnum) : (s += rotnum);
}

Here is my shot!

Not thoroughly tested! :slight_smile:

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

#define CONS 13
#define UPPER 65
#define LOWER 97

void rotate(char, int);

int main() {
  char *str = "zypher";
  int length;
  int i;

  for( length = strlen(str), i=0; i<length; i++ ) {
    if( str >= UPPER && str <= (UPPER + CONS*2 - 1) ) {
      rotate(str, UPPER);
    }
    else if( str >= LOWER && str <= (LOWER + CONS*2 - 1) ) {
      rotate(str, LOWER);
    }
  }
  return 0;
}

void rotate(char ch, int start) {
  (ch + CONS) > (start + CONS*2 - 1) ?  printf("%c\n", ( ch + CONS ) - ( (start + CONS*2 - 1) + 1 ) + start) : printf("%c\n", ch + CONS);
}

is awk counted ? :slight_smile:

#!/usr/bin/awk
# Function: convert between morse and english
# Limitations: Many !!
BEGIN{
          morse["A"]=".-"   ; morse["B"]="-..."
          morse["C"]="-.-." ; morse["D"]="-.."
          morse["E"]="."    ; morse["F"]="..-."
          morse["G"]="--."  ; morse["H"]="...." 
          morse["I"]=".."   ; morse["J"]=".---"
          morse["K"]="-.-"  ; morse["L"]=".-.." 
          morse["M"]="--"   ; morse["N"]="-."
          morse["O"]="---"  ; morse["P"]=".--."
          morse["Q"]="--.-" ; morse["R"]=".-." 
          morse["S"]="..."  ; morse["T"]="-"
          morse["U"]="..-"  ; morse["V"]="...-"
          morse["W"]=".--"  ; morse["X"]="-..-" 
          morse["Y"]="-.--" ; morse["Z"]="--.." 
          morse["0"]="-----"; morse["1"]=".----"
          morse["2"]="..---"; morse["3"]=""
          morse["4"]="....-"; morse["5"]="....."
          morse["6"]="-...."; morse["7"]="--..."
          morse["8"]="---.."; morse["9"]="----."          
          while (1){
             print "1) English to Morse."
             print "2) Morse to English."
             print "3) Exit."
             printf "Enter choice: "
             getline which
             if (which==3) { exit }
             if (which==1 ){
                 printf "Enter letters to convert: "
                 getline choice
                 n=split(choice,arr,"")          
                 for(i=1;i<=n;i++) {
                     arr=toupper(arr)
                     printf morse[arr]              
                 }
                 print     
              }
              else if (which==2){
                  printf "Enter morse to convert: "
                  getline morsecode
                  for ( i in morse) {                       
                       if ( morse==morsecode) {
                           print i
                       }
                  }
              
               }
             
             
             }
          

}

Well, this is what the OP had posted

But trying in all possible ways should be good !

was wondering whether this topic should have its own subforum or something, instead of in "C programming".

No, we don't want to have too many forums that people get lost. But ideally people should not post in this forum inviting folks to program in a shell language. If the topic is that general, maybe the advanced forum would have been a better choice. But it's ok here. Sometimes we get a topic that does not nicely fall into any existing forum, but we can't create a new forum each time that happens.

I don't really care.

I have another challenge:

Challenge: Create your own ls, or list the files in a directory.

Difficulty: Medium

Helpful Information: <dirent.h>

Here is my code:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>

void dirlist(DIR *, const char *);

main(int argc, char *argv[]) {
	DIR *dp;
	struct dirent *dp2;

	if (argc == 1) {
		dp = opendir(".");
		if (dp == NULL) {
			perror("opendir");
		}
		dirlist(dp, "./");
	} else {
		while (--argc > 0) {
			dp = opendir(*++argv);
			if (dp == NULL) {
				perror("opendir");
			}
			dirlist(dp, *argv);

			if (argc > 1) {
				printf("\n");
			}
		}
	}
	closedir(dp);
}
void dirlist(DIR *dp, const char *name) {
	struct dirent *dp2;

	printf("%s:\n", name);
	while ((dp2 = readdir(dp)) != NULL) {
		if ((strstr(dp2->d_name, ".") != NULL &&
		     strstr(".", dp2->d_name) != NULL) ||
		    (strstr(dp2->d_name, "..") != NULL) &&
		     strstr("..", dp2->d_name) != NULL) {
			continue;
		}
		printf("%s  ", dp2->d_name);
	}
	printf("\n");
}

Someone else has to come up with another programming challenge...right?

http://acm.uva.es/problemset/

There are some seriously difficult problems on that site....

I don't like some of those problems though; I personally like the type of problems I have submitted.

I have some other challenges in my mind, but I want someone else to submit an idea before I say any more,

Challenge: DRAM

Difficulty: Easy to Medium in C, Easy in perl/python

As the problem says, the value of the palindrome may exceed your system's defined integer size in C/C++.

$ echo /path/to/dir/*

:stuck_out_tongue:

Cheers,
ZB

Good challenge, and I've been working on it for a while now. I can't get a function to determine if a number is a palindrome, but I'll work more on it later.