Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #147078 > unrolled thread
| Started by | DFS <nospam@dfs.com> |
|---|---|
| First post | 2019-10-19 13:35 -0400 |
| Last post | 2019-10-27 13:09 -0700 |
| Articles | 20 on this page of 60 — 17 participants |
Back to article view | Back to comp.lang.c
How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-19 13:35 -0400
Re: How to use a struct with qsort()? Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2019-10-19 10:22 -0700
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-19 14:19 -0400
Re: How to use a struct with qsort()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-10-19 19:36 +0100
Re: How to use a struct with qsort()? Melzzzzz <Melzzzzz@zzzzz.com> - 2019-10-19 18:44 +0000
Re: How to use a struct with qsort()? Barry Schwarz <schwarzb@delq.com> - 2019-10-19 10:23 -0700
Re: How to use a struct with qsort()? Ike Naar <ike@sdf.lonestar.org> - 2019-10-19 19:09 +0000
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-19 15:51 -0400
Re: How to use a struct with qsort()? already5chosen@yahoo.com - 2019-10-19 13:09 -0700
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-19 16:26 -0400
Re: How to use a struct with qsort()? already5chosen@yahoo.com - 2019-10-19 13:51 -0700
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-19 17:24 -0400
Re: How to use a struct with qsort()? already5chosen@yahoo.com - 2019-10-19 14:49 -0700
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-19 18:26 -0400
Re: How to use a struct with qsort()? already5chosen@yahoo.com - 2019-10-19 16:32 -0700
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-20 09:22 -0400
Re: How to use a struct with qsort()? Paul <nospam@needed.invalid> - 2019-10-26 04:15 -0400
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-26 09:37 -0400
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-26 15:40 +0100
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-28 19:49 -0400
Re: How to use a struct with qsort()? Paul <nospam@needed.invalid> - 2019-10-29 01:59 -0400
Re: How to use a struct with qsort()? Paul <nospam@needed.invalid> - 2019-10-30 04:54 -0400
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-30 11:54 +0000
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-30 08:58 -0700
Re: How to use a struct with qsort()? Öö Tiib <ootiib@hot.ee> - 2019-11-07 01:10 -0800
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-11-07 10:51 +0000
Re: How to use a struct with qsort()? Paul <nospam@needed.invalid> - 2019-10-26 15:03 -0400
Re: How to use a struct with qsort()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-10-26 21:50 +0100
Re: How to use a struct with qsort()? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-11-04 16:02 -0800
Re: How to use a struct with qsort()? Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-10-21 11:58 +0000
Re: How to use a struct with qsort()? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-10-23 04:51 -0700
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-19 23:25 +0100
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-19 15:38 -0700
Re: How to use a struct with qsort()? David Brown <david.brown@hesbynett.no> - 2019-10-20 14:44 +0200
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-22 15:42 -0400
Re: How to use a struct with qsort()? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-10-23 05:47 -0700
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-23 16:40 +0100
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-23 13:51 -0700
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-23 23:07 +0100
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-23 15:50 -0700
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-24 01:20 +0100
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-23 18:20 -0700
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-24 10:40 +0100
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-24 11:00 -0700
Re: How to use a struct with qsort()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-10-20 00:30 +0100
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-20 00:44 +0100
Re: How to use a struct with qsort()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-10-20 01:27 +0100
Re: How to use a struct with qsort()? Manfred <noname@add.invalid> - 2019-10-25 20:30 +0200
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-25 16:07 -0400
Re: How to use a struct with qsort()? Ike Naar <ike@sdf.lonestar.org> - 2019-10-26 07:27 +0000
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-26 02:11 -0700
Re: How to use a struct with qsort()? Bart <bc@freeuk.com> - 2019-10-26 11:06 +0100
Re: How to use a struct with qsort()? Manfred <noname@invalid.add> - 2019-10-26 16:58 +0200
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-26 18:17 -0400
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-26 16:08 -0700
Re: How to use a struct with qsort()? DFS <nospam@dfs.com> - 2019-10-26 21:33 -0400
Re: How to use a struct with qsort()? Keith Thompson <kst-u@mib.org> - 2019-10-26 22:10 -0700
Re: How to use a struct with qsort()? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-10-27 01:48 +0100
Re: How to use a struct with qsort()? Manfred <noname@invalid.add> - 2019-10-27 19:29 +0100
Re: How to use a struct with qsort()? Barry Schwarz <schwarzb4aarp@gmail.com> - 2019-10-27 13:09 -0700
Page 1 of 3 [1] 2 3 Next page →
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-19 13:35 -0400 |
| Subject | How to use a struct with qsort()? |
| Message-ID | <cvHqF.33195$hU2.4342@fx20.iad> |
struct words {char *word; double calc;};
I tried:
qsort(words, wordcnt, sizeof(words), compare);
The tcc compiler throws an error: 'words' undeclared
[toc] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2019-10-19 10:22 -0700 |
| Message-ID | <ed2d1df6-bc5f-4344-9e0a-123f61d01f6a@googlegroups.com> |
| In reply to | #147078 |
On Saturday, 19 October 2019 18:13:52 UTC+1, DFS wrote:
> struct words {char *word; double calc;};
>
> I tried:
> qsort(words, wordcnt, sizeof(words), compare);
>
> The tcc compiler throws an error: 'words' undeclared
>
"struct words" is the name of the structure. You need an array of
those structures to sort.
struct words wordlist[100];
will create an array of a hundred structures. You still need to populate
the list with data, which you can do with the curly brackets, or in
a non-test program, probably by reading in the words from a file.
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-19 14:19 -0400 |
| Message-ID | <aqIqF.211712$zU2.43109@fx01.iad> |
| In reply to | #147079 |
On 10/19/2019 1:22 PM, Malcolm McLean wrote:
> On Saturday, 19 October 2019 18:13:52 UTC+1, DFS wrote:
>> struct words {char *word; double calc;};
>>
>> I tried:
>> qsort(words, wordcnt, sizeof(words), compare);
>>
>> The tcc compiler throws an error: 'words' undeclared
>>
> "struct words" is the name of the structure. You need an array of
> those structures to sort.
>
> struct words wordlist[100];
>
> will create an array of a hundred structures. You still need to populate
> the list with data, which you can do with the curly brackets, or in
> a non-test program, probably by reading in the words from a file.
I already populated the struct with words from a file, and a calculation
to go with each word.
The qsort prototype indicates an array - so there's no way to sort the
data already in the struct using qsort()?
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2019-10-19 19:36 +0100 |
| Message-ID | <87v9skzio0.fsf@bsb.me.uk> |
| In reply to | #147081 |
DFS <nospam@dfs.com> writes:
> On 10/19/2019 1:22 PM, Malcolm McLean wrote:
>> On Saturday, 19 October 2019 18:13:52 UTC+1, DFS wrote:
>>> struct words {char *word; double calc;};
>>>
>>> I tried:
>>> qsort(words, wordcnt, sizeof(words), compare);
>>>
>>> The tcc compiler throws an error: 'words' undeclared
>>>
>> "struct words" is the name of the structure. You need an array of
>> those structures to sort.
>>
>> struct words wordlist[100];
>>
>> will create an array of a hundred structures. You still need to populate
>> the list with data, which you can do with the curly brackets, or in
>> a non-test program, probably by reading in the words from a file.
>
>
> I already populated the struct with words from a file, and a
> calculation to go with each word.
>
> The qsort prototype indicates an array - so there's no way to sort the
> data already in the struct using qsort()?
You want to sort the array of structs, so there is no problem -- you
have an array as required by qsort.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Melzzzzz <Melzzzzz@zzzzz.com> |
|---|---|
| Date | 2019-10-19 18:44 +0000 |
| Message-ID | <sQIqF.1184885$_w5.651528@fx31.am4> |
| In reply to | #147081 |
On 2019-10-19, DFS <nospam@dfs.com> wrote:
> On 10/19/2019 1:22 PM, Malcolm McLean wrote:
>> On Saturday, 19 October 2019 18:13:52 UTC+1, DFS wrote:
>>> struct words {char *word; double calc;};
>>>
>>> I tried:
>>> qsort(words, wordcnt, sizeof(words), compare);
>>>
>>> The tcc compiler throws an error: 'words' undeclared
>>>
>> "struct words" is the name of the structure. You need an array of
>> those structures to sort.
>>
>> struct words wordlist[100];
>>
>> will create an array of a hundred structures. You still need to populate
>> the list with data, which you can do with the curly brackets, or in
>> a non-test program, probably by reading in the words from a file.
>
>
> I already populated the struct with words from a file, and a calculation
> to go with each word.
>
> The qsort prototype indicates an array - so there's no way to sort the
> data already in the struct using qsort()?
qsort works for arrays. if array is data member of your struct pass it
as any other array...
>
>
>
>
--
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@delq.com> |
|---|---|
| Date | 2019-10-19 10:23 -0700 |
| Message-ID | <h8hmqet6l4a4t6e6aiqlt53d2m98eq7msq@4ax.com> |
| In reply to | #147078 |
On Sat, 19 Oct 2019 13:35:55 -0400, DFS <nospam@dfs.com> wrote:
>struct words {char *word; double calc;};
>
>I tried:
>qsort(words, wordcnt, sizeof(words), compare);
>
>The tcc compiler throws an error: 'words' undeclared
Where do you think words was declared. qsort requires the address of
an object. There is no object named words. There is a type named
struct words but that is not the same thing.
You probably want something like
struct Words {char *word; double calc;} words[10];
so words is now the name of the array of struct and when used in the
call to qsort it is converted to the address of the first element of
the array.
In that case you would also change the third argument of the call to
qsort to sizeof(struct Words) or more simply sizeof *words.
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Ike Naar <ike@sdf.lonestar.org> |
|---|---|
| Date | 2019-10-19 19:09 +0000 |
| Message-ID | <slrn3if8qqmnqo.6il.ike@sdf.lonestar.org> |
| In reply to | #147078 |
On 2019-10-19, DFS <nospam@dfs.com> wrote:
> struct words {char *word; double calc;};
>
> I tried:
> qsort(words, wordcnt, sizeof(words), compare);
>
> The tcc compiler throws an error: 'words' undeclared
The type is named "struct words", not "words".
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-19 15:51 -0400 |
| Message-ID | <yFJqF.60483$oA2.36504@fx08.iad> |
| In reply to | #147084 |
On 10/19/2019 3:09 PM, Ike Naar wrote:
> On 2019-10-19, DFS <nospam@dfs.com> wrote:
>> struct words {char *word; double calc;};
>>
>> I tried:
>> qsort(words, wordcnt, sizeof(words), compare);
>>
>> The tcc compiler throws an error: 'words' undeclared
>
> The type is named "struct words", not "words".
error: identifier expected
[toc] | [prev] | [next] | [standalone]
| From | already5chosen@yahoo.com |
|---|---|
| Date | 2019-10-19 13:09 -0700 |
| Message-ID | <06add10e-1e30-4741-a20c-ff56363733fe@googlegroups.com> |
| In reply to | #147086 |
On Saturday, October 19, 2019 at 10:41:27 PM UTC+3, DFS wrote:
> On 10/19/2019 3:09 PM, Ike Naar wrote:
> > On 2019-10-19, DFS <nospam@dfs.com> wrote:
> >> struct words {char *word; double calc;};
> >>
> >> I tried:
> >> qsort(words, wordcnt, sizeof(words), compare);
> >>
> >> The tcc compiler throws an error: 'words' undeclared
> >
> > The type is named "struct words", not "words".
>
>
> error: identifier expected
It does not sound like you know 'C'.
I recommend to spend several days (or a little more) with books and tutorials. It's may be boring, but worth it.
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-19 16:26 -0400 |
| Message-ID | <BkKqF.69070$1A2.65981@fx07.iad> |
| In reply to | #147087 |
On 10/19/2019 4:09 PM, already5chosen@yahoo.com wrote:
> On Saturday, October 19, 2019 at 10:41:27 PM UTC+3, DFS wrote:
>> On 10/19/2019 3:09 PM, Ike Naar wrote:
>>> On 2019-10-19, DFS <nospam@dfs.com> wrote:
>>>> struct words {char *word; double calc;};
>>>>
>>>> I tried:
>>>> qsort(words, wordcnt, sizeof(words), compare);
>>>>
>>>> The tcc compiler throws an error: 'words' undeclared
>>>
>>> The type is named "struct words", not "words".
>>
>>
>> error: identifier expected
>
> It does not sound like you know 'C'.
> I recommend to spend several days (or a little more) with books and tutorials. It's may be boring, but worth it.
Books and tutorials won't help. I've spent hours on stack overflow
trying to figure out how to qsort an array of structs. It's a common
question out there.
I actually want to sort the data first by the number field, then by the
char field. But I'll be happy if I can sort by just the number field.
Here's the program as it stands, which works great except for
this sorting issue. You can test it by using words_alpha.txt from
https://github.com/dwyl/english-words
=============================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <Windows.h>
//windows tcc compile
//tcc -o anagrams.exe anagrams.c
//usage
//anagrams wordlist.txt searchword
//vars
int i=0, j=0, k=0;
int primes[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};
char *charset = "abcdefghijklmnopqrstuvwxyz";
LARGE_INTEGER frequency,start,end;
//build struct
struct words {char *word; double wordpf;};
struct words **wordrec = NULL;
//program timing
double elapsedtime(LARGE_INTEGER startingtimer)
{
QueryPerformanceCounter(&end);
return (end.QuadPart - startingtimer.QuadPart) /
(double)frequency.QuadPart;
}
//compute product of primes corresponding to the letters of the input word
double calcpf(char *str, int len) {
double pf = 1;
for(i=0;i<len;i++) {
pf *= primes[(int)(strchr(charset, str[i]) - charset)];
}
return pf;
}
//trim trailing spaces
void righttrim(char *str, int len) {
while(len>0 && isspace(str[len-1])){
len--;
}
str[len] = '\0';
}
//sort structure by prime factors, then word
int comparepf(const void *p1, const void *p2)
{
const struct words *a = p1;
const struct words *b = p2;
//printf("%.0lf %.0lf\n",a->wordpf,b->wordpf);
if(a->wordpf > b->wordpf)
return 1;
else if (a->wordpf < b->wordpf)
return -1;
else
return 0;
}
int main(int argc, char *argv[])
{
QueryPerformanceFrequency(&frequency);
printf("\nloading data...");
//read in list of words, load into struct
int wordcnt = 0;
char wordin[30];
char *filein = argv[1];
char *searchword = argv[2];
FILE *fwords;
QueryPerformanceCounter(&start);
fwords = fopen(filein,"r");
while(fgets(wordin,sizeof(wordin),fwords)!=NULL) {
//trim trailing spaces
righttrim(wordin,strlen(wordin));
//memory
wordrec = (struct words **)realloc(wordrec,(wordcnt+1) * sizeof(struct
words *));
wordrec[wordcnt] = (struct words *)malloc(sizeof(struct words));
wordrec[wordcnt]->word = malloc(strlen(wordin)+1);
//add entry to struct
strcpy(wordrec[wordcnt]->word, wordin);
wordrec[wordcnt]->wordpf = calcpf(wordin, strlen(wordin));
wordcnt++;
}
printf("\n%.4fs to load %d words\n\n",elapsedtime(start),wordcnt);
printf("Contents of struct (word, pf)\n");
for(i=0;i<wordcnt;i++) {
if(i<10 || i>(wordcnt-11)) {
printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
wordrec[i]->wordpf);
}
}
//for fastest search, sort the struct by prime factorization, then word
//https://stackoverflow.com/search?q=sort+array+of+structs
printf("\nsorting by prime factor...\n");
QueryPerformanceCounter(&start);
qsort(struct wordrec, wordcnt, sizeof(struct wordrec), comparepf);
printf("%.4fs to qsort on prime factors\n\n",elapsedtime(start));
printf("Contents of sorted struct (word, pf)\n");
for(i=0;i<wordcnt;i++) {
if(i<10 || i>(wordcnt-11)) {
printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
wordrec[i]->wordpf);
}
}
//find single-word anagrams
//Two comparisons have to be made, but only do 2 if 1 is a match:
//1. compare the prime factorizations (numerical comparison)
//2. compare the word itself
printf("\nSearching for anagrams of '%s'...\n",searchword);
double searchpf = calcpf(searchword, strlen(searchword));
char *dataword = NULL;
j=0;
QueryPerformanceCounter(&start);
for(i=0;i<wordcnt;i++) {
if(wordrec[i]->wordpf==searchpf) {
dataword = malloc(strlen(wordrec[i]->word)+1);
strcpy(dataword,wordrec[i]->word);
if(strcmp(dataword,searchword)!=0)
{
printf("%s ",dataword);
j++;
}
}
}
if(j>0) {printf("\n%d anagram(s) found in %.4fs\n",j,elapsedtime(start));}
if(j==0) {printf("No anagrams found\n");}
//finish
//free(wordincopy);
free(wordrec);
fclose(fwords);
printf("Done");
exit(0);
}
===========================================================
[toc] | [prev] | [next] | [standalone]
| From | already5chosen@yahoo.com |
|---|---|
| Date | 2019-10-19 13:51 -0700 |
| Message-ID | <60434cb2-a003-454b-890f-f2121004bd22@googlegroups.com> |
| In reply to | #147089 |
On Saturday, October 19, 2019 at 11:27:22 PM UTC+3, DFS wrote:
> On 10/19/2019 4:09 PM, already5chosen@yahoo.com wrote:
> > On Saturday, October 19, 2019 at 10:41:27 PM UTC+3, DFS wrote:
> >> On 10/19/2019 3:09 PM, Ike Naar wrote:
> >>> On 2019-10-19, DFS <nospam@dfs.com> wrote:
> >>>> struct words {char *word; double calc;};
> >>>>
> >>>> I tried:
> >>>> qsort(words, wordcnt, sizeof(words), compare);
> >>>>
> >>>> The tcc compiler throws an error: 'words' undeclared
> >>>
> >>> The type is named "struct words", not "words".
> >>
> >>
> >> error: identifier expected
> >
> > It does not sound like you know 'C'.
> > I recommend to spend several days (or a little more) with books and tutorials. It's may be boring, but worth it.
>
>
> Books and tutorials won't help.
How do you know if you never tried?
Learning thing on stack overflow only works when you have a basic knowledge.
Robert Sheckley was absolutely spot on in his classic.
http://www.gutenberg.org/files/33854/33854-h/33854-h.htm
> I've spent hours on stack overflow
> trying to figure out how to qsort an array of structs. It's a common
> question out there.
>
> I actually want to sort the data first by the number field, then by the
> char field. But I'll be happy if I can sort by just the number field.
>
> Here's the program as it stands, which works great except for
> this sorting issue. You can test it by using words_alpha.txt from
> https://github.com/dwyl/english-words
>
> =============================================================
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <time.h>
> #include <Windows.h>
>
> //windows tcc compile
> //tcc -o anagrams.exe anagrams.c
>
> //usage
> //anagrams wordlist.txt searchword
>
> //vars
> int i=0, j=0, k=0;
> int primes[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
> 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};
> char *charset = "abcdefghijklmnopqrstuvwxyz";
>
> LARGE_INTEGER frequency,start,end;
>
> //build struct
> struct words {char *word; double wordpf;};
> struct words **wordrec = NULL;
>
>
> //program timing
> double elapsedtime(LARGE_INTEGER startingtimer)
> {
> QueryPerformanceCounter(&end);
> return (end.QuadPart - startingtimer.QuadPart) /
> (double)frequency.QuadPart;
> }
>
> //compute product of primes corresponding to the letters of the input word
> double calcpf(char *str, int len) {
> double pf = 1;
> for(i=0;i<len;i++) {
> pf *= primes[(int)(strchr(charset, str[i]) - charset)];
> }
> return pf;
> }
>
> //trim trailing spaces
> void righttrim(char *str, int len) {
> while(len>0 && isspace(str[len-1])){
> len--;
> }
> str[len] = '\0';
> }
>
> //sort structure by prime factors, then word
> int comparepf(const void *p1, const void *p2)
> {
> const struct words *a = p1;
> const struct words *b = p2;
> //printf("%.0lf %.0lf\n",a->wordpf,b->wordpf);
> if(a->wordpf > b->wordpf)
> return 1;
> else if (a->wordpf < b->wordpf)
> return -1;
> else
> return 0;
> }
>
>
> int main(int argc, char *argv[])
> {
>
> QueryPerformanceFrequency(&frequency);
>
> printf("\nloading data...");
>
> //read in list of words, load into struct
> int wordcnt = 0;
> char wordin[30];
> char *filein = argv[1];
> char *searchword = argv[2];
> FILE *fwords;
>
> QueryPerformanceCounter(&start);
> fwords = fopen(filein,"r");
> while(fgets(wordin,sizeof(wordin),fwords)!=NULL) {
>
> //trim trailing spaces
> righttrim(wordin,strlen(wordin));
>
> //memory
> wordrec = (struct words **)realloc(wordrec,(wordcnt+1) * sizeof(struct
> words *));
> wordrec[wordcnt] = (struct words *)malloc(sizeof(struct words));
> wordrec[wordcnt]->word = malloc(strlen(wordin)+1);
>
> //add entry to struct
> strcpy(wordrec[wordcnt]->word, wordin);
> wordrec[wordcnt]->wordpf = calcpf(wordin, strlen(wordin));
> wordcnt++;
> }
> printf("\n%.4fs to load %d words\n\n",elapsedtime(start),wordcnt);
>
> printf("Contents of struct (word, pf)\n");
> for(i=0;i<wordcnt;i++) {
> if(i<10 || i>(wordcnt-11)) {
> printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
> wordrec[i]->wordpf);
> }
> }
>
>
> //for fastest search, sort the struct by prime factorization, then word
> //https://stackoverflow.com/search?q=sort+array+of+structs
> printf("\nsorting by prime factor...\n");
> QueryPerformanceCounter(&start);
> qsort(struct wordrec, wordcnt, sizeof(struct wordrec), comparepf);
> printf("%.4fs to qsort on prime factors\n\n",elapsedtime(start));
>
> printf("Contents of sorted struct (word, pf)\n");
> for(i=0;i<wordcnt;i++) {
> if(i<10 || i>(wordcnt-11)) {
> printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
> wordrec[i]->wordpf);
> }
> }
>
>
> //find single-word anagrams
> //Two comparisons have to be made, but only do 2 if 1 is a match:
> //1. compare the prime factorizations (numerical comparison)
> //2. compare the word itself
> printf("\nSearching for anagrams of '%s'...\n",searchword);
> double searchpf = calcpf(searchword, strlen(searchword));
> char *dataword = NULL;
> j=0;
>
> QueryPerformanceCounter(&start);
> for(i=0;i<wordcnt;i++) {
> if(wordrec[i]->wordpf==searchpf) {
> dataword = malloc(strlen(wordrec[i]->word)+1);
> strcpy(dataword,wordrec[i]->word);
> if(strcmp(dataword,searchword)!=0)
> {
> printf("%s ",dataword);
> j++;
> }
> }
> }
>
> if(j>0) {printf("\n%d anagram(s) found in %.4fs\n",j,elapsedtime(start));}
> if(j==0) {printf("No anagrams found\n");}
>
>
>
>
> //finish
> //free(wordincopy);
> free(wordrec);
> fclose(fwords);
> printf("Done");
> exit(0);
> }
> ===========================================================
One can sort object (specifically, array). It's impossible to sort *type*.
The correct syntax in your case is:
qsort(wordrec, wordcnt, sizeof(struct words), comparepf);
Sorting by wordpf as primary key and word as secondary key:
int comparepf1(const void *p1, const void *p2)
{
const struct words *a = p1;
const struct words *b = p2;
if (a->wordpf == b->wordpf)
return strcmp(a->word, b->word);
return a->wordpf < b->wordpf ? -1 : 1;
}
But in practice it's unlikely to work because floating-point rarely produces an exact equality.
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-19 17:24 -0400 |
| Message-ID | <wbLqF.74859$pe2.47975@fx34.iad> |
| In reply to | #147090 |
On 10/19/2019 4:51 PM, already5chosen@yahoo.com wrote:
> On Saturday, October 19, 2019 at 11:27:22 PM UTC+3, DFS wrote:
>> On 10/19/2019 4:09 PM, already5chosen@yahoo.com wrote:
>>> On Saturday, October 19, 2019 at 10:41:27 PM UTC+3, DFS wrote:
>>>> On 10/19/2019 3:09 PM, Ike Naar wrote:
>>>>> On 2019-10-19, DFS <nospam@dfs.com> wrote:
>>>>>> struct words {char *word; double calc;};
>>>>>>
>>>>>> I tried:
>>>>>> qsort(words, wordcnt, sizeof(words), compare);
>>>>>>
>>>>>> The tcc compiler throws an error: 'words' undeclared
>>>>>
>>>>> The type is named "struct words", not "words".
>>>>
>>>>
>>>> error: identifier expected
>>>
>>> It does not sound like you know 'C'.
>>> I recommend to spend several days (or a little more) with books and tutorials. It's may be boring, but worth it.
>>
>>
>> Books and tutorials won't help.
>
> How do you know if you never tried?
> Learning thing on stack overflow only works when you have a basic knowledge.
> Robert Sheckley was absolutely spot on in his classic.
> http://www.gutenberg.org/files/33854/33854-h/33854-h.htm
"In order to ask a question you must already know most of the answer"
haha...
Well, in this case the qsort() prototype confused me
>> I've spent hours on stack overflow
>> trying to figure out how to qsort an array of structs. It's a common
>> question out there.
>>
>> I actually want to sort the data first by the number field, then by the
>> char field. But I'll be happy if I can sort by just the number field.
>>
>> Here's the program as it stands, which works great except for
>> this sorting issue. You can test it by using words_alpha.txt from
>> https://github.com/dwyl/english-words
>>
>> =============================================================
>> #include <stdlib.h>
>> #include <stdio.h>
>> #include <string.h>
>> #include <time.h>
>> #include <Windows.h>
>>
>> //windows tcc compile
>> //tcc -o anagrams.exe anagrams.c
>>
>> //usage
>> //anagrams wordlist.txt searchword
>>
>> //vars
>> int i=0, j=0, k=0;
>> int primes[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
>> 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};
>> char *charset = "abcdefghijklmnopqrstuvwxyz";
>>
>> LARGE_INTEGER frequency,start,end;
>>
>> //build struct
>> struct words {char *word; double wordpf;};
>> struct words **wordrec = NULL;
>>
>>
>> //program timing
>> double elapsedtime(LARGE_INTEGER startingtimer)
>> {
>> QueryPerformanceCounter(&end);
>> return (end.QuadPart - startingtimer.QuadPart) /
>> (double)frequency.QuadPart;
>> }
>>
>> //compute product of primes corresponding to the letters of the input word
>> double calcpf(char *str, int len) {
>> double pf = 1;
>> for(i=0;i<len;i++) {
>> pf *= primes[(int)(strchr(charset, str[i]) - charset)];
>> }
>> return pf;
>> }
>>
>> //trim trailing spaces
>> void righttrim(char *str, int len) {
>> while(len>0 && isspace(str[len-1])){
>> len--;
>> }
>> str[len] = '\0';
>> }
>>
>> //sort structure by prime factors, then word
>> int comparepf(const void *p1, const void *p2)
>> {
>> const struct words *a = p1;
>> const struct words *b = p2;
>> //printf("%.0lf %.0lf\n",a->wordpf,b->wordpf);
>> if(a->wordpf > b->wordpf)
>> return 1;
>> else if (a->wordpf < b->wordpf)
>> return -1;
>> else
>> return 0;
>> }
>>
>>
>> int main(int argc, char *argv[])
>> {
>>
>> QueryPerformanceFrequency(&frequency);
>>
>> printf("\nloading data...");
>>
>> //read in list of words, load into struct
>> int wordcnt = 0;
>> char wordin[30];
>> char *filein = argv[1];
>> char *searchword = argv[2];
>> FILE *fwords;
>>
>> QueryPerformanceCounter(&start);
>> fwords = fopen(filein,"r");
>> while(fgets(wordin,sizeof(wordin),fwords)!=NULL) {
>>
>> //trim trailing spaces
>> righttrim(wordin,strlen(wordin));
>>
>> //memory
>> wordrec = (struct words **)realloc(wordrec,(wordcnt+1) * sizeof(struct
>> words *));
>> wordrec[wordcnt] = (struct words *)malloc(sizeof(struct words));
>> wordrec[wordcnt]->word = malloc(strlen(wordin)+1);
>>
>> //add entry to struct
>> strcpy(wordrec[wordcnt]->word, wordin);
>> wordrec[wordcnt]->wordpf = calcpf(wordin, strlen(wordin));
>> wordcnt++;
>> }
>> printf("\n%.4fs to load %d words\n\n",elapsedtime(start),wordcnt);
>>
>> printf("Contents of struct (word, pf)\n");
>> for(i=0;i<wordcnt;i++) {
>> if(i<10 || i>(wordcnt-11)) {
>> printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
>> wordrec[i]->wordpf);
>> }
>> }
>>
>>
>> //for fastest search, sort the struct by prime factorization, then word
>> //https://stackoverflow.com/search?q=sort+array+of+structs
>> printf("\nsorting by prime factor...\n");
>> QueryPerformanceCounter(&start);
>> qsort(struct wordrec, wordcnt, sizeof(struct wordrec), comparepf);
>> printf("%.4fs to qsort on prime factors\n\n",elapsedtime(start));
>>
>> printf("Contents of sorted struct (word, pf)\n");
>> for(i=0;i<wordcnt;i++) {
>> if(i<10 || i>(wordcnt-11)) {
>> printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
>> wordrec[i]->wordpf);
>> }
>> }
>>
>>
>> //find single-word anagrams
>> //Two comparisons have to be made, but only do 2 if 1 is a match:
>> //1. compare the prime factorizations (numerical comparison)
>> //2. compare the word itself
>> printf("\nSearching for anagrams of '%s'...\n",searchword);
>> double searchpf = calcpf(searchword, strlen(searchword));
>> char *dataword = NULL;
>> j=0;
>>
>> QueryPerformanceCounter(&start);
>> for(i=0;i<wordcnt;i++) {
>> if(wordrec[i]->wordpf==searchpf) {
>> dataword = malloc(strlen(wordrec[i]->word)+1);
>> strcpy(dataword,wordrec[i]->word);
>> if(strcmp(dataword,searchword)!=0)
>> {
>> printf("%s ",dataword);
>> j++;
>> }
>> }
>> }
>>
>> if(j>0) {printf("\n%d anagram(s) found in %.4fs\n",j,elapsedtime(start));}
>> if(j==0) {printf("No anagrams found\n");}
>>
>>
>>
>>
>> //finish
>> //free(wordincopy);
>> free(wordrec);
>> fclose(fwords);
>> printf("Done");
>> exit(0);
>> }
>> ===========================================================
>
>
> One can sort object (specifically, array). It's impossible to sort *type*.
> The correct syntax in your case is:
>
> qsort(wordrec, wordcnt, sizeof(struct words), comparepf);
"The qsort() function sorts an array with nmemb elements of size size."
https://linux.die.net/man/3/qsort
You passed an array and the sizeof the struct, not the sizeof the array.
That doesn't make sense to me.
And it doesn't work. The first iteration of qsort() shows the wordpf
values as 0 and 0.
Then it throws WindowsException code c0000005 is the code for an access
violation. That means that your program is accessing (either reading or
writing) a memory address to which it does not have rights. Most
commonly this is caused by:
Accessing a stale pointer. That is accessing memory that has already
been deallocated. Note that such stale pointer accesses do not always
result in access violations. Only if the memory manager has returned the
memory to the system do you get an access violation.
Reading off the end of an array. This is when you have an array of
length N and you access elements with index >=N.
> Sorting by wordpf as primary key and word as secondary key:
>
> int comparepf1(const void *p1, const void *p2)
> {
> const struct words *a = p1;
> const struct words *b = p2;
> if (a->wordpf == b->wordpf)
> return strcmp(a->word, b->word);
> return a->wordpf < b->wordpf ? -1 : 1;
> }
>
> But in practice it's unlikely to work because floating-point rarely produces an exact equality.
>
Not sure why I ended up with doubles (floating points not necessary
here). I think I tried to use long long int and had some problem. I'll
try again.
Thanks for your help, chosen. I feel like I'm close.
[toc] | [prev] | [next] | [standalone]
| From | already5chosen@yahoo.com |
|---|---|
| Date | 2019-10-19 14:49 -0700 |
| Message-ID | <1ca42f72-9e0e-40c3-8ef0-b5002e079cef@googlegroups.com> |
| In reply to | #147092 |
On Sunday, October 20, 2019 at 12:25:57 AM UTC+3, DFS wrote:
> On 10/19/2019 4:51 PM, already5chosen@yahoo.com wrote:
> > On Saturday, October 19, 2019 at 11:27:22 PM UTC+3, DFS wrote:
> >> On 10/19/2019 4:09 PM, already5chosen@yahoo.com wrote:
> >>> On Saturday, October 19, 2019 at 10:41:27 PM UTC+3, DFS wrote:
> >>>> On 10/19/2019 3:09 PM, Ike Naar wrote:
> >>>>> On 2019-10-19, DFS <nospam@dfs.com> wrote:
> >>>>>> struct words {char *word; double calc;};
> >>>>>>
> >>>>>> I tried:
> >>>>>> qsort(words, wordcnt, sizeof(words), compare);
> >>>>>>
> >>>>>> The tcc compiler throws an error: 'words' undeclared
> >>>>>
> >>>>> The type is named "struct words", not "words".
> >>>>
> >>>>
> >>>> error: identifier expected
> >>>
> >>> It does not sound like you know 'C'.
> >>> I recommend to spend several days (or a little more) with books and tutorials. It's may be boring, but worth it.
> >>
> >>
> >> Books and tutorials won't help.
> >
> > How do you know if you never tried?
> > Learning thing on stack overflow only works when you have a basic knowledge.
> > Robert Sheckley was absolutely spot on in his classic.
> > http://www.gutenberg.org/files/33854/33854-h/33854-h.htm
>
>
> "In order to ask a question you must already know most of the answer"
>
> haha...
>
> Well, in this case the qsort() prototype confused me
>
>
>
> >> I've spent hours on stack overflow
> >> trying to figure out how to qsort an array of structs. It's a common
> >> question out there.
> >>
> >> I actually want to sort the data first by the number field, then by the
> >> char field. But I'll be happy if I can sort by just the number field.
> >>
> >> Here's the program as it stands, which works great except for
> >> this sorting issue. You can test it by using words_alpha.txt from
> >> https://github.com/dwyl/english-words
> >>
> >> =============================================================
> >> #include <stdlib.h>
> >> #include <stdio.h>
> >> #include <string.h>
> >> #include <time.h>
> >> #include <Windows.h>
> >>
> >> //windows tcc compile
> >> //tcc -o anagrams.exe anagrams.c
> >>
> >> //usage
> >> //anagrams wordlist.txt searchword
> >>
> >> //vars
> >> int i=0, j=0, k=0;
> >> int primes[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
> >> 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};
> >> char *charset = "abcdefghijklmnopqrstuvwxyz";
> >>
> >> LARGE_INTEGER frequency,start,end;
> >>
> >> //build struct
> >> struct words {char *word; double wordpf;};
> >> struct words **wordrec = NULL;
> >>
> >>
> >> //program timing
> >> double elapsedtime(LARGE_INTEGER startingtimer)
> >> {
> >> QueryPerformanceCounter(&end);
> >> return (end.QuadPart - startingtimer.QuadPart) /
> >> (double)frequency.QuadPart;
> >> }
> >>
> >> //compute product of primes corresponding to the letters of the input word
> >> double calcpf(char *str, int len) {
> >> double pf = 1;
> >> for(i=0;i<len;i++) {
> >> pf *= primes[(int)(strchr(charset, str[i]) - charset)];
> >> }
> >> return pf;
> >> }
> >>
> >> //trim trailing spaces
> >> void righttrim(char *str, int len) {
> >> while(len>0 && isspace(str[len-1])){
> >> len--;
> >> }
> >> str[len] = '\0';
> >> }
> >>
> >> //sort structure by prime factors, then word
> >> int comparepf(const void *p1, const void *p2)
> >> {
> >> const struct words *a = p1;
> >> const struct words *b = p2;
> >> //printf("%.0lf %.0lf\n",a->wordpf,b->wordpf);
> >> if(a->wordpf > b->wordpf)
> >> return 1;
> >> else if (a->wordpf < b->wordpf)
> >> return -1;
> >> else
> >> return 0;
> >> }
> >>
> >>
> >> int main(int argc, char *argv[])
> >> {
> >>
> >> QueryPerformanceFrequency(&frequency);
> >>
> >> printf("\nloading data...");
> >>
> >> //read in list of words, load into struct
> >> int wordcnt = 0;
> >> char wordin[30];
> >> char *filein = argv[1];
> >> char *searchword = argv[2];
> >> FILE *fwords;
> >>
> >> QueryPerformanceCounter(&start);
> >> fwords = fopen(filein,"r");
> >> while(fgets(wordin,sizeof(wordin),fwords)!=NULL) {
> >>
> >> //trim trailing spaces
> >> righttrim(wordin,strlen(wordin));
> >>
> >> //memory
> >> wordrec = (struct words **)realloc(wordrec,(wordcnt+1) * sizeof(struct
> >> words *));
> >> wordrec[wordcnt] = (struct words *)malloc(sizeof(struct words));
> >> wordrec[wordcnt]->word = malloc(strlen(wordin)+1);
> >>
> >> //add entry to struct
> >> strcpy(wordrec[wordcnt]->word, wordin);
> >> wordrec[wordcnt]->wordpf = calcpf(wordin, strlen(wordin));
> >> wordcnt++;
> >> }
> >> printf("\n%.4fs to load %d words\n\n",elapsedtime(start),wordcnt);
> >>
> >> printf("Contents of struct (word, pf)\n");
> >> for(i=0;i<wordcnt;i++) {
> >> if(i<10 || i>(wordcnt-11)) {
> >> printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
> >> wordrec[i]->wordpf);
> >> }
> >> }
> >>
> >>
> >> //for fastest search, sort the struct by prime factorization, then word
> >> //https://stackoverflow.com/search?q=sort+array+of+structs
> >> printf("\nsorting by prime factor...\n");
> >> QueryPerformanceCounter(&start);
> >> qsort(struct wordrec, wordcnt, sizeof(struct wordrec), comparepf);
> >> printf("%.4fs to qsort on prime factors\n\n",elapsedtime(start));
> >>
> >> printf("Contents of sorted struct (word, pf)\n");
> >> for(i=0;i<wordcnt;i++) {
> >> if(i<10 || i>(wordcnt-11)) {
> >> printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
> >> wordrec[i]->wordpf);
> >> }
> >> }
> >>
> >>
> >> //find single-word anagrams
> >> //Two comparisons have to be made, but only do 2 if 1 is a match:
> >> //1. compare the prime factorizations (numerical comparison)
> >> //2. compare the word itself
> >> printf("\nSearching for anagrams of '%s'...\n",searchword);
> >> double searchpf = calcpf(searchword, strlen(searchword));
> >> char *dataword = NULL;
> >> j=0;
> >>
> >> QueryPerformanceCounter(&start);
> >> for(i=0;i<wordcnt;i++) {
> >> if(wordrec[i]->wordpf==searchpf) {
> >> dataword = malloc(strlen(wordrec[i]->word)+1);
> >> strcpy(dataword,wordrec[i]->word);
> >> if(strcmp(dataword,searchword)!=0)
> >> {
> >> printf("%s ",dataword);
> >> j++;
> >> }
> >> }
> >> }
> >>
> >> if(j>0) {printf("\n%d anagram(s) found in %.4fs\n",j,elapsedtime(start));}
> >> if(j==0) {printf("No anagrams found\n");}
> >>
> >>
> >>
> >>
> >> //finish
> >> //free(wordincopy);
> >> free(wordrec);
> >> fclose(fwords);
> >> printf("Done");
> >> exit(0);
> >> }
> >> ===========================================================
> >
> >
> > One can sort object (specifically, array). It's impossible to sort *type*.
> > The correct syntax in your case is:
> >
> > qsort(wordrec, wordcnt, sizeof(struct words), comparepf);
>
>
> "The qsort() function sorts an array with nmemb elements of size size."
> https://linux.die.net/man/3/qsort
>
This man page is not very well written.
This one is better:
http://www.cplusplus.com/reference/cstdlib/qsort/
Or that:
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort?view=vs-2019
But even your man page contains the required info, just read it slowly: "an array with nmemb elements of size size".
The 3rd parameter is a size of *one element* rather than of the whole array.
In your case it can be expressed as sizeof(struct words) or sizeof(*wordrec) or sizeof(wordrec[0]).
Personally, I prefer the 3rd variant, but it is a matter of individual taste. All three variants should work.
> You passed an array and the sizeof the struct, not the sizeof the array.
>
> That doesn't make sense to me.
>
> And it doesn't work. The first iteration of qsort() shows the wordpf
> values as 0 and 0.
>
Well, I don't know what do you expect to see so can't comment.
> Then it throws WindowsException code c0000005 is the code for an access
> violation. That means that your program is accessing (either reading or
> writing) a memory address to which it does not have rights. Most
> commonly this is caused by:
>
> Accessing a stale pointer. That is accessing memory that has already
> been deallocated. Note that such stale pointer accesses do not always
> result in access violations. Only if the memory manager has returned the
> memory to the system do you get an access violation.
> Reading off the end of an array. This is when you have an array of
> length N and you access elements with index >=N.
>
>
>
>
> > Sorting by wordpf as primary key and word as secondary key:
> >
> > int comparepf1(const void *p1, const void *p2)
> > {
> > const struct words *a = p1;
> > const struct words *b = p2;
> > if (a->wordpf == b->wordpf)
> > return strcmp(a->word, b->word);
> > return a->wordpf < b->wordpf ? -1 : 1;
> > }
> >
> > But in practice it's unlikely to work because floating-point rarely produces an exact equality.
> >
>
> Not sure why I ended up with doubles (floating points not necessary
> here). I think I tried to use long long int and had some problem. I'll
> try again.
>
> Thanks for your help, chosen. I feel like I'm close.
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-19 18:26 -0400 |
| Message-ID | <l5MqF.242244$iJ2.110801@fx47.iad> |
| In reply to | #147093 |
On 10/19/2019 5:49 PM, already5chosen@yahoo.com wrote:
> On Sunday, October 20, 2019 at 12:25:57 AM UTC+3, DFS wrote:
>>>
>>> One can sort object (specifically, array). It's impossible to sort *type*.
>>> The correct syntax in your case is:
>>>
>>> qsort(wordrec, wordcnt, sizeof(struct words), comparepf);
>>
>>
>> "The qsort() function sorts an array with nmemb elements of size size."
>> https://linux.die.net/man/3/qsort
>>
>
> This man page is not very well written.
> This one is better:
> http://www.cplusplus.com/reference/cstdlib/qsort/
> Or that:
> https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort?view=vs-2019
>
>
> But even your man page contains the required info, just read it slowly: "an array with nmemb elements of size size".
> The 3rd parameter is a size of *one element* rather than of the whole array.
> In your case it can be expressed as sizeof(struct words) or sizeof(*wordrec) or sizeof(wordrec[0]).
> Personally, I prefer the 3rd variant, but it is a matter of individual taste. All three variants should work.
>
>
>> You passed an array and the sizeof the struct, not the sizeof the array.
>>
>> That doesn't make sense to me.
>>
>> And it doesn't work. The first iteration of qsort() shows the wordpf
>> values as 0 and 0.
>>
>
> Well, I don't know what do you expect to see so can't comment.
I expect to see words, and wordpf values > 0.
with qsort(wordrec, wordcnt, sizeof(wordrec[0]), comparepf);
I get comparison data like this:
printf("%lld %lld\n",a->wordpf,b->wordpf);
printf("%s %s\n",a->word,b->word);
5706976 61382032
└¶W ╨¢¿♥
5706976 0
└¶W └▬a♦
61382032 0
╨¢¿♥ └¶W
5706880 61382032
└¶W
5707040 61382032
@§W └¶W
5707104 61382032
ɧW └¶W
5707184 61382032
α§W └¶W
...
And it's not sorting, even if I remove the strcmp() in the compare
function.
Contents of struct (word, pf)
0. a 2
1. aa 4
2. aaa 8
3. aah 76
4. aahed 5852
5. aahing 1277788
6. aahs 5092
7. aal 148
8. aalii 78292
9. aaliis 5245564
370096. zwanziger 19103747476418
370097. zwieback 1972436070
370098. zwiebacks 132153216690
370099. zwieselite 1038886419549253
370100. zwinglian 10315082135494
370101. zwinglianism 651717204402646414
370102. zwinglianist 1128583451526534034
370103. zwitter 652178563399
370104. zwitterion 30315216162475717
370105. zwitterionic 3486249858684707455
sorting by prime factor...
0.1225s to qsort on prime factors
Contents of sorted struct (word, pf)
0. aa 4
1. zwitterionic 3486249858684707455
2. aaa 8
3. aah 76
4. aahed 5852
5. aahing 1277788
6. aaliis 5245564
7. aahs 5092
8. aal 148
9. aals 9916
370096. zoonosology 4071704963907151271
370097. zootaxy 273506199574
370098. zootaxonomist 2408189718480815814
370099. zygodactylae 3071796316291780
370100. zonal 15104954
370101. zoonotic 3681625354685
370102. zygodactylism 8821780139074134190
370103. zygopterid 3182163587115359
370104. zygopterous 4543516887672778763
370105. zygosporangium -3857035110672614842
[toc] | [prev] | [next] | [standalone]
| From | already5chosen@yahoo.com |
|---|---|
| Date | 2019-10-19 16:32 -0700 |
| Message-ID | <07784ff9-2fee-49e6-8271-22d713294245@googlegroups.com> |
| In reply to | #147096 |
On Sunday, October 20, 2019 at 1:27:37 AM UTC+3, DFS wrote:
> On 10/19/2019 5:49 PM, already5chosen@yahoo.com wrote:
> > On Sunday, October 20, 2019 at 12:25:57 AM UTC+3, DFS wrote:
>
> >>>
> >>> One can sort object (specifically, array). It's impossible to sort *type*.
> >>> The correct syntax in your case is:
> >>>
> >>> qsort(wordrec, wordcnt, sizeof(struct words), comparepf);
> >>
> >>
> >> "The qsort() function sorts an array with nmemb elements of size size."
> >> https://linux.die.net/man/3/qsort
> >>
> >
> > This man page is not very well written.
> > This one is better:
> > http://www.cplusplus.com/reference/cstdlib/qsort/
> > Or that:
> > https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort?view=vs-2019
> >
> >
> > But even your man page contains the required info, just read it slowly: "an array with nmemb elements of size size".
> > The 3rd parameter is a size of *one element* rather than of the whole array.
> > In your case it can be expressed as sizeof(struct words) or sizeof(*wordrec) or sizeof(wordrec[0]).
> > Personally, I prefer the 3rd variant, but it is a matter of individual taste. All three variants should work.
> >
> >
> >> You passed an array and the sizeof the struct, not the sizeof the array.
> >>
> >> That doesn't make sense to me.
> >>
> >> And it doesn't work. The first iteration of qsort() shows the wordpf
> >> values as 0 and 0.
> >>
> >
> > Well, I don't know what do you expect to see so can't comment.
>
>
> I expect to see words, and wordpf values > 0.
>
> with qsort(wordrec, wordcnt, sizeof(wordrec[0]), comparepf);
>
> I get comparison data like this:
>
> printf("%lld %lld\n",a->wordpf,b->wordpf);
> printf("%s %s\n",a->word,b->word);
>
>
> 5706976 61382032
> └¶W ╨¢¿♥
> 5706976 0
> └¶W └▬a♦
> 61382032 0
> ╨¢¿♥ └¶W
> 5706880 61382032
> └¶W
> 5707040 61382032
> @§W └¶W
> 5707104 61382032
> ɧW └¶W
> 5707184 61382032
> α§W └¶W
> ...
>
>
>
> And it's not sorting, even if I remove the strcmp() in the compare
> function.
>
> Contents of struct (word, pf)
> 0. a 2
> 1. aa 4
> 2. aaa 8
> 3. aah 76
> 4. aahed 5852
> 5. aahing 1277788
> 6. aahs 5092
> 7. aal 148
> 8. aalii 78292
> 9. aaliis 5245564
> 370096. zwanziger 19103747476418
> 370097. zwieback 1972436070
> 370098. zwiebacks 132153216690
> 370099. zwieselite 1038886419549253
> 370100. zwinglian 10315082135494
> 370101. zwinglianism 651717204402646414
> 370102. zwinglianist 1128583451526534034
> 370103. zwitter 652178563399
> 370104. zwitterion 30315216162475717
> 370105. zwitterionic 3486249858684707455
>
> sorting by prime factor...
> 0.1225s to qsort on prime factors
>
> Contents of sorted struct (word, pf)
> 0. aa 4
> 1. zwitterionic 3486249858684707455
> 2. aaa 8
> 3. aah 76
> 4. aahed 5852
> 5. aahing 1277788
> 6. aaliis 5245564
> 7. aahs 5092
> 8. aal 148
> 9. aals 9916
> 370096. zoonosology 4071704963907151271
> 370097. zootaxy 273506199574
> 370098. zootaxonomist 2408189718480815814
> 370099. zygodactylae 3071796316291780
> 370100. zonal 15104954
> 370101. zoonotic 3681625354685
> 370102. zygodactylism 8821780139074134190
> 370103. zygopterid 3182163587115359
> 370104. zygopterous 4543516887672778763
> 370105. zygosporangium -3857035110672614842
o.k. I don't know why, but I read your code.
Turned out, you don't have an array of records. For some reason, you decided to build an array of pointers to records. That's quite different!
Your comparison function should take that into account and to use double indirection, like that:
int comparepf(const void *p1, const void *p2)
{
const struct words *a = *(const struct words **)p1;
const struct words *b = *(const struct words **)p2;
if (a->wordpf == b->wordpf)
return strcmp(a->word, b->word);
return a->wordpf < b->wordpf ? -1 : 1;
}
BTW, I repeat my advice from above. Your code looks very non-idiomatic, very script-kidddish.
Tutorial can help.
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-20 09:22 -0400 |
| Message-ID | <bdZqF.216192$TC2.20635@fx43.iad> |
| In reply to | #147099 |
On 10/19/2019 7:32 PM, already5chosen@yahoo.com wrote:
> On Sunday, October 20, 2019 at 1:27:37 AM UTC+3, DFS wrote:
> o.k. I don't know why, but I read your code.
> Turned out, you don't have an array of records. For some reason, you decided to build an array of pointers to records. That's quite different!
> Your comparison function should take that into account and to use double indirection, like that:
>
> int comparepf(const void *p1, const void *p2)
> {
> const struct words *a = *(const struct words **)p1;
> const struct words *b = *(const struct words **)p2;
> if (a->wordpf == b->wordpf)
> return strcmp(a->word, b->word);
> return a->wordpf < b->wordpf ? -1 : 1;
> }
The qsort now works.
Thanks!
> BTW, I repeat my advice from above. Your code looks very non-idiomatic, very script-kidddish.
> Tutorial can help.
Exactly which lines look 'script-kiddish'? How would you improve them?
original code in this thread
========================================================================
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <time.h>
5 #include <Windows.h>
6
7 //windows tcc compile
8 //tcc -o anagrams.exe anagrams.c
9
10 //usage
11 //anagrams wordlist.txt searchword
12
13 //vars
14 int i=0, j=0, k=0;
15 int primes[26] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
16 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101};
17 char *charset = "abcdefghijklmnopqrstuvwxyz";
18
19 LARGE_INTEGER frequency,start,end;
20
21 //build struct
22 struct words {char *word; double wordpf;};
23 struct words **wordrec = NULL;
24
25
26 //program timing
27 double elapsedtime(LARGE_INTEGER startingtimer)
28 {
29 QueryPerformanceCounter(&end);
30 return (end.QuadPart - startingtimer.QuadPart) /
(double)frequency.QuadPart;
31 }
32
33 //compute product of primes corresponding to the letters of the
input word
34 double calcpf(char *str, int len) {
35 double pf = 1;
36 for(i=0;i<len;i++) {
37 pf *= primes[(int)(strchr(charset, str[i]) - charset)];
38 }
39 return pf;
40 }
41
42 //trim trailing spaces
43 void righttrim(char *str, int len) {
44 while(len>0 && isspace(str[len-1])){
45 len--;
46 }
47 str[len] = '\0';
48 }
49
50 //sort structure by prime factors, then word
51 int comparepf(const void *p1, const void *p2)
52 {
53 const struct words *a = p1;
54 const struct words *b = p2;
55 //printf("%.0lf %.0lf\n",a->wordpf,b->wordpf);
56 if(a->wordpf > b->wordpf)
57 return 1;
58 else if (a->wordpf < b->wordpf)
59 return -1;
60 else
61 return 0;
62 }
63
64
65 int main(int argc, char *argv[])
66 {
67
68 QueryPerformanceFrequency(&frequency);
69
70 printf("\nloading data...");
71
72 //read in list of words, load into struct
73 int wordcnt = 0;
74 char wordin[30];
75 char *filein = argv[1];
76 char *searchword = argv[2];
77 FILE *fwords;
78
79 QueryPerformanceCounter(&start);
80 fwords = fopen(filein,"r");
81 while(fgets(wordin,sizeof(wordin),fwords)!=NULL) {
82
83 //trim trailing spaces
84 righttrim(wordin,strlen(wordin));
85
86 //memory
87 wordrec = (struct words **)realloc(wordrec,(wordcnt+1) *
sizeof(struct words *));
88 wordrec[wordcnt] = (struct words *)malloc(sizeof(struct
words));
89 wordrec[wordcnt]->word = malloc(strlen(wordin)+1);
90
91 //add entry to struct
92 strcpy(wordrec[wordcnt]->word, wordin);
93 wordrec[wordcnt]->wordpf = calcpf(wordin, strlen(wordin));
94 wordcnt++;
95 }
96 printf("\n%.4fs to load %d words\n\n",elapsedtime(start),wordcnt);
97
98 printf("Contents of struct (word, pf)\n");
99 for(i=0;i<wordcnt;i++) {
100 if(i<10 || i>(wordcnt-11)) {
101 printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
wordrec[i]->wordpf);
102 }
103 }
104
105
106 //for fastest search, sort the struct by prime factorization,
then word
107 //https://stackoverflow.com/search?q=sort+array+of+structs
108 printf("\nsorting by prime factor...\n");
109 QueryPerformanceCounter(&start);
110 qsort(struct wordrec, wordcnt, sizeof(struct wordrec), comparepf);
111 printf("%.4fs to qsort on prime factors\n\n",elapsedtime(start));
112
113 printf("Contents of sorted struct (word, pf)\n");
114 for(i=0;i<wordcnt;i++) {
115 if(i<10 || i>(wordcnt-11)) {
116 printf("%d. %-18s %-18.0lf\n",i, wordrec[i]->word,
wordrec[i]->wordpf);
117 }
118 }
119
120
121 //find single-word anagrams
122 //Two comparisons have to be made, but only do 2 if 1 is a match:
123 //1. compare the prime factorizations (numerical comparison)
124 //2. compare the word itself
125 printf("\nSearching for anagrams of '%s'...\n",searchword);
126 double searchpf = calcpf(searchword, strlen(searchword));
127 char *dataword = NULL;
128 j=0;
129
130 QueryPerformanceCounter(&start);
131 for(i=0;i<wordcnt;i++) {
132 if(wordrec[i]->wordpf==searchpf) {
133 dataword = malloc(strlen(wordrec[i]->word)+1);
134 strcpy(dataword,wordrec[i]->word);
135 if(strcmp(dataword,searchword)!=0)
136 {
137 printf("%s ",dataword);
138 j++;
139 }
140 }
141 }
142
143 if(j>0) {printf("\n%d anagram(s) found in
%.4fs\n",j,elapsedtime(start));}
144 if(j==0) {printf("No anagrams found\n");}
145
146
147
148
149 //finish
150 //free(wordincopy);
151 free(wordrec);
152 fclose(fwords);
153 printf("Done");
154 exit(0);
155 }
========================================================================
[toc] | [prev] | [next] | [standalone]
| From | Paul <nospam@needed.invalid> |
|---|---|
| Date | 2019-10-26 04:15 -0400 |
| Message-ID | <qp0vbg$672$1@gioia.aioe.org> |
| In reply to | #147113 |
DFS wrote:
> On 10/19/2019 7:32 PM, already5chosen@yahoo.com wrote:
>> On Sunday, October 20, 2019 at 1:27:37 AM UTC+3, DFS wrote:
>
>
>> o.k. I don't know why, but I read your code.
>> Turned out, you don't have an array of records. For some reason, you
>> decided to build an array of pointers to records. That's quite different!
>> Your comparison function should take that into account and to use
>> double indirection, like that:
>>
>> int comparepf(const void *p1, const void *p2)
>> {
>> const struct words *a = *(const struct words **)p1;
>> const struct words *b = *(const struct words **)p2;
>> if (a->wordpf == b->wordpf)
>> return strcmp(a->word, b->word);
>> return a->wordpf < b->wordpf ? -1 : 1;
>> }
>
>
> The qsort now works.
>
> Thanks!
I took your code and messed around a bit with it.
For the prime number idea, you can assign the primes
according to letter frequency. The intention being,
to reduce the amount of storage to hold the prime products.
The letter "e" is assigned "2", as it's the most frequent.
dichlorodiphenyltrichloroethane 55812442766843314104001446573936360
And since that "broke" my calculator, I used log2 of all
the prime numbers and addition, to come up with estimates
of the storage requirements for the "worst word", the one shown.
I had to figure out the storage requirements, so I could
figure out how to store the numbers (I wanted to use uint64_t
initially, but they weren't big enough).
regmax = 7564585 for string dichlorodiphenyltrichloroethane
The number is fixed point, and needs to be shifted >>16 to get
the size of register needed. 7564585/65536 = 115.4 or 116 bits,
so two 64 bit uint64_t would do. I multiply together the
primes until one uint64_t is full, then multiply the rest
into a second unit64_t.
I used GMP, and only transferred my two 64 bit accumulators
to GMP when "most" of the multiplies were finished. GMP
lacks 64 bit assignment, so I had to take the 64 bit uint64_t
and shift out a 32 bit quantity and load the GMP variables that
way (I'm doing this on a 32 bit machine). The purpose of not
doing all the multiplies, was to reduce the need to use GMP.
But I wanted to use the mpz_cmp function, rather than write
some nasty if statements using my uint64_t variables instead
(and doing my own multiply code or something). The GMP really
isn't that bad, but it's missing features that would make it
truly useful. The C++ part of it works better, because it
has operator overloading and you can write "natural" looking
code for more of it, than you can write in C.
Once the qsort is done, I used a binary search to find
the start of the (sorted by wordpf) anagram table.
Searching for anagrams of 'now'...
own won
2 anagram(s) found in 0.000070 seconds
*******
This is the output of the slight mod to your code.
The timestamper debug statements were necessary, because
I was getting some corruption in the timestamps, and
I have to leave the raw data there so I can "catch"
the problem if it arises again.
L:\>anagrams2 words_alpha.txt now
loading data...
freq 3005590000
now 1053823553067672 now/freq 350621.193532
freq 3005590000
now 1053823553199207 now/freq 350621.193576
duration 0.000044
dichlorodiphenyltrichloroethane
29 11 41 23 31 7 19 7 29 11 67 23 2 13 53 31 3 19 11 41 23 31 7 19 7 2 3 23 5 13 2
pfhigh = 9490186362596940 pflow = 5881069205006689694
55812442766843314104001446573936360
after loop
freq 3005590000
now 1053824394137112 now/freq 350621.473367
0.2798s to load 370103 words
regmax = 7564585 for string dichlorodiphenyltrichloroethane
variable wordrec is at address: 004080E0
Contents of struct (word, pf)
0. a 5
1. aa 19
2. aaa 7d
3. aah 23f
4. aahed 8246
5. aahing 4c88ad <=== pf dumped in hex
6. aahs 262f
7. aal 307
8. aalii 16e4f
9. aaliis 18533f
370093. zwanziger e83fd0a44e
370094. zwieback 2318f22d22
370095. zwiebacks 254a814ff42
370096. zwieselite 21f939918
370097. zwinglian 10c412b9e29
370098. zwinglianism 20e9eb030ad5d1
370099. zwinglianist 24bdad09597d9
370100. zwitter 156115e
370101. zwitterion 53989e88e
370102. zwitterionic 9345df4b22a
sorting by prime factor...
freq 3005590000
now 1053824400143568 now/freq 350621.475365
freq 3005590000
now 1053825384030732 now/freq 350621.802718
0.3274s to qsort on prime factors
Contents of sorted struct (word, pf)
0. e 2
1. t 3
2. ee 4
3. a 5
4. et 6
5. te 6
6. o 7
7. ae a
8. ea a
9. i b
2377. now 14f9
2378. own 14f9
2379. won 14f9
370093. cyclotrimethylenetrinitramine 1860424ddc7694f6fca00f9630
370094. formaldehydesulphoxylic 1be542f8603bdaf9716edd5e8c
370095. pathologicopsychological 1f7813b27f81f88f6bd73ca9ef
370096. electroencephalographically 5d9c0dac6de2d4b7af0469d810
370097. hydroxydesoxycorticosterone 9061cc85898dcac646dab48e48
370098. trinitrophenylmethylnitramine 913f8dd325653c1599e1f3cb98
370099. microspectrophotometrically 9aba287a31028f4509cc30dd1c
370100. hydroxydehydrocorticosterone 510c71bb0a52f66b6c9ac515218
370101. philosophicopsychological 26b6c1941415142b7b83d64fd613
370102. dichlorodiphenyltrichloroethane abfc410e3f54ff5649a0c76b28ee8
Searching for anagrams of 'now'...
freq 3005590000
now 1053825389785134 now/freq 350621.804632
own won
freq 3005590000
now 1053825389995158 now/freq 350621.804702
2 anagram(s) found in 0.000070s
Done
*******
What was your original bar bet anyway ?
Time to search for a single item, or time for the whole process ?
The binary search seems to be pretty fast. log2(370103)
is about 19 probes or so.
My version is only tuned for the test file,
and isn't as nice as yours. You could, of course,
store the entire word file inside the program, and
eliminate the preprocessing time :-)
Paul
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-26 09:37 -0400 |
| Message-ID | <X%XsF.47310$Ku2.37175@fx41.iad> |
| In reply to | #147238 |
On 10/26/2019 4:15 AM, Paul wrote: > I took your code and messed around a bit with it. <snip> > 370096. electroencephalographically 5d9c0dac6de2d4b7af0469d810 > 370097. hydroxydesoxycorticosterone 9061cc85898dcac646dab48e48 > 370098. trinitrophenylmethylnitramine 913f8dd325653c1599e1f3cb98 > 370099. microspectrophotometrically 9aba287a31028f4509cc30dd1c > 370100. hydroxydehydrocorticosterone 510c71bb0a52f66b6c9ac515218 > 370101. philosophicopsychological 26b6c1941415142b7b83d64fd613 > 370102. dichlorodiphenyltrichloroethane abfc410e3f54ff5649a0c76b28ee8 > > Searching for anagrams of 'now'... > freq 3005590000 > now 1053825389785134 now/freq 350621.804632 > own won > freq 3005590000 > now 1053825389995158 now/freq 350621.804702 > 2 anagram(s) found in 0.000070s > Done > > ******* Interesting thoughts! I've been trying to use gmp (here on Windows) but no luck so far. I did get it installed. > What was your original bar bet anyway ? Well, I was finishing a bottle of Bacardi 151 and web browsing and came across https://wordsmith.org/anagram/ It generated so many anagrams so fast I was blown away. So I went looking for algorithms. The first one I came across was the prime-products, which looked easy to implement. Once I got the code written, I saw how fast it was in C. Sorting the data made it much faster. The hosts of wordsmith.org told me: "Lots of horsepower we put into our server!" > Time to search for a single item, or time for the whole process ? Fastest I got on my old Win8.1 system (i5-750@2.67GHz) is 0.00012 searching for 'cat' Ran it in MSYS2 and it's even faster: Searching for anagrams of 'cat'... act 1 anagram(s) found in 0.00001s Searching for anagrams of 'players'... asperly parleys parsley pyrales replays sparely splayer 7 anagram(s) found in 0.00212s > The binary search seems to be pretty fast. log2(370103) > is about 19 probes or so. chop chop chop chop chop chop chop chop chop chop chop chop chop chop chop chop chop chop boom > My version is only tuned for the test file, > and isn't as nice as yours. Do you mind posting your code, as is? No need to pretty it up or anything. > You could, of course, > store the entire word file inside the program, and > eliminate the preprocessing time :-) heh!
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-10-26 15:40 +0100 |
| Message-ID | <EVYsF.972216$893.214391@fx02.am4> |
| In reply to | #147242 |
On 26/10/2019 14:37, DFS wrote:
> On 10/26/2019 4:15 AM, Paul wrote:
>> What was your original bar bet anyway ?
>
> Well, I was finishing a bottle of Bacardi 151 and web browsing and came
> across https://wordsmith.org/anagram/
>
> It generated so many anagrams so fast I was blown away. So I went
> looking for algorithms. The first one I came across was the
> prime-products, which looked easy to implement. Once I got the code
> written, I saw how fast it was in C. Sorting the data made it much faster.
Preprocessing the data is the key.
Your simple tests combine the processing of all the data (like, reading
in the whole file), with finding anagrams of just one word.
One kind of preprocessing can just chain together all anagrams anyway,
then it comes down to looking up one word in a dictionary, which can be
under a millionth of a second. The anagram part should then take zero
time, following a handful of links.
(This preprocessing need not be done in the program each time it starts;
it can be a separate program that generates a special, linked version of
words_alpha.txt for example.)
>> You could, of course,
>> store the entire word file inside the program, and
>> eliminate the preprocessing time :-)
>
> heh!
(You can do that easily with the right language; one of mine can do this:
var []ichar words = textinclude "/texts/words_alpha.txt"
proc start=
println words.len
println words[1]
println words[$]
end
output is:
370099
a
zwitterionic
However, it slows down compilation (as it deals with 370,000 string
expressions). Much faster is to deal with the file as one string and
then separate into words at runtime.
This is convenient, but instead of loading a 4MB .txt file, you now have
to load a 7MB bigger executable, due to various overheads. So may not be
worth doing.)
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-10-28 19:49 -0400 |
| Message-ID | <j9LtF.140989$FB1.58070@fx44.iad> |
| In reply to | #147243 |
On 10/26/2019 10:40 AM, Bart wrote: > On 26/10/2019 14:37, DFS wrote: >> On 10/26/2019 4:15 AM, Paul wrote: > >>> What was your original bar bet anyway ? >> >> Well, I was finishing a bottle of Bacardi 151 and web browsing and >> came across https://wordsmith.org/anagram/ >> >> It generated so many anagrams so fast I was blown away. So I went >> looking for algorithms. The first one I came across was the >> prime-products, which looked easy to implement. Once I got the code >> written, I saw how fast it was in C. Sorting the data made it much >> faster. > > Preprocessing the data is the key. > > Your simple tests combine the processing of all the data (like, reading > in the whole file), with finding anagrams of just one word. >> One kind of preprocessing can just chain together all anagrams anyway, > then it comes down to looking up one word in a dictionary, which can be > under a millionth of a second. The anagram part should then take zero > time, following a handful of links. > > (This preprocessing need not be done in the program each time it starts; > it can be a separate program that generates a special, linked version of > words_alpha.txt for example.) Yeah, I wondered how you might do that in C. I've of course written various programs that load data, then wait for keyboard input, and wait for Ctrl+Z to quit, etc. >>> You could, of course, >>> store the entire word file inside the program, and >>> eliminate the preprocessing time :-) >> >> heh! > > (You can do that easily with the right language; one of mine can do this: > > var []ichar words = textinclude "/texts/words_alpha.txt" > > proc start= > println words.len > println words[1] > println words[$] > end > > output is: > > 370099 > a > zwitterionic > > However, it slows down compilation (as it deals with 370,000 string > expressions). Much faster is to deal with the file as one string and > then separate into words at runtime. Splitting a big string is faster than fgets() for each line (which requires ~1 second to read 370K lines, calculate the prime product, and store it in a struct)? > This is convenient, but instead of loading a 4MB .txt file, you now have > to load a 7MB bigger executable, due to various overheads. So may not be > worth doing.)
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web