Bonjour!
Pour commencer, je souhaiterais vous prévenir que lire ce sujet sera un peu long, mais vous le trouverez sûrement très intéressant, donc n'hésitez pas à tout lire!
Je suis "débutant" en C: j'ai commencé il y a 2 mois pour un stage, et j'ai codé pas mal de programmes basiques dans différents domaines. J'ai vu que Google organisait un concours de codage (Google Code Jam), et je me suis dit pourquoi ne pas y participer pour voir un peu mon niveau et apprendre des choses?
Je tiens aussi à préciser que je ne cherche pas une solution toute faite au problème (surtout que la première phase est finie), mais des expliquations.
Voici le problème sur lequel j'aimerais quelques explications (donc un peu long à lire et en anglais, désolé).
Tout d'abord, j'ai quand même était bien impressionné de voir que le premier a résolu ce problème en environ 10 minutes. Et en environ 30 minutes, il en a en fait résolu 3 comme ca... Il y a vraiment des gens aussi forts que ca?Citation:
Problem
So you've registered. We sent you a welcoming email, to welcome you to code jam. But it's possible that you still don't feel welcomed to code jam. That's why we decided to name a problem "welcome to code jam." After solving this problem, we hope that you'll feel very welcome. Very welcome, that is, to code jam.
If you read the previous paragraph, you're probably wondering why it's there. But if you read it very carefully, you might notice that we have written the words "welcome to code jam" several times: 400263727 times in total. After all, it's easy to look through the paragraph and find a 'w'; then find an 'e' later in the paragraph; then find an 'l' after that, and so on. Your task is to write a program that can take any text and print out how many times that text contains the phrase "welcome to code jam".
To be more precise, given a text string, you are to determine how many times the string "welcome to code jam" appears as a sub-sequence of that string. In other words, find a sequence s of increasing indices into the input string such that the concatenation of input[s[0]], input[s[1]], ..., input[s[18]] is the string "welcome to code jam".
The result of your calculation might be huge, so for convenience we would only like you to find the last 4 digits.
Input
The first line of input gives the number of test cases, N. The next N lines of input contain one test case each. Each test case is a single line of text, containing only lower-case letters and spaces. No line will start with a space, and no line will end with a space.
Output
For each test case, "Case #x: dddd", where x is the case number, and dddd is the last four digits of the answer. If the answer has fewer than 4 digits, please add zeroes at the front of your answer to make it exactly 4 digits long.
Limits
1 ≤ N ≤ 100
Small dataset
Each line will be no longer than 30 characters.
Large dataset
Each line will be no longer than 500 characters.
Sample:
Input :
3
elcomew elcome to code jam
wweellccoommee to code qps jam
welcome to codejam
Output:
Case #1: 0001
Case #2: 0256
Case #3: 0000
Parce que moi j'y ai passé quasiment 24 heures pour 2 problèmes ^^
Sinon venons en au vif du sujet.
Pour résumer: on a donc un string de 18 lettres (welcome to code jam) à trouver, quelque soit l'espace entre deux caractères de cette phrase.
Après moulte réflexions, j'en suis venu à l'idée qu'une fonction récursive pouvait être pas mal. Cette fonction serait la suivante:
je lui dit de chercher un caractère dans une chaine à partir d'une certaine position. Si elle trouve ce caractère, elle se rappelle elle même pour trouver le caractère suivant.
Si le caractère suivant a pour numéro 19, c'est que l'on a trouvé notre phrase au complet (il n'y a que 18 caractères dans "welcome to code jam").
Ceci fonctionne très bien pour le petit test qui est donné à la fin. Ceci fonctionne aussi très bien pour le premier test simple donné par google. Par contre le second test plus complexe (avec 500 caractères) met à mal mon ordinateur, et refuse de me donner la réponse.
Je cherche donc à savoir quelles pourraient être les améliorations possibles à cette proposition de fonction récursive afin de rendre la détection plus rapide.
J'ai déjà pensé à supprimé tous les caractères qui n'appartiennent pas à ceux du string en question, mais je ne vois pas d'amélioration notable sur le test long.
Si ca vous intéresse, voici le code que j'ai écrit jusqu'à maintenant:
Et si vous voulez les fichiers de test pour vous amuser vous aussi, n'hésitez pas à me demander ^^Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 /* ================================================================== * Author: A. Decagny * * Date: September 2009 * * Context: Google Code Jam 2009 - Welcome to code jam * * Company: Oº°* Personnal Purposes *°ºO * * file: main.c * ================================================================== */ #define DATA_SIZE 550 #include <stdio.h> #include <stdlib.h> #include <string.h> void seekIsAGeek(char* welcome, int address, int rankOfLetter, char* data, int* result); int main() { int i = 0, j=0; char textFileName[30] = ""; FILE* textFile = NULL; FILE* resultFile = NULL; char** stringOfData = NULL; char** dataExpurgated = NULL; int nbOfData = 0; int result = 0; char* welcome = "welcome to code jam"; char buffer[2] = ""; /* We open the file and get the data */ printf("####################################################\n"); printf("######## Welcome to \"Welcome to Code Jam\" #########\n"); printf("####################################################\n"); printf("\n"); printf("What is the name of the input file?\n"); scanf("%s", textFileName); textFile = fopen(textFileName,"r"); rewind(textFile); fscanf(textFile, "%d\n", &nbOfData); stringOfData = malloc(nbOfData*sizeof(int)); dataExpurgated = malloc(nbOfData*sizeof(int)); for(i=0; i<nbOfData; i++) { stringOfData[i] = malloc(DATA_SIZE * sizeof(char)); dataExpurgated[i] = malloc(DATA_SIZE * sizeof(char)); dataExpurgated[i][0]='\0'; fgets(stringOfData[i], DATA_SIZE - 1, textFile); } fclose(textFile); /* We can now make all the work */ resultFile = fopen("result.txt", "w+"); rewind(resultFile); for(i=0; i<nbOfData; i++) { result = 0; /* expurgating of the data */ for(j=0; j<strlen(stringOfData[i]);j++) { if (strchr(welcome,stringOfData[i][j]) != NULL) { buffer[0]=stringOfData[i][j]; buffer[1]='\0'; strcat(dataExpurgated[i],buffer); } } /* number of possibilities? We search for the letter */ seekIsAGeek(welcome, 0, 0, dataExpurgated[i], &result); fprintf(resultFile, "Case #%d: %04d\n", i+1, result); printf("Case #%d\n", i+1); } /* And now we can free everything */ for(i=0; i<nbOfData; i++) { free(stringOfData[i]); } free(stringOfData); fclose(resultFile); free(dataExpurgated); return 0; } /* This function is used to know where the first googd letter is, * and then call itself again! * /!\ This function is a recursive function! */ void seekIsAGeek(char* welcome, int address, int rankOfLetter, char* data, int* result) { int i = 0; if (rankOfLetter == 19) { (*result)++; } else { for(i=address; i<strlen(data); i++) { if (data[i] == welcome[rankOfLetter]) { seekIsAGeek(welcome, i, rankOfLetter +1, data, result); } } } }
Mais j'avoue que la je bloque un peu sur la méthode pour réaliser des optimisations...
Et si vous avez des idées de cours que je peux lire pour rendre mes codes plus performant en général, je suis preneur. Les cours d'algorithmie de ce site son un bon début? Et après?
Merci d'avance pour votre aide!