Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #147078 > unrolled thread

How to use a struct with qsort()?

Started byDFS <nospam@dfs.com>
First post2019-10-19 13:35 -0400
Last post2019-10-27 13:09 -0700
Articles 20 on this page of 60 — 17 participants

Back to article view | Back to comp.lang.c


Contents

  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 →


#147078 — How to use a struct with qsort()?

FromDFS <nospam@dfs.com>
Date2019-10-19 13:35 -0400
SubjectHow 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]


#147079

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2019-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]


#147081

FromDFS <nospam@dfs.com>
Date2019-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]


#147082

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-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]


#147083

FromMelzzzzz <Melzzzzz@zzzzz.com>
Date2019-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]


#147080

FromBarry Schwarz <schwarzb@delq.com>
Date2019-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]


#147084

FromIke Naar <ike@sdf.lonestar.org>
Date2019-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]


#147086

FromDFS <nospam@dfs.com>
Date2019-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]


#147087

Fromalready5chosen@yahoo.com
Date2019-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]


#147089

FromDFS <nospam@dfs.com>
Date2019-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]


#147090

Fromalready5chosen@yahoo.com
Date2019-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]


#147092

FromDFS <nospam@dfs.com>
Date2019-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]


#147093

Fromalready5chosen@yahoo.com
Date2019-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]


#147096

FromDFS <nospam@dfs.com>
Date2019-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]


#147099

Fromalready5chosen@yahoo.com
Date2019-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]


#147113

FromDFS <nospam@dfs.com>
Date2019-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]


#147238

FromPaul <nospam@needed.invalid>
Date2019-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]


#147242

FromDFS <nospam@dfs.com>
Date2019-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]


#147243

FromBart <bc@freeuk.com>
Date2019-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]


#147316

FromDFS <nospam@dfs.com>
Date2019-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