1 /* fullgen.c */
2 /* Aktuellste Version -- mit Symmetriebetrachtungen */
3 /* 12.9.1996:   - zusaetzliche Option "pid"   (fuer GenView)
4    17.7.1996:   - Fehler-Exits durchnumeriert (fuer GenView)
5                 - mehrere Symmetrien erlaubt
6   24.10.2000:   - added code 8 for sparse6 output
7                     and made some other insignificant changes */
8 /* 24.2.2011: S+12 -> S+13 in dualcode arraygroesse. Hier wird ab 1
9    gezaehlt... */
10 /* 6.10.2011: Fehler verbessert, der ab 136 Knoten Fullerene (eins bei 136) faelschlicherweise verwarf. */
11 /* 16.6. 2014: problem mit code 3 und mehreren knotenzahlen und gleichzeitig
12    output auf stdout geloest. */
13 /* 13.2.2016: Fehler bei Detektierung von Cs mit Fixkanten verbessert */
14 /* 23.2.2016: Den Effekt desselben Fehlers bei anderen Gruppen entfernt. */
15 
16 #include<sys/types.h>
17 #include<unistd.h>
18 #include<stdlib.h>
19 #include<stdio.h>
20 #include<ctype.h>
21 #include<limits.h>
22 #include<sys/stat.h>
23 #include<string.h>
24 
25 #ifndef NOTIMES
26 #include<time.h>
27 #include<sys/times.h>
28 #endif //NOTIMES
29 
30 #define S        140           /* Maximale Anzahl der 6-Ecke */
31 #define N        ((4*S)+20)    /* Maximal moegliche Anzahl der Knoten */
32 
33 
34 #define aussen   (N+2) /* so werden kanten nach aussen markiert */
35 
36 #define infty    LONG_MAX
37 #define FL_MAX   UCHAR_MAX
38 #define KN_MAX   USHRT_MAX
39 #define unbelegt FL_MAX
40 #define leer     KN_MAX-1
41 #define f_leer   FL_MAX-1
42 #define False    0
43 #define True     1
44 #define nil      0
45 #define reg      3
46 #define filenamenlaenge 200 /* sollte vorerst reichen */
47 
48 #ifndef NOTIMES
49 #if !defined(CLK_TCK) && !defined(_SC_CLK_TCK)
50 #include <time.h>
51 #endif
52 #if !defined(CLK_TCK) && !defined(_SC_CLK_TCK)
53 #include <unistd.h>
54 #endif
55 #if !defined(CLK_TCK) && defined(_SC_CLK_TCK)
56 #define CLK_TCK sysconf(_SC_CLK_TCK)
57 #endif
58 #ifndef CLK_TCK
59 #define CLK_TCK 60     /* If the CPU time stated by the program appears
60 		      to be out by a constant ratio, the most likely
61 		      explanation is that the code got to this point but
62 		      60 is the wrong guess.  Another common value is 100. */
63 #endif
64 
65 #define time_factor CLK_TCK
66 #endif //NOTIMES
67 
68 /*
69    the macro 'my_endianness' is a char value of 'b' for big-endian
70    and 'l' for little-endian machines
71 */
72 static unsigned short word = (((unsigned short) 'b') << 8) | 'l';
73 # define  my_endianness  (* (char *) &word)
74 
75 
76 /* weitere Konstanten (TH) fuer die Kennzeichnung der Symmetriegruppen: */
77 /* (Werte nicht veraendern - oder synchron dazu die Strings mit den
78    Bezeichnungen der Symmetriegruppen aendern) */
79 #define C1__    1
80 #define C2__    2
81 #define Ci__    3
82 #define Cs__    4
83 #define C3__    5
84 #define D2__    6
85 #define S4__    7
86 #define C2v__   8
87 #define C2h__   9
88 #define D3__   10
89 #define S6__   11
90 #define C3v__  12
91 #define C3h__  13
92 #define D2h__  14
93 #define D2d__  15
94 #define D5__   16
95 #define D6__   17
96 #define D3h__  18
97 #define D3d__  19
98 #define T__    20
99 #define D5h__  21
100 #define D5d__  22
101 #define D6h__  23
102 #define D6d__  24
103 #define Td__   25
104 #define Th__   26
105 #define I__    27
106 #define Ih__   28
107 
108 
109 /* konstante Strings zur Kennzeichnung der Symmetriegruppen: */
110 
111 char symm_name[29][4] =
112   {{' ',' ',' ','\0'},  {'C','1',' ','\0'},  {'C','2',' ','\0'},
113    {'C','i',' ','\0'},  {'C','s',' ','\0'},  {'C','3',' ','\0'},
114    {'D','2',' ','\0'},  {'S','4',' ','\0'},  {'C','2','v','\0'},
115    {'C','2','h','\0'},  {'D','3',' ','\0'},  {'S','6',' ','\0'},
116    {'C','3','v','\0'},  {'C','3','h','\0'},  {'D','2','h','\0'},
117    {'D','2','d','\0'},  {'D','5',' ','\0'},  {'D','6',' ','\0'},
118    {'D','3','h','\0'},  {'D','3','d','\0'},  {'T',' ',' ','\0'},
119    {'D','5','h','\0'},  {'D','5','d','\0'},  {'D','6','h','\0'},
120    {'D','6','d','\0'},  {'T','d',' ','\0'},  {'T','h',' ','\0'},
121    {'I',' ',' ','\0'},  {'I','h',' ','\0'}};
122 
123 /* Typ-Deklarationen: */
124 
125 typedef  char BOOL; /* von 0 verschieden entspricht True */
126 
127 typedef unsigned short KNOTENTYP;
128 typedef unsigned char FLAECHENTYP; /* Bereich 1..252 */ /* DO NOT CHANGE ! Changes in the coding
129 				      and at several places where FL_MAX is used (as a sign !)
130 				      are necessary */
131 
132 typedef KNOTENTYP GRAPH[N+1][3]; /* fuer schreibegraph und Isomorphietest */
133 
134 /* Element der Adjazenztabelle: */
135 
136 
137 typedef struct BBiL {
138 		  struct BBiL *next_item;
139 		  FLAECHENTYP code[8];
140 		} BBITEMLISTE; /* die BBItems -- d.h. Codes */
141 
142 typedef struct BBiallocL {
143 		  struct BBiallocL *prev;
144 		  BBITEMLISTE *space;
145 		} BBALLOCLISTE; /* die allozierten 1000er BBitemfelder */
146 
147 
148 typedef struct iL {
149 		  struct iL *next_item;
150 		  FLAECHENTYP code[5];
151 		} ITEMLISTE; /* die Items -- d.h. Codes */
152 
153 
154 typedef struct BBsL {
155 		  int number_next;
156 		  BBITEMLISTE **items;
157 		} BBSEQUENZLISTE; /* die verzweigung der liste nach der Sequenz */
158 
159 
160 typedef struct sL {
161                   struct sL **next_level;
162 		  int number_next;
163 		  ITEMLISTE *items;
164 		  ITEMLISTE *last_item;
165 		} SEQUENZLISTE; /* die verzweigung der liste nach der Sequenz */
166 
167 
168 
169 typedef struct BBSL {
170 		  int total_items;
171 		  int total_maps;
172                   BBSEQUENZLISTE *sechser[S+1];
173  		  } BBS_LISTE; /* die erste stufe der liste -- verzweigung nach Anzahl der 6-Ecke */
174 
175 
176 typedef struct SL {
177 		  int total_maps;
178                   SEQUENZLISTE *sechser[S+1];
179  		  } S_LISTE; /* die erste stufe der liste -- verzweigung nach Anzahl der 6-Ecke */
180 
181 
182 typedef struct K {
183                    KNOTENTYP ursprung; /* bei welchem knoten startet die kante */
184                    KNOTENTYP name;  /* Identifikation des Knotens, mit
185                                        dem Verbindung besteht */
186 		   long dummy;   /* fuer alle moeglichen zwecke */
187 		   BOOL nostart;
188 		   BOOL noleft; /* fuer die Rekonstruktion: Keine Flaeche links hiervon */
189 		   BOOL noright; /* fuer die Rekonstruktion: Keine Flaeche rechts hiervon */
190 		   BOOL mirror_nostart;
191 		   KNOTENTYP mininame; /* jeweils fuer den minimalitaetstest */
192                    struct K *prev;  /* vorige Kante im Uhrzeigersinn */
193                    struct K *next;  /* naechste Kante im Uhrzeigersinn */
194 		   struct K *invers; /* die inverse Kante (in der Liste von "name") */
195                   } KANTE;
196 
197 typedef struct  {
198                    int laenge;
199                    int sequenz[7];  /* die laenge der luecke. Konvention: Beendet durch "leer" */
200 		   KANTE *kanten[7];/* die letzten aussenkanten vor der sequenz */
201 		   char k_marks[7]; /* 1 wenn anfang einer kanonischen Sequenz, 0 sonst */
202 		 } SEQUENZ;
203 
204 
205 typedef struct le { FLAECHENTYP code[12];
206 		    struct le *smaller;
207 		    struct le *larger; } LISTENTRY;
208 
209 
210 /* "Ueberschrift" der Adjazenztabelle (Array of Pointers): */
211 typedef KANTE PLANMAP[N+1][3];
212                   /* Jeweils 3 KANTEn */
213                   /* ACHTUNG: 1. Zeile der Adjazenztabelle hat Index 0 -
214                      wird fast nicht benutzt, N Zeilen auch ausreichend
215 		     In [0][0].name wird aber die knotenzahl gespeichert */
216 
217 
218 /*********************GLOBALE*VARIABLEN********************************/
219 
220 /* Die folgenden Variablen werden von fast allen Programmteilen benutzt
221    oder werden aus anderen Gruenden global verwaltet. Trotzdem werden
222    sie in einigen Faellen auch an Funktionen uebergeben, um die
223    Parameterabhaengigkeit der Funktionen zu betonen */
224 /* Variablen-Deklarationen: */
225 
226 
227 int output; /* soll auf stdout geschrieben werden */
228 int knotenzahl;  /* Knotenzahl des Graphen;
229 		   ergibt sich aus Eingabe; wird im Verlauf
230 		   der Konstruktion nicht geaendert */
231 
232 long long int non_iso_graphenzahl[N+1];
233 long long int graphenzahl[N+1];
234 
235 S_LISTE mapliste;
236 BBS_LISTE bbliste;
237 
238 KANTE *F_eck_kanten[60]; /* eine liste aller kanten, so dass links davon ein
239 			    5-Eck liegt */
240 int anzahl_5ek; /* die momentane Anzahl der eingetragenen kanten */
241 
242 int max_sechsecke,min_sechsecke;
243 
244 FLAECHENTYP **lastcode[N]; /* wird bei codeart 3 gebraucht */
245 FLAECHENTYP last_code[12]; /* wird bei codeart 2 gebraucht */
246 
247 int minbbl=N, maxbbl=0;
248 int minbrillenglas=N, maxbrillenglas=0;
249 int min_2_3_4=N;
250 int no_penta_spiral=0, no_hexa_spiral=0;
251 
252 BOOL bblmark[N+1], brillenglasmark[N+1], zwei_3_4_mark[N+1];
253 BOOL do_bauchbinde,do_brille,do_sandwich;
254 
255 LISTENTRY codeliste[N+1];
256 
257 FILE *fil[N+1];
258 int write_header_fil[N+1];
259 int write_header_stdout=1;
260 FILE *logfile;
261 char logfilename[filenamenlaenge], no_penta_spiral_filename[filenamenlaenge], no_spiral_filename[filenamenlaenge];
262 char no_hexa_spiral_filename[filenamenlaenge];
263 
264 BOOL quiet=0;
265 BOOL IPR=0, is_ipr=1;
266 BOOL to_stdout=0;
267 BOOL hexspi=0, spistat=0;
268 BOOL spiralcheck=0;
269 int codenumber, listenlaenge, mod=0, rest=0;
270 int spiralnumbers[12*S+120+1];
271 
272 /* weitere globale Variablen (TH) fuer die Statistik der Symmetriegruppen: */
273 
274 BOOL symstat=0;    /* 1 -> Symmetriestatistik erstellen */
275 int symm_anz[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
276     /*  symm_anz[i] enthaelt die Anzahl der gefundenen Fullerene, die die
277         Symmetrien der Symmetriegruppe mit der Nummer i besitzen */
278 char symm[29] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
279 int symm_len = 0;
280     /* Speicher fuer Nummern von Symmetriegruppen, die beruecksichtigt werden sollen
281        und die Anzahl der Eintraege im Array (0 => alle Gruppen beruecksichtigen) */
282 char symmstring[29*4];     /* Dateikennung, falls Symmetriegruppen gewaehlt */
283 
284 /* Prototypen: */
285 
286 void codiereplanar();
287 void common_history();
288 void schreibemap();
289 void schreibehistory();
290 
291 /****************SCHREIBE_SYMMETRIESTATISTIK********TH*****/
292 
schreibe_symmetriestatistik()293 void schreibe_symmetriestatistik()
294 { int i, j=0;
295   fprintf(stderr,"Symmetries:\n");
296   for (i=1; i<=28; i++) {
297     if (symm_anz[i]>0) {
298       fprintf(stderr,"  %s: %10d ",symm_name[i],symm_anz[i]);
299       j++;
300       if (j%4==0) {fprintf(stderr,"\n");}
301     }
302   }
303   if (j%4) {fprintf(stderr,"\n");}
304 }
305 
306 
307 /**********************CHECKSIZE_MARK_RETURN**************************************/
308 
309 /* bestimmt die groesse der flaeche links von edge -- ist da keine gibt's Probleme
310    ausserdem setzt er fuer alle kanten, so dass diese flaeche links davon ist, dummy
311    auf mark. In nextedge wird die im Gegen-Uhrzeigersinn letzte unmarkierte Kante
312    (heisst: die letzte kante mit markierung < mark) zurueckgegeben -- und nil, wenn
313    sie nicht existiert. */
314 
checksize_mark_return(KANTE * edge,int mark,KANTE ** nextedge)315 int checksize_mark_return(KANTE* edge, int mark, KANTE **nextedge)
316 
317 {
318 KANTE *run;
319 int zaehler=1;
320 
321 *nextedge=nil;
322 if (edge->dummy < mark) { *nextedge=edge->invers; edge->dummy=edge->invers->dummy=mark; }
323 
324 for (run=edge->invers->next; run != edge; run=run->invers->next)
325         { if (run->dummy < mark) { *nextedge=run->invers; run->dummy=run->invers->dummy=mark; }
326 	  zaehler++; }
327 return(zaehler);
328 }
329 
330 
331 
332 /**********************CHECKSIZE_MARK_RETURN_RIGHT**************************************/
333 
334 /* bestimmt die groesse der flaeche rechts von edge -- sonst wie oben */
335 
checksize_mark_return_right(KANTE * edge,int mark,KANTE ** nextedge)336 int checksize_mark_return_right(KANTE* edge, int mark, KANTE **nextedge)
337 
338 {
339 KANTE *run;
340 int zaehler=1;
341 
342 *nextedge=nil;
343 if (edge->dummy < mark) { *nextedge=edge->invers; edge->dummy=edge->invers->dummy=mark; }
344 
345 for (run=edge->invers->prev; run != edge; run=run->invers->prev)
346       {if (run->dummy < mark) { *nextedge=run->invers; run->dummy=run->invers->dummy=mark; }
347        zaehler++;}
348 return(zaehler);
349 }
350 
351 
352 
353 
354 /************************GET_SPIRAL_CODE**********************************/
355 
get_spiralcode(KANTE * edge,int minmark,FLAECHENTYP cmpcode[12],int sixgons)356 BOOL get_spiralcode ( KANTE *edge, int minmark, FLAECHENTYP cmpcode[12],
357 		 int sixgons)
358 
359 /* entwickelt den Spiralcode, bei dem die erste Flaeche links von edge
360    liegt, die zweite rechts davon und die Entwicklung im Uhrzeigersinn
361    geht. Entwickelt wird solange der Code besser ist als cmpcode. Das
362    Resultat wird in cmpcode geschrieben, wenn es besser ist. Wenn ein
363    Code gefunden wird, der besser ist, als cmpcode, wird 1 zurueckgegeben,
364    sonst 0.  Die aufrufende Funktion muss sicherstellen, dass alle Kanten
365    kante->dummy <= minmark erfuellen.
366 */
367 
368 {
369 int mark, i;
370 KANTE *nextedge;
371 BOOL kleiner=0;
372 FLAECHENTYP code[12], zaehler;
373 int fuenfecke=0, sechsecke=0; /* zaehler fuer die wirklich eingefuegten Flaechen */
374 int stelle;
375 
376 mark=minmark+1;
377 
378 if (checksize_mark_return(edge, mark, &nextedge)==5)
379                       {  code[0]=1; stelle=0; fuenfecke=1; }
380 else { stelle= -1; sechsecke=1; }
381 if (checksize_mark_return_right( edge, mark, &nextedge)==5)
382     { stelle++; code[stelle]=2; fuenfecke++; } else sechsecke++;
383 
384 for (i=0; (i<=stelle) && (!kleiner); i++)
385   { if (code[i]>cmpcode[i]) return(0);
386     if (code[i]<cmpcode[i]) kleiner=1; }
387 
388 zaehler=3;
389 
390 while (nextedge != nil)
391   { if (checksize_mark_return_right(nextedge, mark, &nextedge)==5)
392                        { fuenfecke++;
393 			 stelle++; code[stelle]=zaehler;
394 		         if (!kleiner)
395 			    { if (zaehler>cmpcode[stelle]) { return(0); }
396 			      if (zaehler<cmpcode[stelle]) kleiner=1;
397 			    }
398 		       }
399     else sechsecke++;
400     zaehler++;
401   }
402 
403 if ((fuenfecke<12) || (sechsecke < sixgons)) return(0);
404 
405 for (i=0; i<12; i++) cmpcode[i]=code[i];
406 return(1);
407 }
408 
409 
410 /************************GET_SPIRAL_CODE_INV**********************************/
411 
get_spiralcode_inv(KANTE * edge,int minmark,FLAECHENTYP cmpcode[12],int sixgons)412 BOOL get_spiralcode_inv ( KANTE *edge, int minmark, FLAECHENTYP cmpcode[12],
413 		 int sixgons)
414 
415 /* entwickelt den Spiralcode, bei dem die erste Flaeche links von edge
416    liegt, die zweite rechts davon und die Entwicklung im GEGEN-Uhrzeigersinn
417    geht. Sonst wie oben */
418 
419 {
420 int mark, i;
421 KANTE *nextedge;
422 BOOL kleiner=0;
423 FLAECHENTYP code[12], zaehler;
424 int fuenfecke=0, sechsecke=0; /* zaehler fuer die wirklich eingefuegten Flaechen */
425 int stelle;
426 
427 mark=minmark+1;
428 
429 if (checksize_mark_return( edge, mark, &nextedge)==5)
430                       { code[0]=1; stelle=0; fuenfecke=1; }
431 else { stelle= -1; sechsecke=1; }
432 if (checksize_mark_return_right( edge, mark, &nextedge)==5)
433     { stelle++; code[stelle]=2; fuenfecke++; } else sechsecke++;
434 
435 nextedge=edge->invers->prev;
436 
437 for (i=0; (i<=stelle) && (!kleiner); i++)
438   { if (code[i]>cmpcode[i]) return(0);
439     if (code[i]<cmpcode[i]) kleiner=1; }
440 
441 zaehler=3;
442 
443 while (nextedge != nil)
444   {
445     if (checksize_mark_return( nextedge, mark, &nextedge)==5)
446                        { fuenfecke++;
447 			 stelle++; code[stelle]=zaehler;
448 		         if (!kleiner)
449 			    { if (zaehler>cmpcode[stelle]) { return(0); }
450 			      if (zaehler<cmpcode[stelle]) kleiner=1;
451 			    }
452 		       }
453     else sechsecke++;
454     zaehler++;
455   }
456 
457 if ((fuenfecke<12) || (sechsecke < sixgons)) return(0);
458 
459 for (i=0; i<12; i++) cmpcode[i]=code[i];
460 return(1);
461 }
462 
463 
464 /************************VEGACODE*****************************/
465 
vegacode(FILE * fil,PLANMAP map)466 void vegacode( FILE *fil, PLANMAP map )
467 
468 {
469 static int erster_aufruf=1;
470 int i;
471 
472 if (erster_aufruf)
473   { fprintf(fil,">>writegraph3d planar <<\n");
474     erster_aufruf=0; }
475 
476 if (map[0][0].name >= 100)
477   {
478     for (i=1; i<=map[0][0].name; i++)
479       fprintf(fil,"%3d  0 0 0   %3d %3d %3d\n",i,map[i][0].name,map[i][1].name,map[i][2].name);
480   }
481 else
482   {
483     for (i=1; i<=map[0][0].name; i++)
484       fprintf(fil,"%2d  0 0 0   %2d %2d %2d\n",i,map[i][0].name,map[i][1].name,map[i][2].name);
485   }
486 fprintf(fil,"0\n");
487 
488 }
489 
490 /************************BELEGEDUMMIES************************/
491 
belegedummies(KANTE * edge,int nummer)492 void belegedummies(KANTE *edge, int nummer)
493 /* belegt edge->dummy, edge->invers->pre->dummy, ... mit Nummer
494    -- einmal rund um die Flaeche */
495 
496 {
497 KANTE *merke;
498 
499 merke=edge; edge->dummy=nummer;
500 edge=edge->invers->prev;
501 
502 while (edge != merke) { edge->dummy=nummer;
503 			edge=edge->invers->prev; }
504 }
505 
506 
507 /************************DUALCODE*****************************/
508 
dualcode(PLANMAP map)509 int dualcode( PLANMAP map )
510 
511 {
512 /* berechnet das Dual und schreibt es als planarcode auf stdout */
513 
514 int flaechenzahl, knotenzahl, codelaenge=1,i,j, nextnumber=2;
515 FLAECHENTYP code[(S+13)*7]; /* In main wird schon abgefangen, wenn das nicht in
516 			       unsigned char passt */
517 KANTE *startedge[S+13];
518 KANTE *run, *merke;
519 static int write_header=1;
520 
521 if (write_header)
522   { write_header=0;
523     fprintf(stdout,">>planar_code %ce<<", my_endianness);
524   }
525 
526 
527 knotenzahl=map[0][0].name;
528 code[0]=flaechenzahl= 2 + (map[0][0].name / 2);
529 
530 
531 for (i=1; i<= knotenzahl; i++) for (j=0; j<3; j++) map[i][j].dummy=0;
532 /* dummy gibt die Nummer der Flaeche rechts der Kante an */
533 
534 belegedummies(map[1],1);
535 startedge[1]=map[1];
536 
537 for (i=1; i<=flaechenzahl; i++)
538   { merke=startedge[i];
539     if (merke->invers->dummy) { code[codelaenge]=merke->invers->dummy;
540 				codelaenge++; }
541     else { code[codelaenge]= nextnumber; codelaenge++;
542 	   startedge[nextnumber]=merke->invers;
543 	   belegedummies(merke->invers,nextnumber);
544 	   nextnumber++; }
545     for (run=merke->invers->prev; run != merke; run=run->invers->prev)
546       { if (run->invers->dummy) { code[codelaenge]=run->invers->dummy;
547 				    codelaenge++; }
548         else { code[codelaenge]= nextnumber; codelaenge++;
549 	     startedge[nextnumber]=run->invers;
550 	     belegedummies(run->invers,nextnumber);
551 	     nextnumber++; }
552       }
553     code[codelaenge]=0; codelaenge++;
554   }
555 
556 fwrite(code,sizeof(FLAECHENTYP),codelaenge,stdout);
557 
558 return(codelaenge);
559 }
560 
561 /*************************SPARSE6CODE*****************************/
562 
563 int
sparse6code(PLANMAP map,FLAECHENTYP * code)564 sparse6code( PLANMAP map, FLAECHENTYP *code)
565 /* Make sparse6 code, including final '\n'. */
566 {
567     FLAECHENTYP *p;
568     int nb,i,j,lastj,x,k,r,rr,topbit;
569     int nv;
570     KANTE *merke, *lauf;
571 
572     nv = map[0][0].name;
573 
574     p = code;
575     *p++ = ':';
576 
577     if (nv <= 62)
578         *p++ = 63 + nv;
579     else
580     {
581         *p++ = 63 + 63;
582         *p++ = 63 + 0;
583         *p++ = 63 + (nv >> 6);
584         *p++ = 63 + (nv & 0x3F);
585     }
586 
587     for (i = nv-1, nb = 0; i != 0 ; i >>= 1, ++nb) {}
588     topbit = 1 << (nb-1);
589     k = 6;
590     x = 0;
591 
592     lastj = 0;
593     for (j = 0; j < nv; ++j)
594     {
595         merke = lauf = map[j+1];
596         do
597         {
598             i = lauf->name - 1;
599             if (i <= j)
600             {
601                 if (j == lastj)
602                 {
603                     x <<= 1;
604                     if (--k == 0)
605                     {
606                         *p++ = 63 + x;
607                         k = 6;
608                         x = 0;
609                     }
610                 }
611                 else
612                 {
613                     x = (x << 1) | 1;
614                     if (--k == 0)
615                     {
616                         *p++ = 63 + x;
617                         k = 6;
618                         x = 0;
619                     }
620                     if (j > lastj+1)
621                     {
622                         for (r = 0, rr = j; r < nb; ++r, rr <<= 1)
623                         {
624                             if (rr & topbit) x = (x << 1) | 1;
625                             else             x <<= 1;
626                             if (--k == 0)
627                             {
628                                 *p++ = 63 + x;
629                                 k = 6;
630                                 x = 0;
631                             }
632                         }
633                         x <<= 1;
634                         if (--k == 0)
635                         {
636                             *p++ = 63 + x;
637                             k = 6;
638                             x = 0;
639                         }
640                     }
641                     lastj = j;
642                 }
643                 for (r = 0, rr = i; r < nb; ++r, rr <<= 1)
644                 {
645                     if (rr & topbit) x = (x << 1) | 1;
646                     else             x <<= 1;
647                     if (--k == 0)
648                     {
649                         *p++ = 63 + x;
650                         k = 6;
651                         x = 0;
652                     }
653                 }
654             }
655             lauf = lauf->next;
656         } while (lauf != merke);
657     }
658 
659     if (k != 6) *p++ = 63 + ((x << k) | ((1 << k) - 1));
660 
661     *p++ = '\n';
662     return p - code;
663 }
664 
665 /*************************LONGCODE*****************************/
666 
667 #define TWOBYTES(x) {codeF[zaehler]=(x)&0xFF; codeF[zaehler+1]=((x)>>8)&0xFF;  zaehler += 2;}
668 
longcode(PLANMAP map,FLAECHENTYP * codeF)669 int longcode( PLANMAP map, FLAECHENTYP *codeF )
670 {
671 /* Codiert die Einbettung in codeF und gibt die laenge des codes zurueck */
672 int i,zaehler;
673 KANTE *merke, *lauf;
674 
675 if (map[0][0].name <= FL_MAX)
676 {
677 zaehler=1;
678 codeF[0]=map[0][0].name;
679 for(i=1;i<=map[0][0].name;i++)
680     { merke=map[i]; codeF[zaehler]=merke->name; zaehler++;
681       for(lauf=merke->next; lauf!=merke; lauf=lauf->next)
682 	           { codeF[zaehler]=lauf->name; zaehler++; }
683       codeF[zaehler]=0; zaehler++; }
684 }
685 else /* zu viele knoten fuer FLAECHENTYP */
686 {
687 zaehler=1;
688 codeF[0]=0;
689 TWOBYTES(map[0][0].name);
690 for(i=1;i<=map[0][0].name;i++)
691     { merke=map[i]; TWOBYTES(merke->name)
692       for(lauf=merke->next; lauf!=merke; lauf=lauf->next) TWOBYTES(lauf->name);
693       TWOBYTES(0);}
694 }
695 return(zaehler);
696 }
697 
698 
699 
700 /*************************SPIRALCODE*******************************/
701 
spiralcode(PLANMAP map,FLAECHENTYP code[12])702 BOOL spiralcode(PLANMAP map, FLAECHENTYP code[12])
703 
704 /* berechnet irgendeinen Spiralcode von map und schreibt ihn in code.
705    Gibt 1 zurueck, wenn der gefunden wurde und 0 sonst. versucht zuerst
706    einen Code zu finden, der an einem 5-Eck startet. */
707 
708 { int zaehler, i,j, mark, sixgons;
709   BOOL gefunden=0, hexgefunden=0;
710   FLAECHENTYP codeF[2*(81+8*S)];
711   FILE *fil2;
712   FLAECHENTYP dummycode[12];
713   FLAECHENTYP *dummy;
714   static int write_nopentaheader=1, write_nohexaheader=1;
715 
716 /*schreibemap(map);*/
717 
718 sixgons= (map[0][0].name - 20)/2;
719 
720 for (i=1; i<=map[0][0].name; i++)
721   for (j=0; j<3; j++) { map[i][j].dummy=map[i][j].mininame=0; }
722 for (i=0; i<12; i++) code[i]=FL_MAX;
723 
724 
725 for (i=0; (i<60) && !gefunden; i++)
726   { gefunden= get_spiralcode ( F_eck_kanten[i], i, code, sixgons);
727     (F_eck_kanten[i])->mininame=1; }
728 
729 mark=61;
730 
731 for (i=0; (i<60) && !gefunden; i++)
732   { gefunden= get_spiralcode_inv ( F_eck_kanten[i], mark, code, sixgons);
733     mark++; }
734 
735 
736 if (!gefunden) { no_penta_spiral++;
737 		 zaehler=longcode(map,codeF);
738 		fil2=fopen(no_penta_spiral_filename,"ab");
739 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_penta_spiral_filename);
740 		                  exit(1); }
741 		if (write_nopentaheader)
742 		  { write_nopentaheader=0;
743 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
744 		  }
745 		fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
746 		fclose(fil2);
747 	       }
748 
749 
750 if (!gefunden || hexspi)
751 {
752 if (!gefunden) dummy=code; else
753   { for (i=0; i<12; i++) dummycode[i]=FL_MAX; dummy=dummycode; }
754 for (i=1; (i<=map[0][0].name) && !hexgefunden; i++)
755   for (j=0; j<3 && !hexgefunden; j++)
756     if (!map[i][j].mininame)
757       { hexgefunden= get_spiralcode ( map[i]+j, mark, dummy, sixgons); mark++;
758         if (!hexgefunden)
759 	  { hexgefunden= get_spiralcode_inv ( map[i]+j, mark, dummy, sixgons); mark++; }
760       }
761 }
762 
763 if (hexspi && !hexgefunden) { no_hexa_spiral++;
764 		 zaehler=longcode(map,codeF);
765 		fil2=fopen(no_hexa_spiral_filename,"ab");
766 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_hexa_spiral_filename);
767 		                  exit(1); }
768 		if (write_nohexaheader)
769 		  { write_nohexaheader=0;
770 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
771 		  }
772 		fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
773 		fclose(fil2);
774 	       }
775 
776 
777 
778 return(gefunden || hexgefunden);
779 }
780 
781 
782 /*************************MINSPIRALCODE*******************************/
783 
minspiralcode(PLANMAP map,FLAECHENTYP code[12])784 BOOL minspiralcode(PLANMAP map, FLAECHENTYP code[12])
785 
786 /* berechnet den minimalen Spiralcode von map und schreibt ihn in code.
787    Gibt 1 zurueck, wenn der gefunden wurde und 0 sonst. versucht zuerst
788    einen Code zu finden, der an einem 5-Eck startet. */
789 
790 { int i,j, zaehler, mark, sixgons;
791   BOOL gefunden=0, hexgefunden=0;
792   FLAECHENTYP codeF[2*(81+8*S)];
793   FILE *fil2;
794   FLAECHENTYP dummycode[12];
795   FLAECHENTYP *dummy;
796   static int write_nopentaheader=1, write_nohexaheader=1;
797 
798 
799 /*schreibemap(map);*/
800 
801 sixgons= (map[0][0].name - 20)/2;
802 
803 for (i=1; i<=map[0][0].name; i++)
804   for (j=0; j<3; j++) { map[i][j].dummy=map[i][j].mininame=0; }
805 for (i=0; i<12; i++) code[i]=FL_MAX;
806 
807 
808 
809 for (i=0; (i<60); i++)
810   { if (get_spiralcode ( F_eck_kanten[i], i, code, sixgons)) gefunden=1;
811     (F_eck_kanten[i])->mininame=1; }
812 
813 mark=61;
814 
815 for (i=0; (i<60); i++)
816   { if (get_spiralcode_inv ( F_eck_kanten[i], mark, code, sixgons)) gefunden=1;
817     mark++; }
818 
819 
820 if (!gefunden) { no_penta_spiral++;
821 		 zaehler=longcode(map,codeF);
822 		fil2=fopen(no_penta_spiral_filename,"ab");
823 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_penta_spiral_filename);
824 		                  exit(1); }
825 		if (write_nopentaheader)
826 		  { write_nopentaheader=0;
827 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
828 		  }
829 		fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
830 		fclose(fil2);
831 	       }
832 
833 
834 if (!gefunden || hexspi) /* sonst waeren die neuen codes eh alle groesser */
835 {
836 if (!gefunden) dummy=code; else
837   { for (i=0; i<12; i++) dummycode[i]=FL_MAX; dummy=dummycode; }
838 for (i=1; (i<=map[0][0].name); i++)
839   for (j=0; j<3 ; j++)
840     if (!map[i][j].mininame)
841       { if (get_spiralcode ( map[i]+j, mark, dummy, sixgons)) hexgefunden=1; mark++;
842 	if (get_spiralcode_inv ( map[i]+j, mark, dummy, sixgons)) hexgefunden=1; mark++;
843       }
844 }
845 
846 if (hexspi && !hexgefunden) { no_hexa_spiral++;
847 		 zaehler=longcode(map,codeF);
848 		fil2=fopen(no_hexa_spiral_filename,"ab");
849 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_hexa_spiral_filename);
850 		                  exit(1); }
851 		if (write_nohexaheader)
852 		  { write_nohexaheader=0;
853 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
854 		  }
855 		fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
856 		fclose(fil2);
857 	       }
858 
859 
860 return(gefunden || hexgefunden);
861 }
862 
863 
864 
865 /*************************SPIRALSTATISTIC*******************************/
866 
spiralstatistic(PLANMAP map)867 void spiralstatistic(PLANMAP map)
868 
869 /* berechnet die Statistik, wieviele Spiralen es gibt */
870 
871 { int zaehler=0, i,j, mark, sixgons;
872   FLAECHENTYP code[12];
873 
874 
875 /*schreibemap(map);*/
876 
877 sixgons= (map[0][0].name - 20)/2;
878 
879 for (i=1; i<=map[0][0].name; i++)
880   for (j=0; j<3; j++) { map[i][j].dummy=map[i][j].mininame=0; }
881 for (i=0; i<12; i++) code[i]=FL_MAX;
882 
883 mark=1;
884 
885 for (i=1; (i<=map[0][0].name); i++)
886   for (j=0; j<3; j++)
887       { code[0]=FL_MAX;
888 	if (get_spiralcode ( map[i]+j, mark, code, sixgons)) zaehler++;
889 	/*else fprintf(stderr,"no %d %d \n",i,map[i][j].name);*/
890 	mark++;
891 	code[0]=FL_MAX;
892 	if (get_spiralcode_inv ( map[i]+j, mark, code, sixgons)) zaehler++;
893 	/*else fprintf(stderr,"no inv %d %d \n",i,map[i][j].name); */
894         mark++;}
895 
896 spiralnumbers[zaehler]++;
897 
898 }
899 
900 
901 /*********************CODECMP_KN*****************************************/
902 
codecmp_kn(KNOTENTYP * p1,KNOTENTYP * p2,int max)903 int codecmp_kn(KNOTENTYP *p1, KNOTENTYP *p2, int max)
904 {
905 max--;
906 while ((*p1==*p2) && max) { p1++; p2++; max--; }
907 return( (int)(*p1)-(int)(*p2) );
908 }
909 
910 /*********************CODECMP*****************************************/
911 
codecmp(FLAECHENTYP * p1,FLAECHENTYP * p2,int max)912 int codecmp(FLAECHENTYP *p1, FLAECHENTYP *p2, int max)
913 {
914 max--;
915 while ((*p1==*p2) && max) { p1++; p2++; max--; }
916 return( (int)(*p1)-(int)(*p2) );
917 }
918 
919 
920 /**************************IN_LISTE********************************/
921 
in_liste(FLAECHENTYP * code,LISTENTRY * el)922 void in_liste(FLAECHENTYP *code, LISTENTRY *el)
923 /* schreibt code in die liste */
924 { int compare;
925   int n;
926 
927 
928 if (el->code[0]==0)
929     {
930       for (n=0; n<12; n++) (el->code)[n]= code[n];
931       el->smaller=(LISTENTRY *)malloc(sizeof(LISTENTRY));
932          (el->smaller->code)[0]=0;
933       el->larger=(LISTENTRY *)malloc(sizeof(LISTENTRY));
934          (el->larger->code)[0]=0;
935       if ((el->smaller==nil) || (el->larger==nil))
936 	{ fprintf(stderr,"Cannot allocate memory in \"in_liste\" \n");
937 						     exit(1); }
938     }
939 
940 else {
941        compare=codecmp(code,el->code,12);
942         if (compare<0) in_liste(code,el->smaller);
943                 else if (compare>0) in_liste(code,el->larger);
944                    else { fprintf(stderr,"Dangerous error -- Two equal codes ! \n"); exit(2); }
945      }
946 }
947 
948 
949 /*********************AUSGABE***********************************/
950 
ausgabe(LISTENTRY * liste,int knotenzahl,FLAECHENTYP ** lastcode)951 void ausgabe(LISTENTRY *liste,int knotenzahl,FLAECHENTYP **lastcode)
952 
953 {
954 FLAECHENTYP i;
955 
956 if ((liste->code)[0]==0) return;
957 ausgabe(liste->smaller,knotenzahl,lastcode);
958 
959 for (i=0; (liste->code)[i]==(*lastcode)[i]; i++);
960 fwrite(&i,sizeof(FLAECHENTYP),1,fil[knotenzahl]);
961 fwrite((liste->code)+i,sizeof(FLAECHENTYP),12-i,fil[knotenzahl]);
962 *lastcode=liste->code;
963 
964 ausgabe(liste->larger,knotenzahl,lastcode);
965 }
966 
967 /********************LISTELEER********************************/
968 
listeleer(LISTENTRY * liste)969 void listeleer(LISTENTRY *liste)
970 {
971 if ((liste->code)[0]==0) return;
972 
973 listeleer(liste->smaller); free(liste->smaller);
974 listeleer(liste->larger); free(liste->larger);
975 }
976 
977 
978 /*************************CODIEREPLANAR*****************************/
979 
codiereplanar(PLANMAP map)980 void codiereplanar( PLANMAP map )
981 {
982 /* Codiert die Einbettung, schreibt sie in das entsprechende file oder
983    auf stdout und gibt die laenge des codes zurueck */
984 int zaehler,knotenzahl;
985 FLAECHENTYP codeF[2*(81+8*S)];
986 FLAECHENTYP  *codeFPZ, i;
987  static FLAECHENTYP dummycode[12]={UCHAR_MAX,UCHAR_MAX,UCHAR_MAX,0,0,0,0,0,0,0,0,0};
988 FILE *fil2;
989 BOOL test;
990 static int write_nospiheader=1;
991 
992 knotenzahl=map[0][0].name;
993 
994 if (spistat) spiralstatistic(map);
995 
996 switch(codenumber)
997   {
998   case 0: {
999            if (spiralcheck)
1000 	     { test=spiralcode(map,codeF);
1001 	       if (!test)
1002 		 { zaehler=longcode(map,codeF);
1003 		   fil2=fopen(no_spiral_filename,"ab");
1004 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1005 		                  exit(1); }
1006 		if (write_nospiheader)
1007 		  { write_nospiheader=0;
1008 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
1009 		  }
1010 		   fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1011 		   fclose(fil2);
1012 		 }
1013 	     }
1014 	   break; }
1015   case 1: {
1016            if (spiralcheck)
1017 	     { test=spiralcode(map,codeF);
1018 	       if (!test)
1019 		 { zaehler=longcode(map,codeF);
1020 		   fil2=fopen(no_spiral_filename,"ab");
1021 		   if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1022 		   exit(1); }
1023 		   if (write_nospiheader)
1024 		     { write_nospiheader=0;
1025 		     fprintf(fil2,">>planar_code %ce<<", my_endianness);
1026 		     }
1027 		   fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1028 		   fclose(fil2);
1029 		 }
1030 	     }
1031             zaehler=longcode(map,codeF);
1032 	    if (fil[knotenzahl]==stdout)
1033 	      { if (write_header_stdout)
1034 		         { write_header_stdout=0;
1035 		           fprintf(stdout,">>planar_code %ce<<", my_endianness);
1036 			 }
1037 	      }
1038 	    else
1039 	      { if (write_header_fil[knotenzahl])
1040 		         { write_header_fil[knotenzahl]=0;
1041 		           fprintf(fil[knotenzahl],">>planar_code %ce<<", my_endianness);
1042 			 }
1043 	      }
1044 	    fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil[knotenzahl]);
1045 	    break; }
1046   case 2: { test=spiralcode(map,codeF);
1047 	    if (test) { for (i=0; codeF[i]==last_code[i]; i++);
1048 			fwrite(&i,sizeof(FLAECHENTYP),1,fil[knotenzahl]);
1049 	                fwrite(codeF+i,sizeof(FLAECHENTYP),12-i,fil[knotenzahl]);
1050 		        for ( ; i<12; i++) last_code[i]=codeF[i];}
1051 	    else
1052 	      { zaehler=longcode(map,codeF);
1053 		fil2=fopen(no_spiral_filename,"ab");
1054 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1055 		exit(1); }
1056 		if (write_nospiheader)
1057 		  { write_nospiheader=0;
1058 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
1059 		  }
1060 		fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1061 		fclose(fil2);
1062 	      }
1063 	    break; }
1064   case 3: {
1065             test=minspiralcode(map,codeF);
1066 	    if (test) { in_liste(codeF,codeliste+knotenzahl);
1067 			if (graphenzahl[knotenzahl]%((long long int)listenlaenge)==0)
1068 			  {
1069 			    if (fil[knotenzahl]==stdout)
1070 			      codeFPZ = dummycode;
1071 			    else codeFPZ = *(lastcode[knotenzahl]);
1072 			  ausgabe(codeliste+(knotenzahl),knotenzahl,&codeFPZ);
1073 			  for (i=0; i<12; i++) (*(lastcode[knotenzahl]))[i]= codeFPZ[i];
1074 			  listeleer(codeliste+(knotenzahl));
1075 			  (codeliste[knotenzahl].code)[0]=0;
1076 			}
1077 		      }
1078 	    else
1079 	      { zaehler=longcode(map,codeF);
1080 		fil2=fopen(no_spiral_filename,"ab");
1081 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1082 		exit(1); }
1083 		if (write_nospiheader)
1084 		  { write_nospiheader=0;
1085 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
1086 		  }
1087 		fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1088 		fclose(fil2);
1089 	      }
1090 	    break; }
1091   case 4: {
1092             if (spiralcheck)
1093 	      { test=spiralcode(map,codeF);
1094 		if (!test)
1095 		  { zaehler=longcode(map,codeF);
1096 		    fil2=fopen(no_spiral_filename,"ab");
1097 		   if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1098 		   exit(1); }
1099 		   if (write_nospiheader)
1100 		     { write_nospiheader=0;
1101 		     fprintf(fil2,">>planar_code %ce<<", my_endianness);
1102 		     }
1103 		    fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1104 		    fclose(fil2);
1105 		  }
1106 	      }
1107 	    break; }
1108   case 5: {
1109             zaehler=longcode(map,codeF);
1110 	    if (fil[knotenzahl]==stdout)
1111 	      { if (write_header_stdout)
1112 		         { write_header_stdout=0;
1113 		           fprintf(stdout,">>planar_code %ce<<", my_endianness);
1114 			 }
1115 	      }
1116 	    else
1117 	      if (write_header_fil[knotenzahl])
1118 		         { write_header_fil[knotenzahl]=0;
1119 		           fprintf(fil[knotenzahl],">>planar_code %ce<<", my_endianness);
1120 			 }
1121 	    fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil[knotenzahl]);
1122             test=spiralcode(map,codeF);
1123 	    if (!test)
1124 	      { zaehler=longcode(map,codeF);
1125 		fil2=fopen(no_spiral_filename,"ab");
1126 		if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1127 		exit(1); }
1128 		if (write_nospiheader)
1129 		  { write_nospiheader=0;
1130 		  fprintf(fil2,">>planar_code %ce<<", my_endianness);
1131 		  }
1132 		fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1133 		fclose(fil2);
1134 	      }
1135 	    break; }
1136 
1137   case 6: { vegacode(stdout,map);
1138             if (spiralcheck)
1139 	      { test=spiralcode(map,codeF);
1140 		if (!test)
1141 		  { zaehler=longcode(map,codeF);
1142 		    fil2=fopen(no_spiral_filename,"ab");
1143 		   if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1144 		   exit(1); }
1145 		   if (write_nospiheader)
1146 		     { write_nospiheader=0;
1147 		     fprintf(fil2,">>planar_code %ce<<", my_endianness);
1148 		     }
1149 		    fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1150 		    fclose(fil2);
1151 		  }
1152 	      }
1153 	    break; }
1154 
1155   case 7: { dualcode(map);
1156             if (spiralcheck)
1157 	      { test=spiralcode(map,codeF);
1158 		if (!test)
1159 		  { zaehler=longcode(map,codeF);
1160 		    fil2=fopen(no_spiral_filename,"ab");
1161 		    if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1162 		    exit(1); }
1163 		    if (write_nospiheader)
1164 		      { write_nospiheader=0;
1165 		      fprintf(fil2,">>planar_code %ce<<", my_endianness);
1166 		      }
1167 		    fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1168 		    fclose(fil2);
1169 		  }
1170 	      }
1171 	    break; }
1172 
1173   case 8: {
1174            if (spiralcheck)
1175              { test=spiralcode(map,codeF);
1176                if (!test)
1177                  { zaehler=longcode(map,codeF);
1178                    fil2=fopen(no_spiral_filename,"ab");
1179                    if (fil2==NULL) { fprintf(stderr,"Can't open %s\n",no_spiral_filename);
1180                    exit(1); }
1181                    if (write_nospiheader)
1182                      { write_nospiheader=0;
1183                      fprintf(fil2,">>planar_code %ce<<", my_endianness);
1184                      }
1185                    fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil2);
1186                    fclose(fil2);
1187                  }
1188              }
1189             zaehler=sparse6code(map,codeF);
1190             fwrite(codeF,sizeof(FLAECHENTYP),zaehler,fil[knotenzahl]);
1191             break; }
1192 
1193   default: { fprintf(stderr,"Dangerous error in switch (codiereplanar) ! \n"); exit(3); }
1194   }
1195 }
1196 
1197 
1198 
1199 /*******************INIT_MAP************************/
1200 
init_map(PLANMAP map)1201 void init_map(PLANMAP map)
1202 {
1203 int i,j;
1204 
1205 map[0][0].name=0;
1206 
1207 for (i=1; i<=N; i++)
1208 {
1209 map[i][0].next= map[i]+1; map[i][0].prev= map[i]+2;
1210 map[i][1].next= map[i]+2; map[i][1].prev= map[i];
1211 map[i][2].next= map[i]; map[i][2].prev= map[i]+1;
1212 
1213 for (j=0; j<3; j++)
1214           { map[i][j].ursprung=i;
1215 	    map[i][j].name=leer;
1216             map[i][j].invers=nil; }
1217 }
1218 }
1219 
1220 
1221 /********************BAUE_POLYGON*******************/
1222 /* Baut ein einzelnes leeres Polygon mit n Ecken (n>=3)
1223    und initialisiert map */
1224 
baue_polygon(int n,PLANMAP map,KANTE ** marke)1225 void baue_polygon(int n, PLANMAP map, KANTE **marke )
1226 {
1227 int j;
1228 
1229 if (n<3) { fprintf(stderr,"Error, no 2-gons allowed !\n"); return; }
1230 
1231 /* sicherheitshalber erstmal loeschen und initialisieren */
1232 
1233 init_map(map);
1234 
1235 /* Immer: erster Eintrag zurueck, 2. nach aussen, dritter vor */
1236 
1237 map[1][0].name=n;   map[1][1].name=aussen;   map[1][2].name=2;
1238 map[1][0].invers=map[n]+2; map[1][1].invers=nil; map[1][2].invers=map[2];
1239 
1240 (*marke)=map[1]+1;
1241 
1242 for (j=2; j<n; j++)
1243 {
1244 map[j][0].name=j-1;   map[j][1].name=aussen;   map[j][2].name=j+1;
1245 map[j][0].invers=map[j-1]+2; map[j][1].invers=nil; map[j][2].invers=map[j+1];
1246 }
1247 
1248 map[n][0].name=n-1;   map[n][1].name=aussen;   map[n][2].name=1;
1249 map[n][0].invers=map[n-1]+2; map[n][1].invers=nil; map[n][2].invers=map[1];
1250 
1251 map[0][0].name=n;
1252 
1253 }
1254 
1255 /**********************CHECKSIZE_RIGHT**************************************/
1256 
1257 /* bestimmt die groesse der flaeche rechts von edge -- ist da keine gibt's Probleme */
1258 
checksize_right(KANTE * edge)1259 int checksize_right( KANTE* edge)
1260 {
1261 KANTE *run;
1262 int zaehler=1;
1263 
1264 for (run=edge->invers->prev; run != edge; run=run->invers->prev) zaehler++;
1265 return(zaehler);
1266 }
1267 
1268 
1269 
1270 
1271 /*********************ADD_POLYGON***********************************/
1272 
add_polygon(int n,PLANMAP map,KANTE * start,KANTE ** lastout)1273 void add_polygon(int n, PLANMAP map, KANTE *start, KANTE **lastout)
1274 /* fuegt ein weiteres polygon einer Reihe an. Dabei ist n die groesse des polygons.
1275    Angefuegt wird immer an start. Die Marke wird nicht versetzt. Ueber lastout wird
1276    die letzte Aussenkante des Polygons zurueckgegeben. */
1277 
1278 
1279 {
1280 int new_tempknz, tempknz;
1281 KANTE *ende;
1282 int common_vertices;
1283 
1284 
1285 if (IPR && (n==5))
1286   {
1287     if (checksize_right(start->next)==5) is_ipr=0;
1288     for (ende=start->next->invers->next, common_vertices=2; ende->name != aussen;
1289 	  ende=ende->invers->next) { if (checksize_right(ende)==5) is_ipr=0;
1290                                      common_vertices++;
1291 				   }
1292   }
1293 else for (ende=start->next->invers->next, common_vertices=2; ende->name != aussen;
1294 	  ende=ende->invers->next) common_vertices++;
1295 
1296 
1297 if (n<common_vertices)
1298    { fprintf(stderr,"polygon to insert too small !\n");
1299      exit(4); }
1300 
1301 /* es muessen also n-common_vertices knoten hinzugefuegt werden */
1302 
1303 tempknz=map[0][0].name;
1304 new_tempknz=tempknz+n-common_vertices;
1305 
1306 if (n-common_vertices==0) /* dann kommt kein knoten dazu */
1307   { start->name=ende->ursprung; start->invers=ende;
1308     ende->name=start->ursprung; ende->invers=start;
1309     *lastout=nil;
1310     return;
1311   }
1312 
1313 if (n-common_vertices==1) /* dann kommt nur ein knoten dazu */
1314  {
1315  tempknz++;
1316  start->name=tempknz; start->invers=map[tempknz];
1317  map[tempknz][0].name=start->ursprung; map[tempknz][0].invers=start;
1318  map[tempknz][1].name=aussen; map[tempknz][1].invers=nil;
1319  map[tempknz][2].name=ende->ursprung; map[tempknz][2].invers=ende;
1320  ende->name=tempknz; ende->invers=map[tempknz]+2;
1321  *lastout=map[tempknz]+1;
1322  map[0][0].name=tempknz;
1323  return;
1324  }
1325 
1326 
1327 /* es bleibt: mindestens zwei neue knoten */
1328 
1329 tempknz++;
1330 start->name=tempknz; start->invers=map[tempknz];
1331 map[tempknz][0].name=start->ursprung; map[tempknz][0].invers=start;
1332 map[tempknz][1].name=aussen; map[tempknz][1].invers=nil;
1333 map[tempknz][2].name=tempknz+1; map[tempknz][2].invers=map[tempknz+1];
1334 
1335 for (tempknz++; tempknz<new_tempknz; tempknz++)
1336     { map[tempknz][0].name=tempknz-1; map[tempknz][0].invers=map[tempknz-1]+2;
1337       map[tempknz][1].name=aussen; map[tempknz][1].invers=nil;
1338       map[tempknz][2].name=tempknz+1; map[tempknz][2].invers=map[tempknz+1]; }
1339 
1340 /* und nun noch den letzten knoten */
1341 map[tempknz][0].name=tempknz-1; map[tempknz][0].invers=map[tempknz-1]+2;
1342 map[tempknz][1].name=aussen; map[tempknz][1].invers=nil;
1343 map[tempknz][2].name=ende->ursprung; map[tempknz][2].invers= ende;
1344 ende->name=tempknz; ende->invers=map[tempknz]+2;
1345 *lastout=map[tempknz]+1;
1346 map[0][0].name=tempknz;
1347 }
1348 
1349 
1350 /**********************SEQUENZ_KANONISCH***********************************/
1351 
sequenz_kanonisch(int sequenz[])1352 int sequenz_kanonisch( int sequenz[] )
1353 /* checkt, ob eine sequenz kanonisch ist, gibt 1 zurueck wenn ja, 0 sonst */
1354 
1355 { int i,j, laenge, max;
1356   int longseq[14];
1357 
1358 
1359   max=sequenz[0]; j=1; /* j hier nur als merker */
1360   for (i=0; sequenz[i] != leer; i++) { longseq[i]=sequenz[i];
1361 				       if (longseq[i]==max) j=0;
1362 				         else if (longseq[i]>max) { return(0); }
1363 				     }
1364   if (j) return(1); /* der erste ist eindeutig, also die ganze sequenz */
1365 
1366   laenge=i;
1367   for (j=0; j<laenge; i++, j++) longseq[i]=sequenz[j];
1368 
1369 for (j=1; j<laenge; i++, j++)
1370     if (longseq[j]==max)
1371 	{ for (i=1; (i<laenge) && (longseq[j+i]==sequenz[i]) ; i++);
1372 	  if (longseq[j+i]>sequenz[i])
1373                         { return(0); }
1374         }
1375 return(1);
1376 }
1377 
1378 
1379 
1380 /***********************BERECHNE_SEQUENZ********************************/
1381 
berechne_sequenz(SEQUENZ * sq,SEQUENZ altsq,int start,int f_ecke)1382 void berechne_sequenz(SEQUENZ *sq, SEQUENZ altsq, int start,int f_ecke)
1383 /* berechnet die neue sequenz startend bei der Kante start */
1384 /* geht fest davon aus, dass 2 mal nach innen hintereinander nicht vorkommt */
1385 /* zwei der Kanten-Eintraege koennen noch nicht belegt werden (die ersten beiden) */
1386 /* start ist der laufindex */
1387 {
1388 int i, j, k, laenge,alt_laenge;
1389 int *sequenz;
1390 int puffer[13];
1391 char *kan;
1392 KANTE **sqkanten;
1393 KANTE *kpuffer[13];
1394 
1395 
1396 sequenz=sq->sequenz;
1397 kan=sq->k_marks;
1398 sqkanten=sq->kanten;
1399 
1400 alt_laenge=altsq.laenge;
1401 sq->laenge= alt_laenge-f_ecke;
1402 laenge=sq->laenge;
1403 
1404 for (i=0; i<alt_laenge; i++) { puffer[i]=puffer[i+alt_laenge]=altsq.sequenz[i];
1405 			       kpuffer[i]=kpuffer[i+alt_laenge]=altsq.kanten[i]; }
1406 
1407 if (puffer[start]==0) { fprintf(stderr,"Berechne_sequenz should not be called for 0-gaps ! \n");
1408                         exit(5); }
1409 
1410 if (f_ecke==0)
1411   { if (laenge==1) sequenz[0]=puffer[0]+1;
1412     else
1413     if (laenge==2)
1414          { if (puffer[start]>1) { sequenz[0]=puffer[start]-1; sequenz[1]=puffer[start+1]+2; }
1415 	      else { sequenz[1]=0; sequenz[0]=puffer[start+1]+2; }
1416 	 }
1417     else /* d.h. laenge > 2 */
1418       { if (puffer[start]>1)
1419 	  {
1420 	    sequenz[0]= puffer[start]-1;
1421 	    sequenz[1]= puffer[start+1]+1;
1422 	    sequenz[laenge-1]=puffer[start+laenge-1]+1;
1423 	    sqkanten[laenge-1]=kpuffer[start+laenge-1];
1424 	    for (j=2; j<laenge-1; j++) { sequenz[j]=puffer[start+j];
1425 					 sqkanten[j]=kpuffer[start+j]; }
1426 	  }
1427 	else /* d.h. die luecke hat laenge 1 */
1428 	  {
1429 	    sequenz[laenge-1]= 0;
1430 	    sequenz[0]= puffer[start+1]+1;
1431 	    sequenz[laenge-2]=puffer[start+laenge-1]+1;
1432 	    sqkanten[laenge-2]=kpuffer[start+laenge-1];
1433 	    for (j=1; j<laenge-2; j++) { sequenz[j]=puffer[start+j+1];
1434 					 sqkanten[j]=kpuffer[start+j+1]; }
1435 	  }
1436       } /* ende laenge > 2 */
1437   } /* ende 0 Fuenfecke */
1438 
1439 else
1440 if (f_ecke==1)
1441   { if (laenge==0) sequenz[0]=puffer[0]+1;
1442     else
1443     if (laenge==1) sequenz[0]=puffer[0]+puffer[1]+1;
1444     else
1445     if (laenge==2)
1446           { sequenz[0]=puffer[start] + puffer[start+1]; sequenz[1]=puffer[start+2]+1;
1447 	    sqkanten[1]=kpuffer[start+2];}
1448     else /* d.h. laenge > 2 */
1449       { sequenz[0]= puffer[start]+puffer[start+1];
1450 	sequenz[laenge-1]=puffer[start+laenge]+1;
1451 	sqkanten[laenge-1]=kpuffer[start+laenge];
1452 	for (j=1; j<laenge-1; j++) { sequenz[j]=puffer[start+j+1];
1453 				     sqkanten[j]=kpuffer[start+j+1]; }
1454       }
1455   } /* ende 1 Fuenfecke */
1456 
1457 else /* d.h. f_ecke==2 */
1458   { if (laenge==0) sequenz[0]=puffer[0]+puffer[1]+1;
1459     else { fprintf(stderr,"ERROR: Two 5-gons not leading to 0-Sequence !\n");
1460 	   exit(6); }
1461   } /* ende 2 Fuenfecke */
1462 
1463 if (sequenz[0]==0) /* nur im Fall eines einzelnen 6-Ecks moeglich */
1464   { puffer[0]=sequenz[0];
1465     for (i=0; i<laenge-1; i++) sequenz[i]=sequenz[i+1]; sequenz[laenge-1]=puffer[0];
1466     for (i=1; i<laenge-1; i++) sqkanten[i]=sqkanten[i+1]; }
1467 
1468 
1469 
1470 if (laenge==0) { sequenz[1]=leer; kan[0]=1; return; }
1471 
1472 sequenz[laenge]=leer;
1473 
1474 kan[0]=sequenz_kanonisch(sequenz);
1475 
1476 for (i=1; i < laenge; i++)
1477   { for (j=i, k=0; j<laenge; j++, k++) puffer[k]=sequenz[j];
1478     for (j=0; j<i; j++, k++) puffer[k]=sequenz[j];
1479     puffer[k]=leer;
1480     kan[i]=sequenz_kanonisch(puffer);
1481   }
1482 
1483 }
1484 
1485 
1486 
1487 
1488 
1489 
1490 /***********************BELEGE_SEQUENZ********************************/
1491 
belege_sequenz(KANTE * start,SEQUENZ * sq)1492 void belege_sequenz( KANTE *start, SEQUENZ *sq)
1493 /* belegt die sequenz startend bei der Kante start */
1494 /* geht fest davon aus, dass 2 mal nach innen hintereinander nicht vorkommt */
1495 
1496 {
1497 int i, j, k, zaehler, position;
1498 KANTE *run;
1499 int *sequenz;
1500 KANTE **seqkanten;
1501 int puffer[7];
1502 char *kan;
1503 
1504 
1505 sequenz=sq->sequenz;
1506 seqkanten=sq->kanten;
1507 kan=sq->k_marks;
1508 
1509 
1510 if (start->next->invers->next->name == aussen)
1511     { fprintf(stderr,"Achtung -- naechste Kante nicht nach innen -- FEHLER !\n");
1512       exit(7); }
1513 
1514 for (i=0; i<7; i++) { sequenz[i]=leer; seqkanten[i]=nil; kan[i]=0;}
1515 
1516 if (start->prev->invers->prev->name != aussen) /* d.h. vorige Kante nicht nach aussen, also nur
1517 						  Randlaenge zu bestimmen */
1518     { sq->laenge=0;
1519       for (run=start->next->invers->next->invers->next, zaehler=1; run != start;
1520            run=run->next->invers->next->invers->next) zaehler++;
1521       sequenz[0]=zaehler;
1522       seqkanten[0]=start;
1523       return;
1524     }
1525 
1526 sq->laenge=0;
1527 zaehler=1;
1528 position=0;
1529 seqkanten[0]=start;
1530 
1531 
1532 for (run=start->next->invers->next->invers->next; run->next->invers->next->name < aussen;
1533      run=run->next->invers->next->invers->next) zaehler++;
1534 sequenz[0]=zaehler; position=1;
1535 if (run->next->invers->next != start) seqkanten[position]=run->next->invers->next;
1536 for (run=run->next->invers->next; run->next->invers->next->name >= aussen;
1537      run=run->next->invers->next)
1538 { sequenz[position]=0; position++;
1539 if (run->next->invers->next != start) seqkanten[position]=run->next->invers->next; }
1540 /* naechste Kante vor nicht-0-sequenz suchen */
1541 
1542 
1543 while (run != start)
1544 {
1545 for (zaehler=0; run->next->invers->next->name < aussen;
1546                 run=run->next->invers->next->invers->next) zaehler++;
1547 sequenz[position]=zaehler;  position++;
1548 if (run->next->invers->next != start) seqkanten[position]=run->next->invers->next;
1549 for (run=run->next->invers->next; run->next->invers->next->name >= aussen;
1550      run=run->next->invers->next) { sequenz[position]=0;  position++;
1551 if (run->next->invers->next != start) seqkanten[position]=run->next->invers->next; }
1552 
1553 }
1554 
1555 sequenz[position]=leer; seqkanten[position]=nil;
1556 sq->laenge=position;
1557 
1558 kan[0]=sequenz_kanonisch(sequenz);
1559 
1560 for (i=1; sequenz[i] != leer; i++)
1561   { for (j=i, k=0; sequenz[j]!=leer; j++, k++) puffer[k]=sequenz[j];
1562     for (j=0; j<i; j++, k++) puffer[k]=sequenz[j];
1563     puffer[k]=leer;
1564     kan[i]=sequenz_kanonisch(puffer);
1565   }
1566 
1567 
1568 
1569 }
1570 
1571 
1572 /**********************CHECKSIZE**************************************/
1573 
1574 /* bestimmt die groesse der flaeche links von edge -- ist da keine gibt's Probleme */
1575 
checksize(KANTE * edge)1576 int checksize(KANTE* edge)
1577 {
1578 KANTE *run;
1579 int zaehler=1;
1580 
1581 for (run=edge->invers->next; run != edge; run=run->invers->next) zaehler++;
1582 return(zaehler);
1583 }
1584 
1585 
1586 
1587 /*************************CODIERE***************************************/
1588 /* speziell fuer diese Flaechenstuecke. Sie werden ab der Marke von aussen
1589    in eine "Spirale" entwickelt. Die Eindeutigkeit ergibt sich nur zusammen
1590    mit der Sequenz. der "code" sind die stellen, an denen 5-Ecke vorkommen
1591 
1592    Ein mieser sonderfall sind die 0-sequenzen. da kann nicht einfach nur abgewickelt
1593    werden. Die Codierung ist dort: erst die Anzahl der 6-Eck Schichten, dann die
1594    Anzahl der Spitzen, die man gegen den Uhrzeigersinn zurueckgehen muss, um ein
1595    5-Eck zu finden und dann erst kann normal fortgefahren werden. Die schichten werden
1596    spiralfoermig abgebaut.
1597 
1598    laenge !=0 gilt nur fuer diese Situation. Dann ist laenge die anzahl der
1599    aussenkanten auf dem rand.
1600 
1601    Im Falle von 6 Pentagonen wird 1 zurueckgegeben, wenn der entwickelte Code
1602    kleinstmoeglich ist und 0 sonst.
1603 
1604    Fuer den miesen sonderfall wird der code aber (in der aufrufroutine) zum wegspeichern
1605    so geaendert, dass die zweite stelle immer die anzahl N der verschiedenen markierten
1606    Pflasterungen ist. die koennen dann erzeugt werden, indem 0 bis N Schritte zum ersten
1607    5-Eck zurueckgegangen wird bei der Rekonstruktion.
1608 
1609    Die Anzahl der 6-Eck-Ringe ist immer 0 beim Aufruf.
1610 
1611 */
1612 
1613 
codiere(PLANMAP map,FLAECHENTYP * code,KANTE * start,int codesize,int laenge)1614 int codiere(PLANMAP map, FLAECHENTYP *code, KANTE *start, int codesize, int laenge)
1615 {
1616 int i, j, stelle, zaehler, knotenzahl, flaechennumber, verschiebung, merkeknoten;
1617 /* zaehler zaehlt die Flaechengroesse, knotenzahl die zahl der restlichen knoten */
1618 int tempknz, laufzaehler, autozaehler, minitest;
1619 KANTE *run, *merke, *run2;
1620 FLAECHENTYP testcode[9];
1621 
1622 
1623 if (start->name != aussen) { fprintf(stderr,"Codiere must start at external edge !\n");
1624 			     exit(8); }
1625 
1626 tempknz=map[0][0].name;
1627 
1628 if (tempknz==5) { code[0]=1; return(1); }
1629 
1630 for (i=1; i<=tempknz; i++) for (j=0; j<3; j++)
1631   if (map[i][j].name == aussen) map[i][j].dummy= infty; else map[i][j].dummy=0;
1632 
1633 run=start; stelle=0; knotenzahl=tempknz;
1634 
1635 if (laenge) /* d.h. 6-Fuenfecke-patch */
1636   { verschiebung=0;
1637     code[2]=unbelegt;
1638     code[0]=0; /*code[1]=verschiebung;*/ stelle=2;
1639     merkeknoten=knotenzahl;
1640     laufzaehler=1;
1641     /* Jetzt den minimalen Code ausrechnen: */
1642     for ( autozaehler=0, run2=start->prev;
1643 	 (verschiebung<laenge) && !autozaehler; verschiebung++, run2=run2->prev->invers->next->invers)
1644       if (checksize(run2)==5)
1645 	{
1646 	  laufzaehler++;
1647 	  run=run2->next;
1648 	  stelle=2; knotenzahl=merkeknoten;
1649 	  flaechennumber=0;
1650 	  while (stelle<codesize)
1651 	    { flaechennumber++;
1652 	      zaehler=2;
1653 	      while (run->prev->invers->prev->dummy>=laufzaehler)
1654 		                                     run=run->prev->invers->prev; /* sicherstellen, dass davor
1655 										     keine aussenkanten sind */
1656 	      run->prev->invers->dummy=laufzaehler; run->next->invers->dummy=laufzaehler;
1657 	      run=run->next->invers->next; knotenzahl--;
1658 	      while (run->dummy>=laufzaehler)
1659 		{ zaehler++; knotenzahl--; run->prev->invers->dummy=laufzaehler;
1660 		  run->next->invers->dummy=laufzaehler;
1661 		  run=run->next->invers->next; }
1662 	      merke=run->next;
1663 	      run=run->prev;
1664 	      while (merke->dummy<laufzaehler)
1665 		{ zaehler++; merke=merke->invers->prev; }
1666 	      if (zaehler==5) { testcode[stelle]=flaechennumber; stelle++; }
1667 	      else if (zaehler!=6) { fprintf(stderr,"ERROR in CODIERE: No 5- or 6-Gon !\n"); exit(9); }
1668 	      if (knotenzahl==5) { testcode[stelle]=flaechennumber+1; stelle++; }
1669 	    } /* ende while */
1670 	  if ((minitest=codecmp(code+2,testcode+2,6))>0)
1671 	    { if (verschiebung) return(0);
1672 	      else { for (stelle=2; stelle<8; stelle++) code[stelle]=testcode[stelle]; }
1673 	    }
1674 	  if (minitest==0) autozaehler=1; /* verschiebung>=1 ist automatisch */
1675 	} /* ende checksize==5 */
1676     if (autozaehler) code[1]=verschiebung-1;
1677     else code[1]=laenge;
1678     return(1);
1679   } /* ende if */
1680 
1681 
1682 
1683  flaechennumber=0;
1684 
1685 
1686 
1687 while (stelle<codesize)
1688   { flaechennumber++;
1689     zaehler=2;
1690     while (run->prev->invers->prev->dummy) run=run->prev->invers->prev; /* sicherstellen, dass davor
1691 									   keine aussenkanten sind */
1692     run->prev->invers->dummy=1; run->next->invers->dummy=1;
1693     run=run->next->invers->next; knotenzahl--;
1694     while (run->dummy)
1695       { zaehler++; knotenzahl--; run->prev->invers->dummy=1; run->next->invers->dummy=1;
1696 	run=run->next->invers->next; }
1697     merke=run->next;
1698     run=run->prev;
1699     while (!(merke->dummy))
1700       { zaehler++; merke=merke->invers->prev; }
1701     if (zaehler==5) { code[stelle]=flaechennumber; stelle++; }
1702     else if (zaehler!=6) { fprintf(stderr,"ERROR in CODIERE(2): No 5- or 6-Gon !\n"); exit(10); }
1703     if (knotenzahl==5) { code[stelle]=flaechennumber+1; stelle++; }
1704   } /* ende while */
1705 
1706 return(1);
1707 
1708 }
1709 
1710 
1711 
1712 /***********************BBITEMALLOC********************************************/
1713 
bbitemalloc()1714 BBITEMLISTE *bbitemalloc()
1715 /* gibt immer die Adresse eines neuen bbitems zurueck */
1716 {
1717 static BBITEMLISTE *back=nil; /* back enthaelt immer den letzten, der zurueckgegeben
1718 			       wurde -- erst hochsetzen -- wichtig */
1719 static BBITEMLISTE *last=nil;
1720 
1721 if (back==last) { back=(BBITEMLISTE *)malloc(sizeof(BBITEMLISTE)*1001);
1722 		  if (back==NULL) { fprintf(stderr,"Can not get more memory for bbitems"); exit(11); }
1723 		  last=back+1000;
1724 		  return(back); }
1725 
1726 /* else */
1727 back++;
1728 return(back);
1729 }
1730 
1731 
1732 /***********************ITEMALLOC********************************************/
1733 
itemalloc()1734 ITEMLISTE *itemalloc()
1735 /* gibt immer die Adresse eines neuen items zurueck */
1736 {
1737 static ITEMLISTE *back=nil; /* back enthaelt immer den letzten, der zurueckgegeben
1738 			       wurde -- erst hochsetzen -- wichtig */
1739 static ITEMLISTE *last=nil;
1740 
1741 if (back==last) { back=(ITEMLISTE *)malloc(sizeof(ITEMLISTE)*1001);
1742 		  if (back==NULL) { fprintf(stderr,"Can not get more memory for items"); exit(12); }
1743 		  last=back+1000;
1744 		  return(back); }
1745 
1746 /* else */
1747 back++;
1748 return(back);
1749 }
1750 
1751 
1752 /*******************PUT_IN_LISTE***********************************************/
1753 
put_in_liste(int sechsecke,SEQUENZ sq,FLAECHENTYP * code,int codesize)1754 void put_in_liste(int sechsecke, SEQUENZ sq, FLAECHENTYP *code, int codesize )
1755 {
1756 
1757 ITEMLISTE *item;
1758 SEQUENZLISTE *anfang;
1759 SEQUENZLISTE **puffer;
1760 int i,j, s_eintrag;
1761 
1762 /*schreibesequenz(sq);*/
1763 /*schreibelistitems();*/
1764 
1765 anfang=mapliste.sechser[sechsecke];
1766 mapliste.total_maps++;
1767 for (i=0; i<sq.laenge; i++)
1768   { s_eintrag=sq.sequenz[i];
1769     if (anfang->number_next <= s_eintrag)
1770       { puffer=anfang->next_level;
1771 	anfang->next_level=(SEQUENZLISTE **)malloc((s_eintrag+1)*sizeof(SEQUENZLISTE *));
1772 	if (anfang->next_level==NULL) { fprintf(stderr,"Can not get more memory"); exit(13); }
1773 	for (j=0; j< anfang->number_next; j++) anfang->next_level[j]=puffer[j];
1774 	for (   ; j <= s_eintrag; j++) anfang->next_level[j]=nil;
1775 	anfang->number_next=s_eintrag+1;
1776 	free(puffer);
1777       }
1778     if (anfang->next_level[s_eintrag]==nil)
1779       {	anfang->next_level[s_eintrag]=(SEQUENZLISTE *)malloc(sizeof(SEQUENZLISTE));
1780 	if (anfang->next_level[s_eintrag]==NULL) { fprintf(stderr,"Can not get more memory"); exit(14); }
1781 	anfang=anfang->next_level[s_eintrag];
1782 	anfang->next_level=nil; anfang->number_next=0;
1783 	anfang->items=anfang->last_item=nil;
1784       }
1785     else anfang=anfang->next_level[s_eintrag];
1786   } /* ende for */
1787 
1788 /* jetzt muesste anfang passend stehen zum Eintragen des Codes */
1789 
1790 if (anfang->items==nil) item=anfang->items=anfang->last_item=itemalloc();
1791    else { item=anfang->last_item->next_item=itemalloc();
1792 	  anfang->last_item=item; }
1793 item->next_item=nil;
1794 for (j=0; j<codesize; j++) item->code[j]=code[j];
1795 }
1796 
1797 
1798 /*******************PUT_IN_BB_LISTE***********************************************/
1799 
put_in_bb_liste(int sechsecke,SEQUENZ sq,FLAECHENTYP * code)1800 void put_in_bb_liste(int sechsecke, SEQUENZ sq, FLAECHENTYP *code)
1801 {
1802 
1803 BBITEMLISTE *item, **puffer, *merke;
1804 BBSEQUENZLISTE *anfang;
1805 int j, s_eintrag;
1806 
1807 /*schreibesequenz(sq);*/
1808 /*schreibelistitems();*/
1809 
1810 
1811 
1812 anfang=bbliste.sechser[sechsecke];
1813 s_eintrag=sq.sequenz[0];
1814 if (anfang->number_next <= s_eintrag)
1815   { puffer=anfang->items;
1816     anfang->items=(BBITEMLISTE **)malloc((s_eintrag+1)*sizeof(BBITEMLISTE *));
1817     if (anfang->items==NULL) { fprintf(stderr,"Can not get more memory"); exit(15); }
1818     for (j=0; j< anfang->number_next; j++) { anfang->items[j]=puffer[j]; }
1819     for (   ; j <= s_eintrag; j++) { anfang->items[j]=nil; }
1820     anfang->number_next=s_eintrag+1;
1821     free(puffer);
1822   }
1823 
1824 bbliste.total_items++;
1825 bbliste.total_maps += code[1];
1826 
1827 if (anfang->items[s_eintrag]==nil) { item=anfang->items[s_eintrag]=bbitemalloc();
1828 			              item->next_item=nil; }
1829    else { merke=anfang->items[s_eintrag];
1830 	  item=anfang->items[s_eintrag]=bbitemalloc();
1831 	  item->next_item=merke; }
1832 if (item==NULL) { fprintf(stderr,"Can not get more memory"); exit(16); }
1833 for (j=0; j<8; j++) item->code[j]=code[j];
1834 
1835 }
1836 
1837 
1838 
1839 
1840 /************************SCHREIBE_AUF************************************/
1841 
schreibe_auf(PLANMAP map,SEQUENZ sq,int rest_sechsecke)1842 void schreibe_auf(PLANMAP map, SEQUENZ sq, int rest_sechsecke)
1843 /* codiert und schreibt eine markierte Pflasterung -- wird nur fuer
1844    bis zu 5 Fuenfecken aufgerufen */
1845 {
1846 int fuenfecke, sechsecke, i, codesize, pfadlaenge, non_nuller;
1847 FLAECHENTYP code[9];
1848 
1849 
1850 if ( !(do_sandwich || do_brille) ) return;
1851 if (IPR && (!is_ipr)) return;
1852 
1853 fuenfecke=6-sq.laenge;
1854 
1855 if (fuenfecke < 2) return; /* die werden bei der konstruktion nie gebraucht */
1856 for (i=non_nuller=0; i< sq.laenge; i++) if (sq.sequenz[i] != 0) non_nuller++;
1857 if (non_nuller >2) return; /* Bei jedem Patch der GEBRAUCHT wird, koennen nur
1858 			      an 2 Stellen Probleme auftreten */
1859 
1860 
1861 pfadlaenge=sq.laenge;
1862 for (i=0; i< sq.laenge; i++) pfadlaenge += (2*sq.sequenz[i]);
1863 
1864 switch (fuenfecke)
1865   {
1866   case 5: { brillenglasmark[pfadlaenge]=1;
1867 	    break; }
1868 
1869   case 4: { zwei_3_4_mark[pfadlaenge]=1;
1870             if (sq.sequenz[1]==0) /* dann kann es auch ein brillenglas sein */
1871 	        brillenglasmark[pfadlaenge]=1;
1872 	    break; }
1873   default: { zwei_3_4_mark[pfadlaenge]=1; }
1874   }
1875 
1876 sechsecke=(map[0][0].name)-10+sq.laenge-sq.sequenz[0];
1877 for (i=1; i<sq.laenge; i++) sechsecke -= sq.sequenz[i];
1878 sechsecke=sechsecke/2;        /* alles leicht aus Euler Formel */
1879 
1880 
1881 if (sechsecke+rest_sechsecke != max_sechsecke) { fprintf(stderr,"Error in 6-gon calculation (schreibe_auf) !\n");
1882 						 exit(17); }
1883 
1884 codesize=fuenfecke;
1885 codiere(map, code, sq.kanten[0], fuenfecke,0);
1886 
1887 put_in_liste(sechsecke, sq, code, codesize );
1888 
1889 return;
1890 	   }
1891 
1892 /*************************CHECK_MARK_UND_SCHREIBE***************************/
1893 
1894 /* Ueberprueft, ob eine Einbettung mit 6 5-Ecken, also ohne
1895 Doppelte Aussenkanten, neu ist. Wenn ja, codiert und speichert sie die Einbettung
1896 und alle sich daraus durch hinzufuegen von 6-Eck-Ringen ergebenden */
1897 
check_mark_und_schreibe(PLANMAP map,KANTE * first,int laenge,int rest_sechsecke)1898 void check_mark_und_schreibe(PLANMAP map, KANTE *first, int laenge, int rest_sechsecke)
1899 {
1900 
1901 
1902 SEQUENZ localsq;
1903 int sechsecke;
1904 FLAECHENTYP code[8];
1905 
1906 if (!do_bauchbinde) return;
1907 if (IPR && (!is_ipr))  return;
1908 
1909 localsq.laenge=0; localsq.sequenz[0]=laenge;
1910 localsq.kanten[0]=first;
1911 
1912 sechsecke=((map[0][0].name)-10-laenge)/2;
1913                /* leicht aus Euler Formel */
1914 
1915 if (sechsecke+rest_sechsecke != max_sechsecke)
1916   { fprintf(stderr,"Error in 6-gon calculation (check_mark_und_schreibe) !\n");
1917 						 exit(18); }
1918 
1919 if (!codiere(map, code, first, 8, laenge)) return; /* nicht kanonisch */
1920 if (code[0] !=0) { fprintf(stderr," there was a hexagon ring.......\n"); exit(19); }
1921 put_in_bb_liste(sechsecke, localsq, code);
1922 
1923 bblmark[laenge]=1;
1924 
1925 /* neue ringe hinzufuegen */
1926 while (rest_sechsecke >= laenge)
1927   {
1928     rest_sechsecke -= laenge;
1929     sechsecke+= laenge;
1930     (code[0])++;
1931     put_in_bb_liste(sechsecke, localsq, code);
1932   }
1933 
1934 return;
1935 
1936 }
1937 
1938 
1939 /***************************BAUE_AUF**************************************/
1940 
1941 /* die eigentliche konstruktionsroutine -- legt auf alle moeglichen arten eine
1942 neue reihe an */
1943 
baue_auf(PLANMAP map,SEQUENZ sq,int sechsecke)1944 void baue_auf(PLANMAP map, SEQUENZ sq, int sechsecke)
1945 {
1946 
1947 SEQUENZ localseq;
1948 int j, i, laenge;
1949 KANTE *naechste, *nextmark, *run;
1950 int anzahl, naechste_stelle, sql;
1951 
1952 
1953 if (IPR && (!is_ipr))  return;
1954 
1955 sql=sq.laenge;
1956 
1957 if (sql >=2)
1958 {
1959 for (i=0; i<sql && ((i==0) || !((sq.k_marks)[i])); i++)
1960                                             /* Schleife ueber alle moeglichen Startpunkte */
1961   {
1962     laenge=sq.sequenz[i];
1963     if (i==sql-1) naechste_stelle=0; else naechste_stelle=i+1;
1964     if (laenge==0)
1965     {
1966     /* da nie eine 0 am anfang einer kanonischen Sequenz stehen kann, kann die erste einer
1967        doppel-0 nie am ende stehen, also: */
1968       if ( (i<sql-1) && (sq.sequenz[i+1]==0) )
1969 	{
1970 	  if (sechsecke >= 1)
1971 	    {
1972 	      naechste=sq.kanten[i];
1973 	      { add_polygon(6,map,naechste,&naechste); nextmark=naechste; }
1974 	      belege_sequenz(nextmark,&localseq);
1975 	      if (localseq.k_marks[0])
1976 		{ schreibe_auf(map,localseq,sechsecke-1);
1977 		  baue_auf(map, localseq, sechsecke-1); }
1978 	      /* aufraeumen: */
1979 	      (map[0][0].name) = (map[0][0].name) - 4;
1980 	      run=sq.kanten[i]; run->name=aussen; run->invers=nil;
1981 	      run=run->next->invers->next; run->name=aussen; run->invers=nil;
1982 	    }   /* ende if ...*/
1983 	  naechste=sq.kanten[i];
1984 	  { add_polygon(5,map,naechste,&naechste); nextmark=naechste; }
1985 	  belege_sequenz(nextmark,&localseq);
1986 	  if (localseq.k_marks[0])
1987 	    { schreibe_auf(map,localseq,sechsecke);
1988 	      baue_auf(map, localseq, sechsecke); }
1989 	  /* aufraeumen: */
1990 	  is_ipr=1;
1991 	  (map[0][0].name) = (map[0][0].name) - 3;
1992 	  run=sq.kanten[i]; run->name=aussen; run->invers=nil;
1993 	  run=run->next->invers->next; run->name=aussen; run->invers=nil;
1994 
1995 	}
1996 
1997     if (sq.laenge==2) /* nur dann oder im vorigen Fall muss auch an 0er angelegt werden */
1998     {
1999     /* In diesem Teil wird die Sequenz nicht a priori berechnet, sondern erst im nachhinein --
2000        das kostet zwar Zeit, ist aber einfacher und braucht nicht so wahnsinnig viele
2001        Fallunterscheidungen */
2002 
2003     if (i != 1) { fprintf(stderr,"ERROR: i should be 1 !\n"); exit(26); }
2004     anzahl= 2 + sq.sequenz[0]; /* Bei laenge 0 muss der naechste mit aufgefuellt werden,
2005 					       um keine Doppel-Innenkanten zu erhalten */
2006 
2007     /* erst nur 6-Ecke */
2008     if (sechsecke >= anzahl)
2009       {
2010       naechste=sq.kanten[i];
2011       if (anzahl==1) { add_polygon(6,map,naechste,&naechste); nextmark=naechste; }
2012         else {
2013                add_polygon(6,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2014                for (j=1; j<anzahl; j++)  add_polygon(6,map,naechste,&naechste); }
2015       belege_sequenz(nextmark,&localseq);
2016       if (localseq.k_marks[0])
2017 	   { schreibe_auf(map,localseq,sechsecke-anzahl);
2018 	     baue_auf(map, localseq, sechsecke-anzahl); }
2019       /* aufraeumen: */
2020       (map[0][0].name) = (map[0][0].name) - 2*anzahl -2;
2021       run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2022       run=run->next->invers->next; run->name=aussen; run->invers=nil;
2023       for (j=2 ; j<anzahl; j++) { run=run->next->invers->next->invers->next;
2024 	                         run->name=aussen; run->invers=nil; }
2025       }   /* ende if ...*/
2026 
2027 
2028 
2029     /* dann ein 5- und 6-Ecke */
2030     if (sechsecke >= anzahl-1)
2031       {
2032       naechste=sq.kanten[i];
2033       if (anzahl==1) { add_polygon(5,map,naechste,&naechste); nextmark=naechste; }
2034         else {
2035                add_polygon(6,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2036                for (j=1; j<anzahl-1; j++)  add_polygon(6,map,naechste,&naechste);
2037                add_polygon(5,map,naechste,&naechste);  }
2038       belege_sequenz(nextmark,&localseq);
2039       if (localseq.k_marks[0])
2040 	   { schreibe_auf(map,localseq,sechsecke-anzahl+1);
2041 	     baue_auf(map, localseq, sechsecke-anzahl+1); }
2042       /* aufraeumen: */
2043       is_ipr=1;
2044       (map[0][0].name) = (map[0][0].name) - 2*anzahl-1;
2045       run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2046       run=run->next->invers->next; run->name=aussen; run->invers=nil;
2047       for (j=2 ; j<anzahl; j++) { run=run->next->invers->next->invers->next;
2048 	                         run->name=aussen; run->invers=nil; }
2049       }   /* ende if ... */
2050 
2051     /* dann eventuell zwei 5- und der Rest 6-Ecke um es zu 0-Sequenz zu machen */
2052     if (sechsecke >= anzahl-2)
2053       {
2054       naechste=sq.kanten[i];
2055       add_polygon(5,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2056       for (j=1; j<anzahl-1; j++)  add_polygon(6,map,naechste,&naechste);
2057       add_polygon(5,map,naechste,&naechste);
2058       belege_sequenz(nextmark,&localseq);
2059       check_mark_und_schreibe(map,nextmark,localseq.sequenz[0],sechsecke-anzahl+2);
2060 
2061       /* aufraeumen: */
2062       is_ipr=1;
2063       (map[0][0].name) = (map[0][0].name) - 2*anzahl;
2064       run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2065       run=run->next->invers->next; run->name=aussen; run->invers=nil;
2066       for (j=2; j<anzahl; j++) { run=run->next->invers->next->invers->next;
2067 	                         run->name=aussen; run->invers=nil; }
2068 
2069       }   /* ende if */
2070      } /* ende if sq.laenge==2 */
2071     } /* ende laenge==0 */
2072 
2073 
2074     else /* d.h. laenge !=0 */
2075     {
2076 
2077     /* ein sonderfall, wenn der naechste ein 0er ist (der erste aber nicht)--
2078        dann musss da noch ein 6-Eck mehr angefuegt werden: */
2079 
2080       if ((sq.sequenz[naechste_stelle]==0) && (sql>2))
2081 	  {
2082 	    if (sechsecke >= laenge+1)
2083 	    {
2084 	      naechste=sq.kanten[i];
2085               add_polygon(6,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2086 	      /* insgesamt laenge+1: */
2087 	      for (j=1; j<=laenge; j++)  add_polygon(6,map,naechste,&naechste);
2088 	      belege_sequenz(nextmark,&localseq);
2089 	      if (localseq.k_marks[0])
2090 		{ schreibe_auf(map,localseq,sechsecke-laenge-1);
2091 		  baue_auf(map, localseq, sechsecke-laenge-1); }
2092               /* aufraeumen: */
2093 	      (map[0][0].name) = (map[0][0].name) - 2*laenge -4;
2094 	      run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2095 	      for (j=0; j<laenge; j++) { run=run->next->invers->next->invers->next;
2096 					 run->name=aussen; run->invers=nil; }
2097 	      run=run->next->invers->next; run->name=aussen; run->invers=nil;
2098 
2099 	    }   /* ende if ...*/
2100 	    if (sechsecke >= laenge)
2101 	    {
2102 	      naechste=sq.kanten[i];
2103               add_polygon(6,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2104 	      /* insgesamt laenge+1: */
2105 	      for (j=1; j<laenge; j++)  add_polygon(6,map,naechste,&naechste);
2106 	      add_polygon(5,map,naechste,&naechste);
2107 	      belege_sequenz(nextmark,&localseq);
2108 	      if (localseq.k_marks[0])
2109 		{ schreibe_auf(map,localseq,sechsecke-laenge);
2110 		  baue_auf(map, localseq, sechsecke-laenge); }
2111               /* aufraeumen: */
2112 	      is_ipr=1;
2113 	      (map[0][0].name) = (map[0][0].name) - 2*laenge -3;
2114 	      run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2115 	      for (j=0; j<laenge; j++) { run=run->next->invers->next->invers->next;
2116 					 run->name=aussen; run->invers=nil; }
2117 	      run=run->next->invers->next; run->name=aussen; run->invers=nil;
2118 
2119 	    }   /* ende if ...*/
2120 	  } /* ende sonderfall naechste_stelle==0-sequenz */
2121 
2122 
2123 
2124     /* erst nur 6-Ecke */
2125     if (sechsecke >= laenge)
2126       {
2127       naechste=sq.kanten[i];
2128       berechne_sequenz(&localseq,sq,i,0);
2129       if (localseq.k_marks[0])
2130       {
2131       if (laenge==1) { add_polygon(6,map,naechste,&naechste); nextmark=naechste;
2132                        localseq.kanten[0]=nextmark;
2133 		       localseq.kanten[localseq.laenge-1]=naechste->prev->invers->prev; }
2134         else {
2135                add_polygon(6,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2136                for (j=1; j<laenge; j++)  add_polygon(6,map,naechste,&naechste);
2137                localseq.kanten[0]=nextmark; localseq.kanten[1]=naechste; }
2138       if (localseq.k_marks[0])
2139 	   { schreibe_auf(map,localseq,sechsecke-laenge);
2140 	     baue_auf(map, localseq, sechsecke-laenge); }
2141       /* aufraeumen: */
2142       (map[0][0].name) = (map[0][0].name) - 2*laenge -1;
2143 
2144       run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2145       for (j=0; j<laenge; j++) { run=run->next->invers->next->invers->next;
2146 	                         run->name=aussen; run->invers=nil; }
2147     }/* ende if kanonisch */
2148       }   /* ende if ...*/
2149 
2150 
2151 
2152     /* dann ein 5- und 6-Ecke */
2153     if (sechsecke >= laenge-1)
2154       {
2155       naechste=sq.kanten[i];
2156       berechne_sequenz(&localseq,sq,i,1);
2157       if (localseq.k_marks[0])
2158       {
2159       if (laenge==1) { add_polygon(5,map,naechste,&naechste); nextmark=naechste;
2160                        localseq.kanten[0]=nextmark; }
2161         else {
2162                add_polygon(6,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2163                for (j=1; j<laenge-1; j++)  add_polygon(6,map,naechste,&naechste);
2164                add_polygon(5,map,naechste,&naechste);
2165                localseq.kanten[0]=nextmark; }
2166       if (localseq.k_marks[0])
2167 	   { schreibe_auf(map,localseq,sechsecke-laenge+1);
2168 	     baue_auf(map, localseq, sechsecke-laenge+1); }
2169       /* aufraeumen: */
2170       is_ipr=1;
2171       (map[0][0].name) = (map[0][0].name) - 2*laenge;
2172       run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2173       for (j=0; j<laenge; j++) { run=run->next->invers->next->invers->next;
2174 	                         run->name=aussen; run->invers=nil; }
2175     }/* ende if kanonisch */
2176       }   /* ende if ... */
2177 
2178     /* dann eventuell zwei 5- und der Rest 6-Ecke um es zu 0-Sequenz zu machen */
2179     if ((laenge>=2) && (sechsecke >= laenge-2) && (sq.laenge==2))
2180       {
2181       naechste=sq.kanten[i];
2182       berechne_sequenz(&localseq,sq,i,2);
2183       add_polygon(5,map,naechste,&naechste); nextmark=naechste->prev->invers->prev;
2184       for (j=1; j<laenge-1; j++)  add_polygon(6,map,naechste,&naechste);
2185       add_polygon(5,map,naechste,&naechste);
2186       localseq.kanten[0]=nextmark;
2187       check_mark_und_schreibe(map,nextmark,localseq.sequenz[0],sechsecke-laenge+2);
2188 
2189       /* aufraeumen: */
2190       is_ipr=1;
2191       (map[0][0].name) = (map[0][0].name) - 2*laenge + 1;
2192       run=sq.kanten[i]; run->name=aussen; run->invers=nil;
2193       for (j=0; j<laenge; j++) { run=run->next->invers->next->invers->next;
2194 	                         run->name=aussen; run->invers=nil; }
2195       }   /* ende if */
2196     }/* ende laenge != 0 */
2197    } /* ende for */
2198 
2199 } /* ende if sequenzlaenge >=2 */
2200 
2201 else /* d.h. sequenzlaenge==1 */
2202 {
2203 laenge=sq.sequenz[0];
2204 
2205 /* erst nur 6-Ecke */
2206 if (laenge && (sechsecke >= (laenge+1)))
2207  {
2208  naechste=sq.kanten[0];
2209  berechne_sequenz(&localseq,sq,0,0);
2210  for (j=0; j<=laenge; j++)  add_polygon(6,map,naechste,&naechste);
2211  nextmark=naechste;
2212  localseq.kanten[0]=nextmark;
2213  schreibe_auf(map,localseq,sechsecke-laenge-1);
2214  baue_auf(map, localseq, sechsecke-laenge-1);
2215  /* aufraeumen: */
2216  (map[0][0].name) = (map[0][0].name) - 2*laenge -3;
2217 
2218       run=sq.kanten[0]; run->name=aussen; run->invers=nil;
2219       for (j=0; j<laenge; j++) { run=run->next->invers->next->invers->next;
2220 	                         run->name=aussen; run->invers=nil; }
2221       }   /* ende if */
2222 
2223 /* dann ein 5- und 6-Ecke */
2224 if (laenge && (sechsecke >= laenge))
2225   {
2226   naechste=sq.kanten[0];
2227   berechne_sequenz(&localseq,sq,0,1);
2228   for (j=0; j<laenge; j++)  add_polygon(6,map,naechste,&naechste);
2229   add_polygon(5,map,naechste,&naechste);
2230   nextmark=naechste;
2231   /* das ist zwar zwangslaeufig kanonisch, aber trotzdem: */
2232   localseq.kanten[0]=nextmark;
2233   check_mark_und_schreibe(map,nextmark,localseq.sequenz[0],sechsecke-laenge);
2234   /* aufraeumen: */
2235   is_ipr=1;
2236   (map[0][0].name) = (map[0][0].name) - 2*laenge -2;
2237   run=sq.kanten[0]; run->name=aussen; run->invers=nil;
2238   for (j=0; j<laenge; j++) { run=run->next->invers->next->invers->next;
2239 			     run->name=aussen; run->invers=nil; }
2240       }   /* ende if */
2241 
2242 
2243 } /* ende else */
2244 
2245 }
2246 
2247 /***************************BAUE_PATCHES************************************/
2248 
baue_patches(int sechsecke)2249 void baue_patches(int sechsecke)
2250 {
2251 PLANMAP map;
2252 SEQUENZ sq;
2253 KANTE *marke;
2254 int i;
2255 
2256 
2257 for (i=0; i<=N; i++) bblmark[i]=brillenglasmark[i]=zwei_3_4_mark[i]=0;
2258 
2259 
2260 /* Patches, die nur aus einer Flaeche bestehen, brauchen nicht betrachtet zu
2261    werden */
2262 
2263 if (sechsecke >=2)
2264 /* zuerst Start mit 2 Sechsecken */
2265 {
2266 baue_polygon(6,map,&marke);
2267 add_polygon(6,map,marke,&marke);
2268 belege_sequenz(marke, &sq);
2269 schreibe_auf(map,sq,sechsecke-2);
2270 baue_auf( map, sq, sechsecke-2);
2271 }
2272 
2273 if (sechsecke >=1)
2274 /* dann ein 5- und ein 6-Eck */
2275 {
2276 baue_polygon(5,map,&marke);
2277 add_polygon(6,map,marke,&marke);
2278 belege_sequenz( marke, &sq);
2279 schreibe_auf(map,sq,sechsecke-1);
2280 baue_auf( map, sq, sechsecke-1);
2281 }
2282 
2283 /* dann zwei 5-Ecke */
2284 if (!IPR)
2285 {
2286 baue_polygon(5,map,&marke);
2287 add_polygon(5,map,marke,&marke);
2288 belege_sequenz( marke, &sq);
2289 schreibe_auf(map,sq,sechsecke);
2290 baue_auf( map, sq, sechsecke);
2291 }
2292 
2293 
2294 for (minbbl=1; bblmark[minbbl]==0; minbbl++);
2295 for (maxbbl=N; bblmark[maxbbl]==0; maxbbl--);
2296 
2297 for (minbrillenglas=1; brillenglasmark[minbrillenglas]==0; minbrillenglas++);
2298 for (maxbrillenglas=N; brillenglasmark[maxbrillenglas]==0; maxbrillenglas--);
2299 
2300 for (min_2_3_4=1; zwei_3_4_mark[min_2_3_4]==0; min_2_3_4++);
2301 
2302 
2303 }
2304 
2305 /***********************INITIALIZE_LIST**********************************/
2306 
initialize_list()2307 void initialize_list()
2308 {
2309 int j;
2310 SEQUENZLISTE *qq;
2311 BBSEQUENZLISTE *bbqq;
2312 
2313 mapliste.total_maps=0;
2314 
2315 for (j=0; j<=max_sechsecke; j++)
2316   {
2317     qq=(mapliste.sechser)[j]=(SEQUENZLISTE *)malloc(sizeof(SEQUENZLISTE));
2318     if (qq==NULL) { fprintf(stderr,"Can not get more memory"); exit(27); }
2319     qq->next_level=nil;
2320     qq->number_next=0;
2321     qq->items=qq->last_item=nil;
2322   }
2323 
2324 
2325 bbliste.total_items=bbliste.total_maps=0;
2326 for (j=0; j<=max_sechsecke; j++)
2327   {
2328     bbqq=(bbliste.sechser)[j]=(BBSEQUENZLISTE *)malloc(sizeof(BBSEQUENZLISTE));
2329     if (bbqq==NULL) { fprintf(stderr,"Can not get more memory"); exit(28); }
2330     bbqq->items=nil;
2331     bbqq->number_next=0;
2332   }
2333 
2334 
2335 
2336 
2337 }
2338 
2339 
2340 
2341 /**********************ZAEHLE_KNOTEN*************************************/
2342 
zaehle_knoten(PLANMAP map,KNOTENTYP knoten,BOOL mark[],int * patchknz)2343 void zaehle_knoten(PLANMAP map, KNOTENTYP knoten, BOOL mark[], int *patchknz)
2344 
2345 /* zaehlt die knoten, belegt aber auch dummy */
2346 
2347 {
2348 int j;
2349 
2350 for (j=0; j<3; j++)
2351   if (map[knoten][j].mininame == aussen) map[knoten][j].dummy=infty;
2352    else { map[knoten][j].dummy=0;
2353 	  if (!mark[map[knoten][j].mininame])
2354 	    { (*patchknz)++;
2355 	      mark[map[knoten][j].mininame]=1;
2356 	      zaehle_knoten(map,map[knoten][j].mininame,mark,patchknz);
2357 	    }
2358 	}
2359 }
2360 
2361 
2362 
2363 /**********************REKO_BB_CODE***************************************/
2364 /* Rekonstruiert den minimalen Code eines 6-Eck-patches */
2365 
reko_bb_code(PLANMAP map,KNOTENTYP * code,KNOTENTYP * spiegelcode,int laenge,KANTE * start,KANTE * ministart[],KANTE * spiegelministart[],int * patchknz)2366 void reko_bb_code(PLANMAP map, KNOTENTYP *code, KNOTENTYP *spiegelcode, int laenge,
2367 		  KANTE *start, KANTE *ministart[], KANTE *spiegelministart[], int *patchknz)
2368 {
2369 int i, j, stelle, zaehler, knotenzahl, flaechennumber, schichtenzaehler, verschiebung, merkeknoten;
2370 /* zaehler zaehlt die Flaechengroesse, knotenzahl die zahl der restlichen knoten */
2371 int laufzaehler;
2372 KANTE *run, *merke, *run2, *merke_run, *mstart;
2373 KNOTENTYP testcode[9];
2374 int mstartzaehler, test, k, laenge_2;
2375 BOOL mark[N+1];
2376 
2377 
2378 if (start->mininame != aussen) { fprintf(stderr,"Reko_BB_code must start at external edge !\n");
2379 			     exit(29); }
2380 for (i=0; i<8; i++) { code[i]=spiegelcode[i]=unbelegt; testcode[i]=0; }
2381 
2382 mstartzaehler=0;
2383 for (i=0; i<7; i++) ministart[i]=spiegelministart[i]=nil;
2384 
2385 for (i=1; i<=map[0][0].name; i++) mark[i]=0;
2386 mark[start->ursprung]=1; *patchknz=1;
2387 
2388 zaehle_knoten(map,start->ursprung,mark,patchknz);
2389 
2390 laenge_2 = laenge/2;
2391 run=start; knotenzahl=*patchknz;
2392 
2393 verschiebung=schichtenzaehler=0;
2394 
2395 while (!verschiebung)
2396   {for (i=1, run2=run->prev; (i<=laenge_2) && !verschiebung; i++, run2=run2->prev->invers->next->invers)
2397      /* muss bei 1 starten und nachher korrigiert werden, um den Abbruch bei 0 zu gewaehrleisten */
2398      { if (checksize(run2) == 5) { run=run2->next; verschiebung=i; } }
2399    if (!verschiebung) { schichtenzaehler++;
2400 			knotenzahl -= laenge;
2401 			run=run->prev->invers->next->invers;
2402 			for (run2=run, i=0; i<laenge_2; i++,
2403 			     run2=run2->next->invers->next->invers->next)
2404 			  { run2->dummy=infty; }
2405 		      }
2406  } /* ende while */
2407 code[0]=schichtenzaehler; code[1]=0; /* verschiebung wird nicht betrachtet */ stelle=2;
2408 merkeknoten=knotenzahl;
2409 laufzaehler=1;
2410 /* Jetzt den minimalen Code ausrechnen: */
2411 for ( run2=run->prev; verschiebung<=laenge_2; verschiebung++, run2=run2->prev->invers->next->invers)
2412   if (checksize(run2)==5)
2413     { merke_run=run2->next;
2414       laufzaehler++;
2415       run=run2->next;
2416       stelle=2; knotenzahl=merkeknoten;
2417       flaechennumber=0;
2418       while (stelle<8)
2419 	{
2420 	  flaechennumber++;
2421 	  zaehler=2;
2422 	  while (run->prev->invers->prev->dummy>=laufzaehler)
2423 	    run=run->prev->invers->prev; /* sicherstellen, dass davor
2424 					    keine aussenkanten sind */
2425 	  run->prev->invers->dummy=laufzaehler; run->next->invers->dummy=laufzaehler;
2426 	  run=run->next->invers->next; knotenzahl--;
2427 	  while (run->dummy>=laufzaehler)
2428 	    { zaehler++; knotenzahl--; run->prev->invers->dummy=laufzaehler;
2429 	      run->next->invers->dummy=laufzaehler;
2430 	      run=run->next->invers->next; }
2431 	  merke=run->next;
2432 	  run=run->prev;
2433 	  while (merke->dummy<laufzaehler)
2434 	    { zaehler++; merke=merke->invers->prev; }
2435 	  if (zaehler==5) { testcode[stelle]=flaechennumber; stelle++; }
2436 	  else if (zaehler!=6) { fprintf(stderr,"ERROR in REKO_BB_CODE: No 5- or 6-Gon !\n"); exit(30); }
2437 	  if (knotenzahl==5) { testcode[stelle]=flaechennumber+1; stelle++; }
2438 	} /* ende while */
2439       if ((test=codecmp_kn(code+2,testcode+2,6))>=0)
2440 	{ if (test>0) { for (stelle=2; stelle<8; stelle++) code[stelle]=testcode[stelle];
2441 			for (k=0; k<mstartzaehler; k++) ministart[k]=nil;
2442 		        mstartzaehler=0;}
2443 	  mstart=merke_run;
2444 	  for (k=0; k<schichtenzaehler; k++) mstart = mstart->invers->prev->invers->next;
2445 	  ministart[mstartzaehler]=mstart->prev->invers->next;
2446 	  mstartzaehler++;
2447 	}
2448     } /* ende checksize==5 */
2449 
2450 
2451 
2452 /* Jetzt den Spiegelcode */
2453 
2454 for (i=1; i<=map[0][0].name; i++)
2455   if (mark[i])
2456     for (j=0; j<3; j++)
2457       { if (map[i][j].mininame==aussen) map[i][j].dummy=infty;
2458         else map[i][j].dummy=0; }
2459 
2460 run=start; knotenzahl=*patchknz;
2461 
2462 verschiebung=schichtenzaehler=mstartzaehler=0;
2463 
2464 while (!verschiebung)
2465   {for (i=1, run2=run->prev; (i<=laenge_2) && !verschiebung; i++, run2=run2->invers->prev->invers->next)
2466      /* muss bei 1 starten und nachher korrigiert werden, um den Abbruch bei 0 zu gewaehrleisten */
2467      { if (checksize(run2) == 5) { run=run2->next; verschiebung=i; } }
2468    if (!verschiebung) { schichtenzaehler++;
2469 			knotenzahl -= laenge;
2470 			run=run->next->invers->prev->invers;
2471 			for (run2=run, i=0; i<laenge_2; i++,
2472 			     run2=run2->prev->invers->prev->invers->prev)
2473 			  { run2->dummy=infty; }
2474 		      }
2475  } /* ende while */
2476 spiegelcode[0]=schichtenzaehler; spiegelcode[1]=0; /* verschiebung wird nicht betrachtet */ stelle=2;
2477 merkeknoten=knotenzahl;
2478 laufzaehler=1;
2479 /* Jetzt den minimalen Code ausrechnen: */
2480 for ( run2=run->prev; verschiebung<=laenge_2; verschiebung++, run2=run2->invers->prev->invers->next)
2481   if (checksize(run2)==5)
2482     { merke_run=run2->next;
2483       laufzaehler++;
2484       run=run2->next;
2485       stelle=2; knotenzahl=merkeknoten;
2486       flaechennumber=0;
2487       while (stelle<8)
2488 	{ flaechennumber++;
2489 	  zaehler=2;
2490 	  while (run->next->invers->next->dummy>=laufzaehler)
2491 	    run=run->next->invers->next; /* sicherstellen, dass davor
2492 					    keine aussenkanten sind */
2493 	  run->next->invers->dummy=laufzaehler; run->prev->invers->dummy=laufzaehler;
2494 	  run=run->prev->invers->prev; knotenzahl--;
2495 	  while (run->dummy>=laufzaehler)
2496 	    { zaehler++; knotenzahl--; run->next->invers->dummy=laufzaehler;
2497 	      run->prev->invers->dummy=laufzaehler;
2498 	      run=run->prev->invers->prev; }
2499 	  merke=run->prev;
2500 	  run=run->next;
2501 	  while (merke->dummy<laufzaehler)
2502 	    { zaehler++; merke=merke->invers->next; }
2503 	  if (zaehler==5) { testcode[stelle]=flaechennumber; stelle++; }
2504 	  else if (zaehler!=6) { fprintf(stderr,"ERROR in REKO_BB_CODE(2):  No 5- or 6-Gon !\n"); exit(31); }
2505 	  if (knotenzahl==5) { testcode[stelle]=flaechennumber+1; stelle++; }
2506 	} /* ende while */
2507       if ((test=codecmp_kn(spiegelcode+2,testcode+2,6))>=0)
2508 	{ if (test>0) { for (stelle=2; stelle<8; stelle++) spiegelcode[stelle]=testcode[stelle];
2509 			for (k=0; k<mstartzaehler; k++) spiegelministart[k]=nil;
2510 		        mstartzaehler=0;}
2511 	  mstart=merke_run;
2512 	  for (k=0; k<schichtenzaehler; k++) mstart = mstart->invers->next->invers->prev;
2513 	  spiegelministart[mstartzaehler]=mstart->next->invers->prev;
2514 	  mstartzaehler++;
2515 	}
2516     } /* ende checksize==5 */
2517 
2518 return;
2519 }
2520 
2521 /***********************BAUCHBINDE_REKO*******************************/
2522 
2523 /* berechnet den minimalen Code, der sich aus der bei "anfangskante"
2524    beginnenden Bauchbinde ergibt */
2525 /* TH:  Die Funktion wurde so geaendert, dass sie
2526    0 zurueckgibt, wenn code > minimaler Code (wie bisher)
2527    1 zurueckgibt, wenn code < minimaler Code (wie bisher)
2528    2 zurueckgibt, wenn code== minimaler Code fuer die
2529                   Originalversion (Automorphismus existiert)
2530    4 zurueckgibt, wenn code== minimaler Code fuer die
2531                   gespiegelte Version (Automorphismus existiert)
2532    6 zurueckgibt, wenn code== minimaler Code sowohl fuer die
2533                   Originalversion als auch fuer die gespiegelte
2534                   Version (Automorphismus existiert)              */
2535 
bauchbinde_reko(PLANMAP map,KNOTENTYP * code,KANTE * anfangskante)2536 int bauchbinde_reko(PLANMAP map,KNOTENTYP *code,KANTE *anfangskante)
2537 {
2538 int i,j,k, patchknz1, patchknz2, test, test2, test3, test4, returnwert;
2539 KANTE *run;
2540 KNOTENTYP code1[8], code2[8], spiegelcode1[8], spiegelcode2[8];
2541 KANTE *ministart1[7], *ministart2[7], *spiegelministart1[7], *spiegelministart2[7];
2542 KNOTENTYP *ucode, *lcode, *uscode, *lscode;
2543 KANTE **ustart, **lstart, **us_start, **ls_start;
2544 BOOL gleich, ende;
2545 BOOL j_gleich1, j_gleich2, j_gleich3, j_gleich4;                 /* TH */
2546 FLAECHENTYP c3, c11;
2547 
2548 
2549 c3=code[3]; c11=code[11];
2550 code[3]=code[11]=0;
2551 
2552 for (i=1; i<=map[0][0].name; i++) for (j=0;j<3; j++) { map[i][j].dummy=0;
2553 						       map[i][j].mininame=map[i][j].name; }
2554 
2555 for (i=1, run=anfangskante->invers->prev; i<code[0]; i+=2)
2556   { run->prev->mininame=aussen;
2557     run=run->invers->next->invers->prev; }
2558 
2559 reko_bb_code(map, code1, spiegelcode1, code[0], anfangskante->invers->next, ministart1, spiegelministart1,
2560 	     &patchknz1);
2561 
2562 
2563 for (i=1, run=anfangskante->invers->prev; i<code[0]; i+=2)
2564   { run->prev->mininame=run->prev->name;
2565     run->invers->prev->mininame=aussen;
2566     run=run->invers->next->invers->prev; }
2567 
2568 reko_bb_code(map, code2, spiegelcode2, code[0], anfangskante->next, ministart2, spiegelministart2,
2569 	     &patchknz2);
2570 
2571 
2572 if (patchknz2>patchknz1) { ucode=code2; uscode=spiegelcode2; lcode=code1; lscode=spiegelcode1;
2573 			   ustart=ministart2; lstart=ministart1; us_start=spiegelministart2;
2574 			   ls_start=spiegelministart1; gleich=0; }
2575    else if (patchknz2<patchknz1) { ucode=code1; uscode=spiegelcode1; lcode=code2; lscode=spiegelcode2;
2576 				   ustart=ministart1; lstart=ministart2; us_start=spiegelministart1;
2577 				   ls_start=spiegelministart2; gleich=0; }
2578         else /* d.h. beide patchknotenzahlen gleich */
2579 	  { test=codecmp_kn(code1,code2,8);
2580 	    if (test>0) { ucode=code1; lcode=code2; ustart=ministart1; lstart=ministart2; gleich=0; }
2581 	      else { if (test<0) { ucode=code2; lcode=code1; ustart=ministart2; lstart=ministart1; gleich=0; }
2582 		     else { ucode=code1; lcode=code2; ustart=ministart1; lstart=ministart2; /*vorerst*/ gleich=1;
2583 			  }
2584 		   }
2585 	    test=codecmp_kn(spiegelcode1,spiegelcode2,8);
2586 	    if (test>0) { uscode=spiegelcode1; lscode=spiegelcode2; us_start=spiegelministart1;
2587 			  ls_start=spiegelministart2;  }
2588 	      else { if (test<0) { uscode=spiegelcode2; lscode=spiegelcode1; us_start=spiegelministart2;
2589 				   ls_start=spiegelministart1;  }
2590 		     else { uscode=spiegelcode1; lscode=spiegelcode2; us_start=spiegelministart1; /*vorerst*/
2591 			    ls_start=spiegelministart2; }
2592 		   }
2593 	  }
2594 
2595 j_gleich1 = j_gleich2 = 0;       /* TH */
2596 if ((test=codecmp_kn(lcode,code+2,8)) < 0) {code[3]=c3; code[11]=c11; return(0);}
2597    else if (test==0)
2598          { if ((test2=codecmp_kn(ucode,code+10,8)) < 0) {code[3]=c3; code[11]=c11; return(0);}
2599 	   else if (test2==0) /* d.h. die verschiebung muss entscheiden */
2600 	     { for (i=0; ustart[i]!=nil; i++)
2601 		 { run=ustart[i]->next->invers->prev;
2602 		   j=ende=0;
2603 		   while (!ende)
2604 		     {
2605 		       for (k=0; lstart[k] != nil; k++) if (lstart[k]==run) ende=1;
2606 		       if (!ende) { j++; run=run->prev->invers->prev->invers->prev; }
2607 		     }
2608 		   if (j<code[18])  {code[3]=c3; code[11]=c11; return(0);}
2609 		   if (j==code[18]) {j_gleich1 = 1;}            /* TH */
2610                  }
2611 	       if (gleich) {
2612 		 for (i=0; lstart[i]!=nil; i++)
2613 		   { run=lstart[i]->next->invers->prev;
2614 		     j=ende=0;
2615 		     while (!ende)
2616 		       {
2617 		         for (k=0; ustart[k] != nil; k++) if (ustart[k]==run) ende=1;
2618 		         if (!ende) { j++; run=run->prev->invers->prev->invers->prev; }
2619 		       }
2620 		     if (j<code[18]) {code[3]=c3; code[11]=c11; return(0);}
2621                      if (j==code[18]) {j_gleich2 = 1;}     /* TH */
2622                    }
2623                }
2624                else {j_gleich2 = 1;}     /* TH */
2625 	     } /* ende test2==0 */
2626 	 } /* ende test==0 */
2627 
2628 
2629 /* nun fuer die gespiegelte version: */
2630 
2631 j_gleich3 = j_gleich4 = 0;          /* TH */
2632 if ((test3=codecmp_kn(lscode,code+2,8)) < 0) { code[3]=c3; code[11]=c11; return(0); }
2633    else if (test3==0)
2634          { if ((test4=codecmp_kn(uscode,code+10,8)) < 0) {code[3]=c3; code[11]=c11; return(0);}
2635 	   else if (test4==0) /* d.h. die verschiebung muss entscheiden */
2636 	     {
2637 	       for (i=0; us_start[i]!=nil; i++)
2638 		 { run=us_start[i]->prev->invers->next;
2639 		   j=ende=0;
2640 		   while (!ende)
2641 		     { for (k=0; ls_start[k] != nil; k++) if (ls_start[k]==run) ende=1;
2642 		       if (!ende) { j++; run=run->next->invers->next->invers->next; }
2643 		     }
2644 		   if (j<code[18]) {code[3]=c3; code[11]=c11; return(0);}
2645                    if (j==code[18]) {j_gleich3 = 1;}         /* TH */
2646 		 }
2647 	       if (gleich) {
2648 		 for (i=0; ls_start[i]!=nil; i++)
2649 		 { run=ls_start[i]->prev->invers->next;
2650 		   j=ende=0;
2651 		   while (!ende)
2652 		     { for (k=0; us_start[k] != nil; k++) if (us_start[k]==run) ende=1;
2653 		       if (!ende) { j++; run=run->next->invers->next->invers->next; }
2654 		     }
2655 		   if (j<code[18]) {code[3]=c3; code[11]=c11; return(0);}
2656                    if (j==code[18]) {j_gleich4 = 1;}
2657 		 }
2658                }
2659                else {j_gleich4 = 1;}      /* TH */
2660 	     } /* ende test2==0 */
2661 	 } /* ende test==0 */
2662 
2663 code[3]=c3; code[11]=c11;
2664 
2665 /* TH: Auswertung */
2666 returnwert = 1;
2667 if (test==0 && test2==0 && j_gleich1 && j_gleich2) {returnwert=2;}
2668 if (test3==0 && test4==0 && j_gleich3 && j_gleich4) {
2669   if (returnwert==1) {returnwert=4;} else {returnwert=6;}
2670 }
2671 return(returnwert);
2672 
2673 }
2674 
2675 
2676 
2677 /***********************SUCHESTART_REKO********************************/
2678 
suchestart_reko(KANTE * start,int * fuenfecke)2679 KANTE *suchestart_reko( KANTE *start, int *fuenfecke)
2680 /* belegt eine sequenz und sucht die kanonische Kante mit dem kleinsten Namen
2681    arbeitet "invers", d.h. es wird als Innenrand gesehen, der gefuellt werden
2682    muss. Wird aufgerufen fuer Brille und Sandwich. Start muss eine Kante sein, die
2683    ins innere zeigt.
2684    Funktioniert wie suchestart, nur dass mininame statt name benutzt wird und die
2685    Anzahl der 5-Ecke auch berechnet wird */
2686 
2687 {
2688 int i, j, k, zaehler, position, sqlaenge;
2689 KANTE *run;
2690 int sequenz[7];
2691 KANTE *seqkanten[7];
2692 int puffer[7];
2693 char kan[7];
2694 
2695 
2696 
2697 while (start->next->invers->next->invers->next->mininame == aussen)
2698                       start=start->next->invers->next->invers->next;
2699 /* Sucht 2 Kanten hintereinander nach aussen -- zu unterscheiden vom namen aussen, was
2700    auch nach innen heissen kann. Duerfte nur fuer bauchbinden eine Endlosschleife sein */
2701 
2702 for (i=0; i<7; i++) { sequenz[i]=leer; seqkanten[i]=nil; kan[i]=0; }
2703 
2704 sqlaenge=0;
2705 position=0;
2706 seqkanten[0]=start;
2707 
2708 
2709 for (zaehler=1, run=start;
2710      run->prev->invers->prev->invers->prev->mininame == aussen;
2711      run=run->prev->invers->prev->invers->prev) zaehler++;
2712 sequenz[0]=zaehler; position=1; seqkanten[1]=nil;
2713 for (run=run->prev->invers->prev->invers->prev->invers->prev; run->mininame != aussen;
2714      run=run->invers->prev)
2715 { sequenz[position]=0; position++; seqkanten[position]=nil; }
2716 /* naechste Kante vor nicht-0-sequenz suchen -- entsprechende innenkanten gibt es nicht
2717    und muessen sich dementsprechend auch nicht gemerkt werden */
2718 
2719 
2720 while (run != start)
2721 {
2722 seqkanten[position]=run;
2723 for (zaehler=1;
2724      run->prev->invers->prev->invers->prev->mininame == aussen;
2725      run=run->prev->invers->prev->invers->prev) { zaehler++; }
2726 sequenz[position]=zaehler; position++; seqkanten[position]=nil;
2727 for (run=run->prev->invers->prev->invers->prev->invers->prev; run->mininame != aussen;
2728      run=run->invers->prev)
2729 { sequenz[position]=0; position++; seqkanten[position]=nil; }
2730 }
2731 
2732 
2733 sequenz[position]=leer; seqkanten[position]=nil;
2734 sqlaenge=position;
2735 
2736 *fuenfecke=6-sqlaenge;
2737 
2738 kan[0]=sequenz_kanonisch(sequenz);
2739 
2740 
2741 for (i=0; sequenz[i] != leer; i++)
2742   { for (j=i, k=0; sequenz[j]!=leer; j++, k++) puffer[k]=sequenz[j];
2743     for (j=0; j<i; j++, k++) puffer[k]=sequenz[j];
2744     puffer[k]=leer;
2745     kan[i]=sequenz_kanonisch(puffer);
2746   }
2747 
2748 
2749 
2750 for (i=0, run=nil; sequenz[i] != leer; i++)
2751   { if (kan[i])
2752       if ((run==nil) || (seqkanten[i]->dummy < run->dummy)) run=seqkanten[i];
2753       /* dummy ersetzt ursprung */
2754   }
2755 
2756 /* Jetzt die vorige Innenkante suchen, um rechts davon dann einfuegen zu koennen */
2757 for (run=run->next->invers->next->invers->next; run->mininame != aussen; run=run->invers->next);
2758 
2759 
2760 return(run);
2761 
2762 }
2763 
2764 /**********************CHECKSIZE_AND_MARK**************************************/
2765 
2766 /* bestimmt die groesse der flaeche links von edge -- ist da keine gibt's Probleme
2767    ausserdem setzt er fuer alle kanten, so dass diese flaeche links davon ist, dummy
2768    auf 1*/
2769 
checksize_and_mark(KANTE * edge)2770 int checksize_and_mark( KANTE* edge)
2771 {
2772 KANTE *run;
2773 int zaehler=1;
2774 
2775 edge->noleft=1;
2776 for (run=edge->invers->next; run != edge; run=run->invers->next) {run->noleft=1; zaehler++;}
2777 return(zaehler);
2778 }
2779 
2780 
2781 
2782 
2783 /**************************REKO_PATCH*****************************/
2784 
reko_patch(KANTE * anfang,KNOTENTYP code[],int fuenfecke)2785 void reko_patch(KANTE *anfang,KNOTENTYP code[],int fuenfecke)
2786 {
2787 int i, position, zaehler, z2;
2788 KANTE *run, *merke;
2789 
2790 
2791 /* wenn bei einer kante hier noleft gesetzt ist, so heisst das, dass
2792    links davon keine Flaeche mehr ist. Bei den zur Brille gehoerenden Kanten
2793    ist das teilweise falsch --macht aber nichts */
2794 
2795 for (i=0; i<=fuenfecke; i++) code[i]=0;
2796 
2797 position=0; run=anfang;
2798 zaehler=1;
2799 
2800 while (position<fuenfecke)
2801   {
2802     if (checksize_and_mark(run)==5) { code[position]=zaehler; position++;
2803 					  if (position==fuenfecke) return; }
2804     zaehler++;
2805     merke=run->invers; run=run->prev; z2=1;
2806     while ((merke != run) && (run->noleft) && (z2 <=6))
2807       { run=run->invers->prev; z2++; }
2808     if ((merke==run) && (run->noleft)) /* dann muss die letzte flaeche das letzte 5-eck sein */
2809       { code[position]=zaehler; position++;
2810 	if (position<fuenfecke)
2811 		{ fprintf(stderr," ERROR in reko_patch ! Patch empty and missing 5-gon !\n"); exit(32); }
2812       }
2813   }
2814 }
2815 
2816 
2817 
2818 /**********************BRILLE_REKO*******************************/
2819 
2820 /* berechnet den minimalen Code, der sich aus der bei "anfangskante"
2821    beginnenden Brille ergibt */
2822 /* TH:  Die Funktion wurde so geaendert, dass sie
2823    0 zurueckgibt, wenn code > minimaler Code (wie bisher)
2824    1 zurueckgibt, wenn code < minimaler Code (wie bisher)
2825    2 zurueckgibt, wenn code== minimaler Code (Automorphismus existiert) */
2826 
brille_reko(PLANMAP map,KNOTENTYP * code,KANTE * anfangskante)2827 int brille_reko(PLANMAP map,KNOTENTYP *code,KANTE *anfangskante)
2828 {
2829 int i,j, l1, l2, l3, fuenfecke, vergleichsanfang, test;
2830 KANTE *run, *startkante1, *startkante2, *startkante3, *anfang;
2831 KNOTENTYP testcode[6];
2832 
2833 
2834 l1=code[2]; l3=code[3]; l2=code[0]-l1-l3;
2835 
2836 for (i=1; i<=map[0][0].name; i++) for (j=0;j<3; j++) { map[i][j].dummy=map[i][j].noleft=0;
2837 						       map[i][j].mininame=1; }
2838 
2839 /* markieren der Brille: */
2840 
2841 anfangskante->mininame=anfangskante->noleft=anfangskante->invers->noleft=1;
2842 anfangskante->invers->mininame=l1;
2843 
2844 for (i=1, run=anfangskante; i<code[0]; i++)
2845   { run=run->invers->prev;
2846     run->noleft=run->invers->noleft=1;
2847     run->mininame=i+1;
2848     run->dummy=run->prev->dummy=run->next->dummy=i;
2849     run->invers->mininame=i;
2850     if (i!=l1) run->prev->mininame=aussen;
2851     i++;
2852     if (i<code[0])
2853       {
2854       run=run->invers->next;
2855       run->noleft=run->invers->noleft=1;
2856       run->dummy=run->prev->dummy=run->next->dummy=i;
2857       run->mininame=i+1;
2858       run->invers->mininame=i;
2859       if (i!=l1) run->next->mininame=aussen;
2860       }
2861   }
2862 
2863 /*  reparieren: */ run->mininame=l1+l2;
2864 
2865 if (l1%2) { startkante1=anfangskante->invers->next;
2866 	    startkante2=anfangskante->invers->prev->invers->prev; }
2867    else   { startkante2=anfangskante->invers->next;
2868 	    startkante1=anfangskante->invers->prev->invers->prev; }
2869 
2870 if (code[0]%2) /* d.h. der knoten, bei dem run ist, ist gerade */
2871   { if (l3%2) startkante3=run->next;
2872          else startkante3=run->prev->invers->prev; }
2873   else
2874   { if (l3%2) startkante3=run->prev;
2875         else  startkante3=run->next->invers->next; }
2876 
2877 vergleichsanfang=4;
2878 anfang=suchestart_reko( startkante1, &fuenfecke);
2879 reko_patch(anfang,testcode,fuenfecke);
2880 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
2881 if (test>0) return(1);
2882 vergleichsanfang+=fuenfecke;
2883 anfang=suchestart_reko( startkante2, &fuenfecke);
2884 reko_patch(anfang,testcode,fuenfecke);
2885 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
2886 if (test>0) return(1);
2887 vergleichsanfang+=fuenfecke;
2888 anfang=suchestart_reko( startkante3, &fuenfecke);
2889 reko_patch(anfang,testcode,fuenfecke);
2890 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
2891 if (test==0) return(2);
2892 return(1);
2893 }
2894 
2895 /***********************SUCHESTART_REKO_SP********************************/
2896 
suchestart_reko_sp(KANTE * start,int * fuenfecke)2897 KANTE *suchestart_reko_sp( KANTE *start, int *fuenfecke)
2898 /* Wie suchestart_reko -- nur die spiegelversion */
2899 
2900 {
2901 int i, j, k, zaehler, position, sqlaenge;
2902 KANTE *run;
2903 int sequenz[7];
2904 KANTE *seqkanten[7];
2905 int puffer[7];
2906 char kan[7];
2907 
2908 
2909 
2910 while (start->prev->invers->prev->invers->prev->mininame == aussen)
2911                       start=start->prev->invers->prev->invers->prev;
2912 /* Sucht 2 Kanten hintereinander nach aussen -- zu unterscheiden vom namen aussen, was
2913    auch nach innen heissen kann. Duerfte nur fuer bauchbinden eine Endlosschleife sein */
2914 
2915 for (i=0; i<7; i++) { sequenz[i]=leer; seqkanten[i]=nil; kan[i]=0; }
2916 
2917 sqlaenge=0;
2918 position=0;
2919 seqkanten[0]=start;
2920 
2921 
2922 for (zaehler=1, run=start;
2923      run->next->invers->next->invers->next->mininame == aussen;
2924      run=run->next->invers->next->invers->next) zaehler++;
2925 sequenz[0]=zaehler; position=1; seqkanten[1]=nil;
2926 for (run=run->next->invers->next->invers->next->invers->next; run->mininame != aussen;
2927      run=run->invers->next)
2928 { sequenz[position]=0; position++; seqkanten[position]=nil; }
2929 /* naechste Kante vor nicht-0-sequenz suchen -- entsprechende innenkanten gibt es nicht
2930    und muessen sich dementsprechend auch nicht gemerkt werden */
2931 
2932 
2933 while (run != start)
2934 {
2935 seqkanten[position]=run;
2936 for (zaehler=1;
2937      run->next->invers->next->invers->next->mininame == aussen;
2938      run=run->next->invers->next->invers->next) { zaehler++; }
2939 sequenz[position]=zaehler; position++; seqkanten[position]=nil;
2940 for (run=run->next->invers->next->invers->next->invers->next; run->mininame != aussen;
2941      run=run->invers->next)
2942 { sequenz[position]=0; position++; seqkanten[position]=nil; }
2943 }
2944 
2945 
2946 sequenz[position]=leer; seqkanten[position]=nil;
2947 sqlaenge=position;
2948 
2949 *fuenfecke=6-sqlaenge;
2950 
2951 kan[0]=sequenz_kanonisch(sequenz);
2952 
2953 
2954 for (i=0; sequenz[i] != leer; i++)
2955   { for (j=i, k=0; sequenz[j]!=leer; j++, k++) puffer[k]=sequenz[j];
2956     for (j=0; j<i; j++, k++) puffer[k]=sequenz[j];
2957     puffer[k]=leer;
2958     kan[i]=sequenz_kanonisch(puffer);
2959   }
2960 
2961 
2962 
2963 for (i=0, run=nil; sequenz[i] != leer; i++)
2964   { if (kan[i])
2965       if ((run==nil) || (seqkanten[i]->dummy < run->dummy)) run=seqkanten[i];
2966       /* dummy ersetzt ursprung */
2967   }
2968 
2969 /* Jetzt die vorige Innenkante suchen, um links (spiegel !!) davon dann einfuegen zu koennen */
2970 for (run=run->prev->invers->prev->invers->prev; run->mininame != aussen; run=run->invers->prev);
2971 
2972 return(run);
2973 
2974 }
2975 
2976 /**********************CHECKSIZE_AND_MARK_SP**************************************/
2977 
2978 /* bestimmt die groesse der flaeche rechts von edge -- ist da keine gibt's Probleme
2979    ausserdem setzt er fuer alle kanten, so dass diese flaeche rechts davon ist,
2980    noright auf 1  */
2981 
checksize_and_mark_sp(KANTE * edge)2982 int checksize_and_mark_sp( KANTE* edge)
2983 {
2984 KANTE *run;
2985 int zaehler=1;
2986 
2987 edge->noright=1;
2988 for (run=edge->invers->prev; run != edge; run=run->invers->prev) {run->noright=1; zaehler++;}
2989 return(zaehler);
2990 }
2991 
2992 
2993 
2994 
2995 /**************************REKO_PATCH_SP*****************************/
2996 
reko_patch_sp(KANTE * anfang,KNOTENTYP code[],int fuenfecke)2997 void reko_patch_sp(KANTE *anfang,KNOTENTYP code[],int fuenfecke)
2998 {
2999 int i, position, zaehler, z2;
3000 KANTE *run, *merke;
3001 
3002 
3003 /* wenn bei einer kante hier noright gesetzt ist, so heisst das, dass
3004    rechts davon keine Flaeche mehr ist. Bei den zur Brille gehoerenden Kanten
3005    ist das teilweise falsch --macht aber nichts */
3006 
3007 for (i=0; i<=fuenfecke; i++) code[i]=0;
3008 
3009 position=0; run=anfang;
3010 zaehler=1;
3011 
3012 while (position<fuenfecke)
3013   { if (checksize_and_mark_sp(run)==5) { code[position]=zaehler; position++;
3014 					     if (position==fuenfecke) return; }
3015     zaehler++;
3016     merke=run->invers; run=run->next; z2=1;
3017     while ((merke != run) && (run->noright) && (z2 <=6))
3018       { run=run->invers->next; z2++; }
3019     if ((merke==run) && (run->noright)) /* dann muss die letzte flaeche das letzte 5-eck sein */
3020       { code[position]=zaehler; position++;
3021 	if (position<fuenfecke)
3022 		{ fprintf(stderr," ERROR in reko_patch_sp ! Patch empty and missing 5-gon !\n"); exit(33); }
3023       }
3024   }
3025 }
3026 
3027 
3028 
3029 /***********************BRILLE_SP_REKO*******************************/
3030 
3031 /* berechnet den minimalen Code, der sich aus der bei "anfangskante"
3032    beginnenden Brille ergibt -- allerdings unter der Voraussetzung,
3033    dass alles spiegelverkehrt gesehen wird */
3034 /* TH:  Die Funktion wurde so geaendert, dass sie
3035    0 zurueckgibt, wenn code > minimaler Code (wie bisher)
3036    1 zurueckgibt, wenn code < minimaler Code (wie bisher)
3037    2 zurueckgibt, wenn code== minimaler Code (Automorphismus existiert) */
3038 
brille_sp_reko(PLANMAP map,KNOTENTYP * code,KANTE * anfangskante)3039 int brille_sp_reko(PLANMAP map,KNOTENTYP *code,KANTE *anfangskante)
3040 {
3041 int i,j, l1, l2, l3, fuenfecke, vergleichsanfang, test;
3042 KANTE *run, *startkante1, *startkante2, *startkante3, *anfang;
3043 KNOTENTYP testcode[6];
3044 
3045 
3046 
3047 l1=code[2]; l3=code[3]; l2=code[0]-l1-l3;
3048 
3049 for (i=1; i<=map[0][0].name; i++) for (j=0;j<3; j++) { map[i][j].dummy=map[i][j].noright=0;
3050 						       map[i][j].mininame=1; }
3051 
3052 /* markieren der Brille: */
3053 
3054 anfangskante->mininame=anfangskante->noright=anfangskante->invers->noright=1;
3055 anfangskante->invers->mininame=l1;
3056 
3057 for (i=1, run=anfangskante; i<code[0]; i++)
3058   { run=run->invers->next;
3059     run->noright=run->invers->noright=1;
3060     run->mininame=i+1;
3061     run->dummy=run->prev->dummy=run->next->dummy=i;
3062     run->invers->mininame=i;
3063     if (i!=l1) run->next->mininame=aussen;
3064     i++;
3065     if (i<code[0])
3066       {
3067       run=run->invers->prev;
3068       run->noright=run->invers->noright=1;
3069       run->dummy=run->prev->dummy=run->next->dummy=i;
3070       run->mininame=i+1;
3071       run->invers->mininame=i;
3072       if (i!=l1) run->prev->mininame=aussen;
3073       }
3074   }
3075 
3076 /*  reparieren: */ run->mininame=l1+l2;
3077 
3078 if (l1%2) { startkante1=anfangskante->invers->prev;
3079 	    startkante2=anfangskante->invers->next->invers->next; }
3080    else   { startkante2=anfangskante->invers->prev;
3081 	    startkante1=anfangskante->invers->next->invers->next; }
3082 
3083 if (code[0]%2) /* d.h. der knoten, bei dem run ist, ist gerade */
3084   { if (l3%2) startkante3=run->prev;
3085          else startkante3=run->next->invers->next; }
3086   else
3087   { if (l3%2) startkante3=run->next;
3088         else  startkante3=run->prev->invers->prev; }
3089 
3090 
3091 vergleichsanfang=4;
3092 anfang=suchestart_reko_sp( startkante1, &fuenfecke);
3093 reko_patch_sp(anfang,testcode,fuenfecke);
3094 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3095 if (test>0) return(1);
3096 vergleichsanfang+=fuenfecke;
3097 anfang=suchestart_reko_sp( startkante2, &fuenfecke);
3098 reko_patch_sp(anfang,testcode,fuenfecke);
3099 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3100 if (test>0) return(1);
3101 vergleichsanfang+=fuenfecke;
3102 anfang=suchestart_reko_sp( startkante3, &fuenfecke);
3103 reko_patch_sp(anfang,testcode,fuenfecke);
3104 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3105 if (test==0) return(2);
3106 
3107 return(1);
3108 }
3109 
3110 
3111 
3112 /***********************SANDWICH_REKO*******************************/
3113 
3114 /* berechnet den minimalen Code, der sich aus dem bei "anfangskante"
3115    beginnenden Sandwich ergibt */
3116 /* TH:  Die Funktion wurde so geaendert, dass sie
3117    0 zurueckgibt, wenn code > minimaler Code (wie bisher)
3118    1 zurueckgibt, wenn code < minimaler Code (wie bisher)
3119    2 zurueckgibt, wenn code== minimaler Code (Automorphismus existiert) */
3120 
sandwich_reko(PLANMAP map,KNOTENTYP * code,KANTE * anfangskante)3121 int sandwich_reko(PLANMAP map,KNOTENTYP *code,KANTE *anfangskante)
3122 {
3123 int i,j, l1, l2, l1_p_l2, fuenfecke, vergleichsanfang, test;
3124 KANTE *run, *startkante1, *startkante2, *startkante3, *anfang;
3125 KNOTENTYP testcode[6];
3126 
3127 
3128 l1=code[2]; l2=code[3];
3129 l1_p_l2 = l1+l2;
3130 
3131 for (i=1; i<=map[0][0].name; i++) for (j=0;j<3; j++) { map[i][j].dummy=map[i][j].noleft=0;
3132 						       map[i][j].mininame=1; }
3133 
3134 /* markieren der Brille: */
3135 
3136 anfangskante->mininame=anfangskante->noleft=anfangskante->invers->noleft=1;
3137 anfangskante->invers->mininame=l1_p_l2;
3138 
3139 for (i=1, run=anfangskante; i<code[0]; i++)
3140   { run=run->invers->prev;
3141     run->noleft=run->invers->noleft=1;
3142     run->mininame=i+1;
3143     run->dummy=run->prev->dummy=run->next->dummy=i;
3144     run->invers->mininame=i;
3145     if (i != l1_p_l2) run->prev->mininame=aussen;
3146     i++;
3147     if (i<code[0])
3148       {
3149       run=run->invers->next;
3150       run->noleft=run->invers->noleft=1;
3151       run->dummy=run->prev->dummy=run->next->dummy=i;
3152       run->mininame=i+1;
3153       run->invers->mininame=i;
3154       if (i != l1_p_l2) run->next->mininame=aussen;
3155       }
3156   }
3157 
3158 /*  reparieren: */ run->mininame=l1;
3159 
3160 /* l1 ist immer >= 3, also geht das folgende: */
3161 
3162 if (l1_p_l2%2) { startkante1=anfangskante->invers->next;
3163 		 startkante3=startkante1->next->invers->prev;
3164 		 if (l2>1) startkante2=anfangskante->prev->invers->next;
3165 		 else /* dann ist l3 > 1 */
3166 		   startkante2=anfangskante->next->invers->prev; }
3167    else
3168                { startkante3=anfangskante->invers->next;
3169 		 startkante1=startkante3->next->invers->prev;
3170 		 if (l2>1) startkante2=anfangskante->next->invers->prev;
3171 		 else /* dann ist l3 > 1 */
3172 		   startkante2=anfangskante->prev->invers->next; }
3173 
3174 
3175 vergleichsanfang=4;
3176 anfang=suchestart_reko( startkante1, &fuenfecke);
3177 reko_patch(anfang,testcode,fuenfecke);
3178 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3179 if (test>0) return(1);
3180 vergleichsanfang+=fuenfecke;
3181 anfang=suchestart_reko( startkante2, &fuenfecke);
3182 reko_patch(anfang,testcode,fuenfecke);
3183 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3184 if (test>0) return(1);
3185 vergleichsanfang+=fuenfecke;
3186 anfang=suchestart_reko( startkante3, &fuenfecke);
3187 reko_patch(anfang,testcode,fuenfecke);
3188 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3189 if (test==0) return(2);
3190 return(1);
3191 }
3192 
3193 
3194 /***********************SANDWICH_REKO_SP*******************************/
3195 
3196 /* berechnet den minimalen Code, der sich aus dem bei "anfangskante"
3197    beginnenden Sandwich ergibt, wenn man es spiegelt */
3198 /* TH:  Die Funktion wurde so geaendert, dass sie
3199    0 zurueckgibt, wenn code > minimaler Code (wie bisher)
3200    1 zurueckgibt, wenn code < minimaler Code (wie bisher)
3201    2 zurueckgibt, wenn code== minimaler Code (Automorphismus existiert) */
3202 
sandwich_reko_sp(PLANMAP map,KNOTENTYP * code,KANTE * anfangskante)3203 int sandwich_reko_sp(PLANMAP map,KNOTENTYP *code,KANTE *anfangskante)
3204 {
3205 int i,j, l1, l2, l1_p_l2, fuenfecke, vergleichsanfang, test;
3206 KANTE *run, *startkante1, *startkante2, *startkante3, *anfang;
3207 KNOTENTYP testcode[6];
3208 
3209 
3210 l1=code[2]; l2=code[3];
3211 l1_p_l2 = l1+l2;
3212 
3213 for (i=1; i<=map[0][0].name; i++) for (j=0;j<3; j++) { map[i][j].dummy=map[i][j].noright=0;
3214 						       map[i][j].mininame=1; }
3215 
3216 /* markieren der Brille: */
3217 
3218 anfangskante->mininame=anfangskante->noright=anfangskante->invers->noright=1;
3219 anfangskante->invers->mininame=l1_p_l2;
3220 
3221 for (i=1, run=anfangskante; i<code[0]; i++)
3222   { run=run->invers->next;
3223     run->noright=run->invers->noright=1;
3224     run->mininame=i+1;
3225     run->dummy=run->prev->dummy=run->next->dummy=i;
3226     run->invers->mininame=i;
3227     if (i != l1_p_l2) run->next->mininame=aussen;
3228     i++;
3229     if (i<code[0])
3230       {
3231       run=run->invers->prev;
3232       run->noright=run->invers->noright=1;
3233       run->dummy=run->prev->dummy=run->next->dummy=i;
3234       run->mininame=i+1;
3235       run->invers->mininame=i;
3236       if (i != l1_p_l2) run->prev->mininame=aussen;
3237       }
3238   }
3239 
3240 /*  reparieren: */ run->mininame=l1;
3241 
3242 /* l1 ist immer >= 3, also geht das folgende: */
3243 
3244 if (l1_p_l2%2) { startkante1=anfangskante->invers->prev;
3245 		 startkante3=startkante1->prev->invers->next;
3246 		 if (l2>1) startkante2=anfangskante->next->invers->prev;
3247 		 else /* dann ist l3 > 1 */
3248 		   startkante2=anfangskante->prev->invers->next; }
3249    else
3250                { startkante3=anfangskante->invers->prev;
3251 		 startkante1=startkante3->prev->invers->next;
3252 		 if (l2>1) startkante2=anfangskante->prev->invers->next;
3253 		 else /* dann ist l3 > 1 */
3254 		   startkante2=anfangskante->next->invers->prev; }
3255 
3256 
3257 vergleichsanfang=4;
3258 anfang=suchestart_reko_sp( startkante1, &fuenfecke);
3259 reko_patch_sp(anfang,testcode,fuenfecke);
3260 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3261 if (test>0) return(1);
3262 vergleichsanfang+=fuenfecke;
3263 anfang=suchestart_reko_sp( startkante2, &fuenfecke);
3264 reko_patch_sp(anfang,testcode,fuenfecke);
3265 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3266 if (test>0) return(1);
3267 vergleichsanfang+=fuenfecke;
3268 anfang=suchestart_reko_sp( startkante3, &fuenfecke);
3269 reko_patch_sp(anfang,testcode,fuenfecke);
3270 if ((test=codecmp_kn(testcode,code+vergleichsanfang,fuenfecke))<0) return(0);
3271 if (test==0) return(2);
3272 
3273 return(1);
3274 }
3275 
3276 
3277 
3278 /*********************bilde_f*****TH***********************************/
3279 
3280 /* Die Funktion bilde_f bildet den kompletten Automorphismus f, der
3281    die Kante k1 in die Kante k2 ueberfuehrt. Dabei muss der Automorphismus
3282    ordnungserhaltend sein, es muss sich also um eine Drehung handeln.
3283    Das Fulleren, auf dem der Automorphismus berechnet wird, besitzt anz
3284    Ecken.  Es wird ein einfacher Backtrackingalgorithmus verwendet.
3285    Bei der Anwendung dieser Funktion ist nicht der gesamte Automorphismus
3286    interessant, sondern nur eine Auswahl von Ecken, deren Bilder errechnet
3287    werden sollen. Versuche, durch eine geschickte Auswahl der Ecken,
3288    deren Bildpunkte errechnet werden, eine Laufzeitverbesserung zu erhalten,
3289    schlagen fehl. */
3290 
3291 /* Die folgende Prozedur enthaelt den Rekursionsschritt */
3292 
bilde_f_rek(KNOTENTYP * f,KANTE * k1,KANTE * k2)3293 void bilde_f_rek(KNOTENTYP *f, KANTE *k1, KANTE *k2) {
3294   KNOTENTYP u;
3295   k1 = k1->invers->prev;
3296   k2 = k2->invers->prev;   /* k1 und k2 im Gleichschritt nach rechts */
3297   u = k1->name;            /* von u wird der Funktionswert f[u] berechnet */
3298   if (!(f[u])) {          /* Funktionswert noch nicht bekannt */
3299     f[u] = k2->name;
3300     bilde_f_rek(f,k1,k2);  /* von u ausgehend weitere Funktionswerte ermitteln */
3301   }
3302   k1 = k1->prev;           /* k1 und k2 im Gleichschritt nach links */
3303   k2 = k2->prev;           /* denn: (k->invers->prev)->prev = k->invers->next */
3304   u = k1->name;
3305   if (!(f[u])) {
3306     f[u] = k2->name;
3307     bilde_f_rek(f,k1,k2);
3308   }
3309 }
3310 
3311 /* Die folgende Prozedur enthaelt den Rekursionsanfang */
3312 
bilde_f(KNOTENTYP * f,KANTE * k1,KANTE * k2,KNOTENTYP anz)3313 void bilde_f(KNOTENTYP *f, KANTE *k1, KANTE *k2, KNOTENTYP anz) {
3314   KNOTENTYP i;
3315   for (i=1; i<=anz; i++) {f[i] = 0;}   /* Funktionstabelle loeschen */
3316   f[k1->ursprung] = k2->ursprung;
3317   f[k1->name]     = k2->name;           /* k1 wird auf k2 abgebildet */
3318   bilde_f_rek(f,k1,k2);
3319 }
3320 
3321 /*********************bilde_f_sp*****TH***********************************/
3322 
3323 /* Die Funktion bilde_f_sp bildet den kompletten Automorphismus f, der
3324    die Kante k1 in die Kante k2 ueberfuehrt. Dabei darf der Automorphismus
3325    NICHT ordnungserhaltend sein, es muss sich also um eine Spiegelung oder
3326    Drehspiegelung handeln. Dies ist der einzige Unterschied zu bilde_f. */
3327 
3328 /* Die folgende Prozedur enthaelt den Rekursionsschritt */
3329 
bilde_f_sp_rek(KNOTENTYP * f,KANTE * k1,KANTE * k2)3330 void bilde_f_sp_rek(KNOTENTYP *f, KANTE *k1, KANTE *k2) {
3331   KNOTENTYP u;
3332   k1 = k1->invers->prev;
3333   k2 = k2->invers->next;   /* k1 und k2 spiegelverkehrt nach rechts und links */
3334   u = k1->name;            /* von u wird der Funktionswert f[u] berechnet */
3335   if (!(f[u])) {           /* Funktionswert noch nicht bekannt */
3336     f[u] = k2->name;
3337     bilde_f_sp_rek(f,k1,k2);  /* von u ausgehend weitere Funktionswerte ermitteln */
3338   }
3339   k1 = k1->prev;           /* k1 und k2 spiegelverkehrt nach links und rechts */
3340   k2 = k2->next;           /* denn: (k->invers->next)->next = k->invers->prev */
3341   u = k1->name;
3342   if (!(f[u])) {
3343     f[u] = k2->name;
3344     bilde_f_sp_rek(f,k1,k2);
3345   }
3346 }
3347 
3348 /* Die folgende Prozedur enthaelt den Rekursionsanfang */
3349 
bilde_f_sp(KNOTENTYP * f,KANTE * k1,KANTE * k2,KNOTENTYP anz)3350 void bilde_f_sp(KNOTENTYP *f, KANTE *k1, KANTE *k2, KNOTENTYP anz) {
3351   KNOTENTYP i;
3352   for (i=1; i<=anz; i++) {f[i] = 0;}   /* Funktionstabelle loeschen */
3353   f[k1->ursprung] = k2->ursprung;
3354   f[k1->name]     = k2->name;           /* k1 wird auf k2 abgebildet */
3355   bilde_f_sp_rek(f,k1,k2);
3356 }
3357 
3358 
3359 /*********************bilde_f_und_g_sp*****TH***********************************/
3360 
3361 /* Die Funktion bilde_f_und_g_sp bildet die komplette Funktion f, die die Kante
3362    k1 in die Kante k2 ueberfuehrt, und simultan die Funktion g, die die Kante
3363    k2 in die Kante k1 ueberfuehrt. Beide Funktionen sind NICHT ordnungserhaltend.
3364    Die Funktion prueft, ob g die Umkehrfunktion von f ist. Ist sie es, so liefert
3365    bild_f_und_g_sp den Wert 1, andernfalls den Wert 0.
3366    Das Fulleren, auf dem die Funktion berechnet wird, besitzt anz Ecken.
3367    Die Inhalte des Arrays g, die in der vorliegenden Funktion berechnet werden,
3368    werden in der uebergeordneten Prozedur minitest nicht gebraucht. Deshalb waere es
3369    eigentlich nicht notwendig, einen Zeiger auf dieses Array zu uebergeben. Es wuerde
3370    ausreichen, das Array innerhalb der Funktion bilde_f_und_g_sp lokal zu definieren.
3371    Da die Funktion aber haeufig aufgerufen wird, wuerde dies viel Zeit in Anspruch
3372    nehmen.   */
3373 
3374 /* Die folgende Prozedur enthaelt den Rekursionsschritt */
3375 
bilde_f_und_g_sp_rek(KNOTENTYP * f,KNOTENTYP * g,KANTE * k1,KANTE * k2)3376 BOOL bilde_f_und_g_sp_rek(KNOTENTYP *f, KNOTENTYP *g, KANTE *k1, KANTE *k2) {
3377   KNOTENTYP u,v;
3378   k1 = k1->invers->prev;
3379   k2 = k2->invers->next;   /* k1 und k2 spiegelverkehrt nach rechts und links */
3380   u = k1->name;            /* von u wird der Funktionswert f[u] berechnet */
3381   v = k2->name;
3382   if (!(f[u])) {          /* Funktionswert noch nicht bekannt */
3383     f[u] = v;
3384     if (g[v]) {return(0);}    /* Widerspruch gefunden */
3385     g[v] = u;
3386     if (!bilde_f_und_g_sp_rek(f,g,k1,k2))  {return(0);}  /* weitere Funktionswerte: Widerspruch? */
3387   }
3388   else {
3389     if (!(g[v])) {return(0);}     /* Widerspruch gefunden. Diese Abfrage koennte aber auch
3390                                       entfallen, denn wenn ein Wert von g noch nicht festgelegt
3391         ist, obwohl der zugehoerige Wert von f bereits feststeht, so wird an anderer Stelle ein
3392         Wert von g zuviel festgelegt sein, obwohl der zugehoerige Wert von f noch nicht feststeht */
3393   }
3394   k1 = k1->prev;           /* k1 und k2 spiegelverkehrt nach links und rechts */
3395   k2 = k2->next;           /* denn: (k->invers->next)->next = k->invers->prev */
3396   u = k1->name;
3397   v = k2->name;
3398   if (!(f[u])) {
3399     f[u] = v;
3400     if (g[v]) {return(0);}
3401     g[v] = u;
3402     if (!bilde_f_und_g_sp_rek(f,g,k1,k2))  {return(0);}
3403   }
3404   else {
3405     if (!(g[v])) {return(0);}
3406   }
3407   return(1);       /* keinen Widerspruch festgestellt */
3408 }
3409 
3410 /* Die folgende Prozedur enthaelt den Rekursionsanfang */
3411 
bilde_f_und_g_sp(KNOTENTYP * f,KNOTENTYP * g,KANTE * k1,KANTE * k2,KNOTENTYP anz)3412 BOOL bilde_f_und_g_sp(KNOTENTYP *f, KNOTENTYP *g, KANTE *k1, KANTE *k2, KNOTENTYP anz) {
3413   KNOTENTYP i;
3414   for (i=1; i<=anz; i++) {f[i]=0; g[i]=0;}   /* Funktionstabellen loeschen */
3415   f[k1->ursprung] = k2->ursprung;
3416   f[k1->name]     = k2->name;           /* f: k1 wird auf k2 abgebildet */
3417   g[k2->ursprung] = k1->ursprung;
3418   g[k2->name]     = k1->name;           /* g: k2 wird auf k1 abgebildet */
3419   return(bilde_f_und_g_sp_rek(f,g,k1,k2));
3420 }
3421 
3422 /*********************bilde_f_und_g********TH***********************************/
3423 
3424 /* Die Funktion bilde_f_und_g  bildet die komplette Funktion f, die die Kante
3425    k1 in die Kante k2 ueberfuehrt, und simultan die Funktion g, die die Kante
3426    k2 in die Kante k1 ueberfuehrt. Beide Funktionen sind ordnungserhaltend.
3427    Die Funktion prueft, ob g die Umkehrfunktion von f ist. Ist sie es, so liefert
3428    bild_f_und_g den Wert 1, andernfalls den Wert 0.
3429    Weitere Anmerkungen siehe bilde_f_und_g_sp. */
3430 
3431 /* Die folgende Prozedur enthaelt den Rekursionsschritt */
3432 
bilde_f_und_g_rek(KNOTENTYP * f,KNOTENTYP * g,KANTE * k1,KANTE * k2)3433 BOOL bilde_f_und_g_rek(KNOTENTYP *f, KNOTENTYP *g, KANTE *k1, KANTE *k2) {
3434   KNOTENTYP u,v;
3435   k1 = k1->invers->prev;
3436   k2 = k2->invers->prev;   /* k1 und k2 im Gleichschritt nach rechts und links */
3437   u = k1->name;            /* von u wird der Funktionswert f[u] berechnet */
3438   v = k2->name;
3439   if (!(f[u])) {          /* Funktionswert noch nicht bekannt */
3440     f[u] = v;
3441     if (g[v]) {return(0);}    /* Widerspruch gefunden */
3442     g[v] = u;
3443     if (!bilde_f_und_g_rek(f,g,k1,k2))  {return(0);}  /* weitere Funktionswerte: Widerspruch? */
3444   }
3445   else {
3446     if (!(g[v])) {return(0);}     /* Widerspruch gefunden. Diese Abfrage koennte aber auch
3447                                       entfallen, denn wenn ein Wert von g noch nicht festgelegt
3448         ist, obwohl der zugehoerige Wert von f bereits feststeht, so wird an anderer Stelle ein
3449         Wert von g zuviel festgelegt sein, obwohl der zugehoerige Wert von f noch nicht feststeht */
3450   }
3451   k1 = k1->prev;           /* k1 und k2 spiegelverkehrt nach links und rechts */
3452   k2 = k2->prev;           /* denn: (k->invers->prev)->prev = k->invers->next */
3453   u = k1->name;
3454   v = k2->name;
3455   if (!(f[u])) {
3456     f[u] = v;
3457     if (g[v]) {return(0);}
3458     g[v] = u;
3459     if (!bilde_f_und_g_rek(f,g,k1,k2))  {return(0);}
3460   }
3461   else {
3462     if (!(g[v])) {return(0);}
3463   }
3464   return(1);       /* keinen Widerspruch festgestellt */
3465 }
3466 
3467 /* Die folgende Prozedur enthaelt den Rekursionsanfang */
3468 
bilde_f_und_g(KNOTENTYP * f,KNOTENTYP * g,KANTE * k1,KANTE * k2,KNOTENTYP anz)3469 BOOL bilde_f_und_g(KNOTENTYP *f, KNOTENTYP *g, KANTE *k1, KANTE *k2, KNOTENTYP anz) {
3470   KNOTENTYP i;
3471   for (i=1; i<=anz; i++) {f[i]=0; g[i]=0;}   /* Funktionstabellen loeschen */
3472   f[k1->ursprung] = k2->ursprung;
3473   f[k1->name]     = k2->name;           /* f: k1 wird auf k2 abgebildet */
3474   g[k2->ursprung] = k1->ursprung;
3475   g[k2->name]     = k1->name;           /* g: k2 wird auf k1 abgebildet */
3476   return(bilde_f_und_g_rek(f,g,k1,k2));
3477 }
3478 
3479 
3480 /************************MINITEST***********TH***************************/
3481 
minitest(PLANMAP map,KNOTENTYP * code)3482 int minitest(PLANMAP map, KNOTENTYP *code)
3483 
3484 /* WICHTIG: Bei der bauchbinde muss auch ueberprueft werden, ob sie wirklich
3485    minimal gebaut ist. Moeglich: Verdrehen und hinterher ist das Spiegelbild
3486    mit der gleichen Binde kleiner verklebt. (Beispiele schon mit 32 Knoten)
3487 
3488    Hier werden nur Pfade betrachtet, an denen mindestens ein 5-Eck liegt.
3489 
3490    Zu einer 5-Eck-Kante gehoert der Pfad, der entsteht, wenn man zur vorigen
3491    Kante (prev) geht und dann wechselnd weiter, bis es nicht mehr geht (d.h. man
3492    muesste eine bereits benutzte Kante nochmal benutzen). (Eigentlich gehoert er zu
3493    dem Winkel aud dieser und der vorigen Kante des 5-Ecks.) Dann geht man in die andere
3494    Richtung weiter, bis es nicht mehr geht. Aber auch in der anderen Reihenfolge
3495    muss der Pfad konstruiert werden, da die Orientierung schon durch andere
3496    Festlegungen bestimmt wurde.
3497 
3498    Akzeptiert werden nur Graphen, bei denen der Weg zu einem 5-Eck korrespondiert,
3499    d.h. aus einer 5-Eck-Kante konstruiert werden kann (im normal ODER im
3500    Spiegel-modus). Jeder Graph hat so einen Weg. Fuer die Minimalitaet werden
3501    auch nur solche Pfade betrachtet. Das ist etwas anderes, als dass nur ein 5-Eck
3502    am Weg liegt. (BSP: Sandwich mit 5-Eck am Stueck l2.)
3503 
3504 
3505    Obwohl viele Pfade sowohl in normalem, als auch im Mirror-Modus konstruiert
3506    werden koennen, gibt es auch Pfade, die nur in einem Modus konstruiert
3507    werden koennen.
3508 
3509 
3510               /<
3511         Kante/  \
3512             /    \
3513            <      --------------> dazugehoerige erste Richtung
3514 
3515 
3516     Anmerkung: Wenn eine 5-Eck-Kante zu einem Endpunkt des Pfades fuehrt, so hat dasselbe
3517     Fuenfeck auch einen Winkel mit dem Pfad gemeinsam (sonst haette man eine Bauchbinde).
3518 
3519 */
3520 
3521 
3522 {
3523 int i, j, ii, m_laenge, ms_laenge, knoten_auf_pfad;
3524 int l1, l2, l3, ll1, ll2, ll3, edgemark, middle, lower_border;
3525 KANTE *miniliste[120], *mini_spiegel[120];
3526 KANTE  *run, *start, *merke_1, *merke_2;
3527 long mark[N+1];
3528 int zaehler, stelle_1, stelle_2, pfadlaenge;
3529 KNOTENTYP cpcode[20];
3530 int test, runzaehler;
3531 BOOL rekonstruiert;
3532 int minierg[120];          /* fuer Bauchbinden */
3533 
3534 rekonstruiert=0;
3535 if (code[1]==1) knoten_auf_pfad=code[0]; else knoten_auf_pfad=code[0]-1;
3536 /* die knoten auf dem Pfad sind immer mit 1..k_a_p nummeriert */
3537 
3538 
3539 test=1;
3540 m_laenge=ms_laenge=0;
3541 
3542 for (i=1; i<=map[0][0].name; i++) { mark[i]=0;
3543 				    for(j=0;j<3;j++)
3544 				      { run=map[i]+j;
3545 					run->dummy=run->mininame=0;
3546 				      }
3547 				  }
3548 
3549 
3550 l1=code[2];
3551     if (code[1]==2) { l3=code[3]; l2=code[0]-l1-l3; }
3552     else { l2=code[3]; l3=code[0]-l1-l2; }
3553 
3554 if (code[1]==1) { rekonstruiert=1; /* Bei bauchbinden ist das immer der Fall */
3555 		  for (i=0; (i<60); i++)
3556                          { run=F_eck_kanten[i];
3557 			   run->nostart=run->mirror_nostart=0; }
3558 		}
3559 else if (code[1]==2) /* muss irgendwo am Pfad liegen */
3560   { for (i=0; (i<60) && !rekonstruiert; i++)
3561                          { run=F_eck_kanten[i];
3562 			   if (run->ursprung <= knoten_auf_pfad) rekonstruiert=1;
3563 			   run->nostart=run->mirror_nostart=0; }
3564     for (; i<60 ; i++)   { run=F_eck_kanten[i];
3565 			   run->nostart=run->mirror_nostart=0; }
3566   }
3567 else /* d.h. code[1]==3 -- also sandwich */
3568   { for (i=0; (i<60) && !rekonstruiert; i++)
3569                          { run=F_eck_kanten[i];
3570 			   if (run->ursprung <= knoten_auf_pfad)
3571 			     {
3572 			       if (run->prev->name==run->ursprung-1)
3573 				 {
3574 				  if ((run->ursprung <=l1) || (run->ursprung >= l1+l2)) rekonstruiert=1;
3575 			          else { if (run->prev->name==l1)
3576 					   { if ((l2+l3) % 2) rekonstruiert=1; }
3577 					 else
3578 					   if (run->name==l1+l2)
3579 					     { if ((l1+l2) % 2) rekonstruiert=1; }
3580 				       }
3581 				 } /* ende "die beiden kanten liegen in laufrichtung */
3582 			       else
3583 				 if (run->prev->name==run->ursprung+1) /* d.h. entgegen der Laufrichtung */
3584 				 { if ((run->ursprung <=l1) || (run->ursprung >= l1+l2)) rekonstruiert=1;
3585 			          else { if (run->prev->name==l1+l2)
3586 					   { if ((l1+l2) % 2) rekonstruiert=1; }
3587 					 else
3588 					   if (run->name==l1)
3589 					     { if ((l2+l3) % 2) rekonstruiert=1; }
3590 				       }
3591 				 } /* ende "die beiden kanten liegen entgegen der laufrichtung */
3592 			     } /* ende if auf pfad */
3593 			   run->nostart=run->mirror_nostart=0; } /* ende for */
3594     for (; i<60 ; i++)   { run=F_eck_kanten[i];
3595 			   run->nostart=run->mirror_nostart=0; }
3596   } /* ende sandwich */
3597 
3598 
3599 if (!rekonstruiert) { return(0); }
3600 
3601 
3602 /* Jetzt die Kanten markieren, bei denen man den Originalpfad rekonstruieren wuerde,
3603    dabei werden 6-Eck-Kanten einfach mitmarkiert */
3604 if (code[1]!=1)
3605   {
3606     /* Von stelle_1 bis ende kann in Richtung auf 1 rekonstruiert werden. Von 1 bis stelle_2 kann in Richtung
3607        aufs ende rekonstruiert werden. Die stellen geben die position des valenz 2 knotens in dem
3608        winkel an. Beachten: bei "invers" ist der valenz-2-knoten immer um eins groesser ? */
3609 
3610 
3611     if (code[1]==2) { if (l1%2) stelle_1=l1-1; else stelle_1=l1;
3612 		      if (l3%2) stelle_2=l1+l2+1; else stelle_2=l1+l2; }
3613     else /* d.h. sandwich */
3614                     { if ((l1+l2)%2) stelle_1=l1+l2-1; else stelle_1=l1+l2;
3615 		      if ((l2+l3)%2) stelle_2=l1+1; else stelle_2=l1; }
3616 
3617     map[1][0].nostart=1;
3618     for (run=map[1][2].invers->next, zaehler=2; zaehler < code[0]; zaehler+=2)
3619       { if (zaehler<=stelle_2) { run->mirror_nostart=1;
3620 				if (zaehler<stelle_2) run->invers->nostart=1; }
3621 	if (zaehler>=stelle_1-1)
3622 	                      { if (zaehler>=stelle_1) run->nostart=1;
3623 				if (zaehler<knoten_auf_pfad) run->invers->mirror_nostart=1; }
3624 	run=run->invers->prev->invers->next;
3625       }
3626 
3627     /* Da jetzt aber die letzte Kante nicht als Startkante markiert werden kann, da dieser Pfad ja nicht
3628        mehr konstruiert wird, muss das nachgeholt werden: */
3629     if (l1==l3)
3630       { if (knoten_auf_pfad % 2) { mini_spiegel[0]=map[knoten_auf_pfad][2].invers; ms_laenge=1; }
3631 	else { miniliste[0]=map[knoten_auf_pfad][1].invers; m_laenge=1; }
3632       }
3633   }
3634 
3635 
3636 /* Jetzt ans konstruieren: */
3637 
3638 edgemark=1;
3639 
3640 for (i=0; i<60; i++) /* for ueber alle kanten, von denen links ein 5-Eck ist */
3641   {
3642     start=F_eck_kanten[i];
3643 
3644     if (! start->nostart)
3645       {
3646 	middle= 2*N*edgemark;
3647 	lower_border=middle-N;
3648 
3649 	mark[start->ursprung]=middle;
3650 	runzaehler=middle-1;
3651 
3652 	start->dummy=start->invers->dummy=edgemark;
3653 	run=start->prev;
3654 	run->dummy=run->invers->dummy=edgemark;
3655 	run=run->invers->next;
3656 	pfadlaenge=2;
3657 
3658 	/* nach rechts laufen: */
3659 	while (run->dummy < edgemark) /* neue kante */
3660 	  { mark[run->ursprung]=runzaehler; runzaehler--;
3661 	    pfadlaenge++;
3662 	    run->dummy=run->invers->dummy=edgemark;
3663 	    merke_1=run; /* letzte neue kante */
3664 	    run=run->invers->prev;
3665 	    if (run->dummy < edgemark)
3666 	      { mark[run->ursprung]=runzaehler; runzaehler--;
3667 		pfadlaenge++;
3668 		run->dummy=run->invers->dummy=edgemark;
3669 		merke_1=run;
3670 		run=run->invers->next; }
3671 	  }
3672 
3673 	/* nach links laufen: */
3674 
3675 	run=start->invers->prev;
3676 	runzaehler=middle+1;
3677 	if (mark[run->ursprung]<lower_border) mark[run->ursprung]=runzaehler;
3678 	                                      /* kann (z.b. bei bauchbinde) vor der schleife noetig
3679 						 sein */
3680 	merke_2=start;
3681 	while (run->dummy < edgemark) /* neue kante */
3682 	  { mark[run->ursprung]=runzaehler; runzaehler++;
3683 	    pfadlaenge++;
3684 	    run->dummy=run->invers->dummy=edgemark;
3685 	    merke_2=run; /* letzte neue kante */
3686 	    run=run->invers->next;
3687 	    if (run->dummy < edgemark)
3688 	      { mark[run->ursprung]=runzaehler; runzaehler++;
3689 		pfadlaenge++;
3690 		run->dummy=run->invers->dummy=edgemark;
3691 		merke_2=run;
3692 		run=run->invers->prev; }
3693 	  }
3694 
3695          /* Jetzt auswerten, was fuer ein pfad gebaut wurde */
3696 
3697 	if (pfadlaenge<code[0]) return(0);
3698         cpcode[0]=pfadlaenge;
3699 	if (merke_1==merke_2->invers->prev->invers) cpcode[1]=1;
3700 	else if (mark[merke_1->name]<mark[merke_2->name]) cpcode[1]=2;
3701 	else cpcode[1]=3;
3702 
3703 
3704 	/* zuerst zum markieren der in zukunft nicht mehr zu testenden Kanten (Winkel): */
3705 	switch(cpcode[1])
3706 	  {
3707 	  case 1: {
3708 	            for (j=0, run=start; j<pfadlaenge; j+=2)
3709 		      { run->nostart=run->mirror_nostart=1;
3710 			run=run->invers;
3711 			run->nostart=run->mirror_nostart=1;
3712 			run=run->prev->invers->next; }
3713 		    break;
3714 		  }
3715 	  case 2: { ll1=mark[merke_1->name]-mark[merke_1->ursprung]+1;
3716 		    ll3=mark[merke_2->ursprung]-mark[merke_2->name]+1;
3717 		    if (ll1 >= ll3) { cpcode[2]=ll1; cpcode[3]=ll3; }
3718 		      else { cpcode[2]=ll3; cpcode[3]=ll1; }
3719 		    if (ll1%2) stelle_1=mark[merke_1->name]-1; else stelle_1=mark[merke_1->name];
3720 		    if (ll3%2) stelle_2=mark[merke_2->name]+1; else stelle_2=mark[merke_2->name];
3721 		    break; }
3722 	  case 3: { ll1=mark[merke_2->name]-mark[merke_1->ursprung]+1;
3723 		    ll3=mark[merke_2->ursprung]-mark[merke_1->name]+1;
3724 		    ll2=pfadlaenge-ll1-ll3;
3725 		    if (ll1>=ll3) { cpcode[2]=ll1; cpcode[3]=ll2; }
3726 		       else { cpcode[2]=ll3; cpcode[3]=ll2; }
3727                     if ((ll1+ll2)%2) stelle_1=mark[merke_1->name]-1; else stelle_1=mark[merke_1->name];
3728 		    if ((ll2+ll3)%2) stelle_2=mark[merke_2->name]+1; else stelle_2=mark[merke_2->name];
3729 		    break; }
3730 	  default: { fprintf(stderr,"Dangerous error in switch (minitest) !\n"); exit(34); }
3731 	  } /* ende switch */
3732 
3733 
3734 if (cpcode[1]==1) { if ((test=codecmp_kn(code,cpcode,2))>0) return(0); }
3735       else { if ((test=codecmp_kn(code,cpcode,4))>0) return(0); }
3736 
3737 
3738 if (code[1]!=1) /* fuer bauchbinden wurde in switch schon markiert */
3739   {
3740     /* Von stelle_1 bis ende kann in Richtung auf den Anfang rekonstruiert werden. Von 1 bis stelle_2 kann
3741        in Richtung aufs ende rekonstruiert werden */
3742 
3743     if (mark[merke_1->ursprung]%2)
3744       { merke_1->nostart=1;
3745 	for (run=merke_1->prev->invers->next, zaehler=mark[merke_1->ursprung]+1;
3746 	                              zaehler <= mark[merke_2->ursprung]; zaehler+=2)
3747 	  { if (zaehler<=stelle_2) { run->mirror_nostart=1;
3748 				    if (zaehler<stelle_2) run->invers->nostart=1; }
3749 	    if (zaehler>=stelle_1-1) { if (zaehler>=stelle_1) run->nostart=1;
3750 				      if (zaehler<mark[merke_2->ursprung]) run->invers->mirror_nostart=1; }
3751 	    run=run->invers->prev->invers->next;
3752 	  }
3753       }
3754     else /* d.h. mark[merke_1->ursprung] gerade */
3755       {
3756 	for (run=merke_1->next, zaehler=mark[merke_1->ursprung];
3757 	                              zaehler <= mark[merke_2->ursprung]; zaehler+=2)
3758 	  { if (zaehler<=stelle_2) { run->mirror_nostart=1;
3759 				    if (zaehler<stelle_2) run->invers->nostart=1; }
3760 	    if (zaehler>=stelle_1-1) { if (zaehler>=stelle_1) run->nostart=1;
3761 				      if (zaehler<mark[merke_2->ursprung]) run->invers->mirror_nostart=1; }
3762 	    run=run->invers->prev->invers->next;
3763 	  }
3764       }
3765   } /* ende code[1] != 1 und damit ende des markierens */
3766 
3767 	/* jetzt eventuell neue Kanten in die Listen: */
3768 	if (test==0)
3769           {
3770 	  if (code[1]==1) { miniliste[m_laenge]=start; m_laenge++; }
3771 	     else { if (ll1>=ll3)
3772 		      { if (mark[merke_1->ursprung]%2)
3773 			  { miniliste[m_laenge]=merke_1->invers; m_laenge++; }
3774 		      else
3775 			{ mini_spiegel[ms_laenge]=merke_1->invers; ms_laenge++; }
3776 		      }
3777 		    if (ll3>=ll1)
3778 		      { if (mark[merke_2->ursprung]%2)
3779 			  { mini_spiegel[ms_laenge]=merke_2->invers; ms_laenge++; }
3780 		      else
3781 			{ miniliste[m_laenge]=merke_2->invers; m_laenge++; }
3782 		      }
3783 		  } /* ende else */
3784 	  }
3785         edgemark++;
3786       } /* ende if (!start->nostart) */
3787 
3788 
3789 
3790 /* nun in die andere Richtung zuerst */
3791 
3792 
3793     if (! start->mirror_nostart)
3794       {
3795 
3796 	middle= 2*N*edgemark;
3797 	lower_border=middle-N;
3798 
3799 	mark[start->ursprung]=middle;
3800 	runzaehler=middle-1;
3801 
3802 	start->dummy=start->invers->dummy=edgemark;
3803 	run=start->prev;
3804 	run->dummy=run->invers->dummy=edgemark;
3805 	pfadlaenge=2;
3806 
3807 	/* nach links laufen: */
3808 	run=start->invers->prev;
3809 	while (run->dummy < edgemark) /* neue kante */
3810 	  { mark[run->ursprung]=runzaehler; runzaehler--;
3811 	    pfadlaenge++;
3812 	    run->dummy=run->invers->dummy=edgemark;
3813 	    merke_1=run; /* letzte neue kante */
3814 	    run=run->invers->next;
3815 	    if (run->dummy < edgemark)
3816 	      { mark[run->ursprung]=runzaehler; runzaehler--;
3817 		pfadlaenge++;
3818 		run->dummy=run->invers->dummy=edgemark;
3819 		merke_1=run;
3820 		run=run->invers->prev; }
3821 	  }
3822 
3823 	/* nach rechts laufen: */
3824 
3825 	run=start->prev->invers->next;
3826 	runzaehler=middle+1;
3827 	if (mark[run->ursprung]<lower_border) mark[run->ursprung]=runzaehler;
3828 	                                      /* kann (z.b. bei bauchbinde) vor der schleife noetig
3829 						 sein */
3830 	merke_2=start->prev;
3831 	while (run->dummy < edgemark) /* neue kante */
3832 	  { mark[run->ursprung]=runzaehler; runzaehler++;
3833 	    pfadlaenge++;
3834 	    run->dummy=run->invers->dummy=edgemark;
3835 	    merke_2=run; /* letzte neue kante */
3836 	    run=run->invers->prev;
3837 	    if (run->dummy < edgemark)
3838 	      { mark[run->ursprung]=runzaehler; runzaehler++;
3839 		pfadlaenge++;
3840 		run->dummy=run->invers->dummy=edgemark;
3841 		merke_2=run;
3842 		run=run->invers->next; }
3843 	  }
3844 
3845          /* Jetzt auswerten, was fuer ein pfad gebaut wurde */
3846 
3847 	if (pfadlaenge<code[0]) return(0);
3848         cpcode[0]=pfadlaenge;
3849 	if (merke_1==merke_2->invers->next->invers) cpcode[1]=1;
3850 	else if (mark[merke_1->name]<mark[merke_2->name]) cpcode[1]=2;
3851 	else cpcode[1]=3;
3852 
3853 	/* zuerst zum markieren der in zukunft nicht mehr zu testenden Kanten (Winkel): */
3854 	switch(cpcode[1])
3855 	  {
3856 	  case 1: { fprintf(stderr,"ERROR: BAUCHBINDEN should not be possible in mirror modus \n");
3857 		    exit(35);
3858 		    break;
3859 		  }
3860 	  case 2: { ll1=mark[merke_1->name]-mark[merke_1->ursprung]+1;
3861 		    ll3=mark[merke_2->ursprung]-mark[merke_2->name]+1;
3862 		    if (ll1 >= ll3) { cpcode[2]=ll1; cpcode[3]=ll3; }
3863 		      else { cpcode[2]=ll3; cpcode[3]=ll1; }
3864 		    if (ll1%2) stelle_1=mark[merke_1->name]-1; else stelle_1=mark[merke_1->name];
3865 		    if (ll3%2) stelle_2=mark[merke_2->name]+1; else stelle_2=mark[merke_2->name];
3866 		    break; }
3867 	  case 3: { ll1=mark[merke_2->name]-mark[merke_1->ursprung]+1;
3868 		    ll3=mark[merke_2->ursprung]-mark[merke_1->name]+1;
3869 		    ll2=pfadlaenge-ll1-ll3;
3870 		    if (ll1>=ll3) { cpcode[2]=ll1; cpcode[3]=ll2; }
3871 		       else { cpcode[2]=ll3; cpcode[3]=ll2; }
3872                     if ((ll1+ll2)%2) stelle_1=mark[merke_1->name]-1; else stelle_1=mark[merke_1->name];
3873 		    if ((ll2+ll3)%2) stelle_2=mark[merke_2->name]+1; else stelle_2=mark[merke_2->name];
3874 		    break; }
3875 	  default: { fprintf(stderr,"Dangerous error in switch (minitest mirror) !\n"); exit(36); }
3876 	  } /* ende switch */
3877 
3878 	if ((test=codecmp_kn(code,cpcode,4))>0) return(0);
3879 
3880 
3881     /* Von stelle_1 bis ende kann in Richtung auf den Anfang rekonstruiert werden. Von 1 bis stelle_2 kann
3882        in Richtung aufs ende rekonstruiert werden */
3883 
3884     if ((mark[merke_1->ursprung]%2)==0) /* umgekehrter laufsinn als bei der anderen entwicklungsrichtung */
3885       { merke_1->nostart=1;
3886 	for (run=merke_1->prev->invers->next, zaehler=mark[merke_1->ursprung]+1;
3887 	                              zaehler <= mark[merke_2->ursprung]; zaehler+=2)
3888 	  { if (zaehler<=stelle_2) { run->mirror_nostart=1;
3889 				    if (zaehler<stelle_2) run->invers->nostart=1; }
3890 	    if (zaehler>=stelle_1-1) { if (zaehler>=stelle_1) run->nostart=1;
3891 				      if (zaehler<mark[merke_2->ursprung]) run->invers->mirror_nostart=1; }
3892 	    run=run->invers->prev->invers->next;
3893 	  }
3894       }
3895     else /* d.h. mark[merke_1->ursprung] ungerade */
3896       {
3897 	for (run=merke_1->next, zaehler=mark[merke_1->ursprung];
3898 	                              zaehler <= mark[merke_2->ursprung]; zaehler+=2)
3899 	  { if (zaehler<=stelle_2) { run->mirror_nostart=1;
3900 				    if (zaehler<stelle_2) run->invers->nostart=1; }
3901 	    if (zaehler>=stelle_1-1) { if (zaehler>=stelle_1) run->nostart=1;
3902 				      if (zaehler<mark[merke_2->ursprung]) run->invers->mirror_nostart=1; }
3903 	    run=run->invers->prev->invers->next;
3904 	  }
3905       }
3906    /* ende des markierens */
3907 
3908 	/* jetzt eventuell neue Kanten in die Listen: */
3909 	if (test==0)
3910 	  { if (ll1>=ll3) /* jeweils vertauscht zum nicht-mirror-fall */
3911 		      { if (mark[merke_1->ursprung]%2)
3912 			  { mini_spiegel[ms_laenge]=merke_1->invers; ms_laenge++; }
3913 		      else
3914 			  { miniliste[m_laenge]=merke_1->invers; m_laenge++; }
3915 		      }
3916 		    if (ll3>=ll1)
3917 		      { if (mark[merke_2->ursprung]%2)
3918 			{ miniliste[m_laenge]=merke_2->invers; m_laenge++; }
3919 		      else
3920 			{ mini_spiegel[ms_laenge]=merke_2->invers; ms_laenge++; }
3921 		      }
3922 	    } /* ende test==0 */
3923         edgemark++;
3924       } /* ende if (!start->mirror_nostart) */
3925 
3926   } /* ende for ueber alle 5-Eck-Kanten */
3927 
3928 
3929 
3930 /* TH:  ab hier ist alles massiv veraendert */
3931 /* Nun wird geprueft, ob der uebergebene Code der kleinstmoegliche ist. */
3932 
3933 if (code[1]==1) /* Bauchbinde */
3934   { i=0;
3935     while (i<m_laenge)
3936       { if ((test = bauchbinde_reko(map,code,miniliste[i]))==0) return(0);
3937         if (test==1) {miniliste[i] = miniliste[m_laenge-1];  m_laenge--;}
3938         else         {minierg[i] = test;  i++;}
3939       }
3940     i=0;
3941     while (i<m_laenge && minierg[i]==4) {i++;}
3942     if (i==m_laenge) {fprintf(stderr,"Es fehlt Originalbauchbinde!\n"); exit(37);}
3943     test = minierg[0];    minierg[0] = minierg[i];      minierg[i] = test;
3944     run  = miniliste[0];  miniliste[0] = miniliste[i];  miniliste[i] = run;
3945     /* Nun befindet sich im ersten Listeneintrag ein Pfad, der durch Drehung des
3946        Originals zustande kommt oder selbst das Original ist. Es gilt dann fuer den
3947        Wert von minierg[i]:
3948        2 = es gibt eine Drehung zwischen Bauchbinde 0 (erster Listeneintrag) und Bauchbinde i
3949        4 = es gibt eine Spiegelung/Drehspiegelung zwischen Bauchbinde 0 und Bcc Thauchbinde i
3950        6 = es gibt eine Drehung und eine Spiegelung zwischen Bauchbinde 0 und Bauchbinde i */
3951   }
3952 else {
3953 
3954   /* Es koennen doppelte Eintraege in der miniliste vorkommen. Diese werden geloescht. */
3955   for (i=0; i<m_laenge-1; i++) {
3956     ii=i+1;
3957     while (ii<m_laenge) {
3958       if (miniliste[i]==miniliste[ii]) {miniliste[ii] = miniliste[m_laenge-1];  m_laenge--;}
3959       else {ii++;}
3960     }
3961   }
3962   for (i=0; i<ms_laenge-1; i++) {
3963     ii=i+1;
3964     while (ii<ms_laenge) {
3965       if (mini_spiegel[i]==mini_spiegel[ii]) {mini_spiegel[ii] = mini_spiegel[ms_laenge-1];  ms_laenge--;}
3966       else {ii++;}
3967     }
3968   }
3969 
3970   if (code[1]==2) /* Brille */
3971      { i=0;
3972        while (i<m_laenge) {
3973 	 if ((test = brille_reko(map,code,miniliste[i]))==0) return(0);
3974          if (test==1) {miniliste[i]=miniliste[m_laenge-1];  m_laenge--;}
3975          else         {i++;}
3976        }
3977        i=0;
3978        while (i<ms_laenge) {
3979 	 if ((test = brille_sp_reko(map,code,mini_spiegel[i]))==0) return(0);
3980          if (test==1) {mini_spiegel[i]=mini_spiegel[ms_laenge-1];  ms_laenge--;}
3981          else         {i++;}
3982        }
3983      }   /* if */
3984   else /* d.h. (code[1]==3) d.h. Sandwich */
3985      { i=0;
3986        while (i<m_laenge) {
3987          if ((test = sandwich_reko(map,code,miniliste[i]))==0) return(0);
3988          if (test==1) {miniliste[i]=miniliste[m_laenge-1];  m_laenge--;}
3989          else         {i++;}
3990        }
3991        i=0;
3992        while (i<ms_laenge) {
3993          if ((test = sandwich_reko_sp(map,code,mini_spiegel[i]))==0) return(0);
3994          if (test==1) {mini_spiegel[i]=mini_spiegel[ms_laenge-1];  ms_laenge--;}
3995          else         {i++;}
3996        }
3997      }  /* else */
3998 }       /* else */
3999 
4000 
4001 if (!symstat) return(1);     /* 1 ist hier ein beliebiger Rueckgabewert ungleich 0 */
4002 
4003 
4004 /* Nun wird versucht, die Symmetriegruppe des erzeugten Fullerens herauszufinden */
4005 
4006 {      /* Klammer zur Abgrenzung der neuen Variablen */
4007 KNOTENTYP f[N+1];                    /* f[x] enthaelt den Bildknoten von Knoten x */
4008 KNOTENTYP e1,e2,e3;
4009 char ordnung[32];                    /* Ordnung einer Drehung */
4010      /* Es treten maximal 31 Drehungen auf (bei Ih__ und I__). Zwar werden bei Bauchbinden
4011         zwischenzeitlich einige Drehungen mehrfach gespeichert, jedoch nicht bei I__ und Ih__,
4012 	da diese Abbildungen keine Sechserdrehungen enthalten. 32 reicht also als Obergrenze. */
4013 BOOL dreh;
4014 KANTE *k1, *k2;
4015 int jj,ord,n,n2;
4016 BOOL geloescht, gefunden, alt;
4017 char symm_ord;                     /* Gesamtordnung der Symmetriegruppe */
4018 
4019 /* zunaechst bei Brillen und Sandwiches */
4020 
4021 if (code[1]!=1) {      /* keine Bauchbinde */
4022   KNOTENTYP f1[24][12],f2[24][12];      /* speichert Abbildung der ersten beiden Ecken eines Pfades */
4023 
4024   symm_ord = m_laenge + ms_laenge + 1;    /* Ordnung der Symmetriegruppe */
4025   switch (symm_ord) {                     /* eindeutige Symmetriegruppe ? */
4026     case 1:   return(C1__);
4027     case 3:   return(C3__);
4028     case 10:  return(D5__);
4029     case 60:  return(I__);
4030     case 120: return(Ih__);
4031   }
4032 
4033   /* Teil 1:  Nun werden alle Drehungen untersucht und die Zahl und die Art der
4034               Drehungen ermittelt */
4035 
4036   n = 0;                  /* n: laufende Nummer des aktuellen Automorphismus */
4037   while (m_laenge>0) {    /* Liste mit Drehungen durchforsten und dabei aufloesen */
4038     k1 = map[1][0].invers;
4039     k2 = miniliste[0];    /* es wird immer der erste Pfad in der Liste betrachtet */
4040     bilde_f(&f[0],k1,k2,map[0][0].name);
4041       /* Automorphismus, bei dem k1 auf k2 abgebildet wird, wird gebildet */
4042 
4043     /* Nun wird betrachtet:  Wie werden die Ecken e1 und e2 abgebildet und nach
4044        wie vielen Schritten werden wieder e1 und e2 erreicht (Ordnung des
4045        Automorphismus)? Dabei werden die zwischenzeitlich erreichten Ecken
4046        in den Arrays f1[n][...] und f2[n][...] zwischengespeichert. Also:
4047        f1[n][0] = f[e1],  f1[n][1] = f[f[e1]],  f1[n][2] = f[f[f[e1]]], ... ,
4048        f1[n][x] = f[...[f[e1]]...] = e1  (mit x = Ordnung des Automorphismus = Endwert von ord) */
4049     ord = 0;                  /* Ordnung des Automorphismus */
4050     e1 = k1->ursprung;
4051     e2 = k1->name;
4052     do {
4053       f1[n][ord] = e1 = f[e1];
4054       f2[n][ord] = e2 = f[e2];
4055       ord++;
4056       if (ord>12) {fprintf(stderr,"Ordnung eines Automorphismus groesser als 12!\n"); exit(38);}
4057     } while ((e1!=k1->ursprung) || (e2!=k1->name));   /* bis Identitaet erreicht */
4058     ordnung[n] = ord;
4059 
4060     /* Nun ist die Ordnung des Automorphismus bekannt (=ordnung[n]) und es muessen noch
4061        die zugehoerigen Pfade in der miniliste gefunden und geloescht werden */
4062     miniliste[0] = miniliste[m_laenge-1];   m_laenge--;    /* erster Pfad wird geloescht */
4063     i = 1;    /* Anzahl der geloeschten Pfade */
4064     j = 0;    /* laufende Nummer des Pfades, ueber den entschieden wird, ob er geloescht wird */
4065     while (j<m_laenge) {
4066       ii=0;   geloescht=0;
4067       while (ii<ord-1 && !geloescht) {
4068         if (miniliste[j]->ursprung==f1[n][ii] && miniliste[j]->name==f2[n][ii])
4069           {miniliste[j]=miniliste[m_laenge-1];  m_laenge--;  geloescht=1;  i++;}
4070           /* Der Pfad wird geloescht, weil sein Anfang durch den aktuellen Automorphismus erreicht wird */
4071         ii++;
4072       }
4073       if (!geloescht) {j++;}  /*falls geloescht, so ist in Position j neuer Pfad => nicht ueberspringen*/
4074     }   /* while */
4075 
4076     if (i+1>ord) {fprintf(stderr,"Zu viele Pfade geloescht!\n");  exit(39);}
4077 
4078     /* Nun wird folgender Fall behandelt:
4079        Bei einem Automorphismus der Ordnung ord muessen ord-1 Pfade geloescht
4080        werden (alle bis auf den Originalpfad, der nicht in der Liste enthalten
4081        ist). Wenn weniger Pfade geloescht wurden, so sind zuvor schon einige
4082        Pfade des Automorphismus geloescht worden. Es gibt folgende Moeglichkeiten:
4083        - es wurde schon frueher eine Zweierdrehung entdeckt, die Bestandteil einer Sechserdrehung ist
4084        - es wurde schon frueher eine Dreierdrehung entdeckt, die Bestandteil einer Sechserdrehung ist
4085        - es wurden schon frueher eine Zweier- und eine Dreierdrehung entdeckt, die beide Bestandteil
4086          einer Sechserdrehung sind.
4087        In diesen Faellen muessen die zuerst gefundenen Zweier- bzw. Dreierdrehungen geloescht werden
4088        und in Sechserdrehungen umgewandelt werden.
4089        Falls einer der drei Faelle vorliegt, so ist der erste Eintrag f1[j][0] und f2[j][0]
4090        des zuerst gefundenen Automorphismus j auch im zweiten Automorphismus n enthalten. Also:
4091        f1[j][0] = f1[n][ii]  und  f2[j][0] = f2[n][ii]   fuer ein ii                             */
4092 
4093     if (i+1<ord) {              /* zuwenig Pfade geloescht */
4094       j=0;                      /* laufende Nummer des Automorphismus, mit dem verglichen wird */
4095       while (j<n && i+1<ord) {  /* es sind noch Automorphismen zu untersuchen */
4096         ii=0;   geloescht=0;
4097         while (ii<ord-1 && !geloescht) {
4098           if (f1[j][0]==f1[n][ii] && f2[j][0]==f2[n][ii]) {
4099             i += ordnung[j]-1;     /* die Anzahl der zuvor geloeschten Pfade */
4100             /* nun wird der zuvor gefundene Automorphismus geloescht (ueberschrieben) */
4101             ordnung[j] = ordnung[n-1];
4102             for (jj=0; jj<ordnung[n-1]; jj++) {f1[j][jj]=f1[n-1][jj];  f2[j][jj]=f2[n-1][jj];}
4103             ordnung[n-1] = ordnung[n];
4104             for (jj=0; jj<ordnung[n]; jj++)   {f1[n-1][jj]=f1[n][jj];  f2[n-1][jj]=f2[n][jj];}
4105             n--;
4106             geloescht=1;
4107           }   /* if */
4108           ii++;
4109         }     /* while */
4110         if (!geloescht) {j++;}
4111       }       /* while */
4112       if (i+1!=ord) {fprintf(stderr,"Falsche Ordnung des Automorphismus.\n"); exit(40);}
4113     }         /* if i+1<ord */
4114 
4115     n++;      /* nun wird der naechste Automorphismus behandelt */
4116   }           /* while m_laenge>0 */
4117 
4118   /* Jetzt sind die Anzahl der Drehungen (n) und zu jeder Drehung j die Art der Drehung
4119      (ordnung[j]) bekannt.
4120 
4121      Es folgt dieselbe Vorgehensweise fuer Spiegelungen. Es wird die Liste minispiegel
4122      aufgeloest. Es werden n2 Spiegelungen festgestellt. Da die Ordnung einer Ebenen-
4123      spiegelung immer 2 betraegt, ist eine Speicherung der Automorphismen in Arrays
4124      wie f1, f2 und ordnung nicht notwendig.
4125      In der Liste minispiegel befinden sich auch Drehspiegelungen (und Punktspiegelungen,
4126      die nichts anderes sind als 2er-Drehspiegelungen). Diese verursachen
4127      Probleme. Deshalb werden Drehspiegelungen, die gefunden werden, vernachlaessigt.
4128      Das ist moeglich, denn sobald die Ordnung einer Symmetriegruppe hoeher als 6 ist, ist
4129      jede Drehspiegelung schon in Form einer Drehung und einer Ebenenspiegelung berueck-
4130      sichtigt (das Fulleren enthaelt auch die einzelnen Symmetrien der zusammengesetzten
4131      Drehspiegelung). Es faellt also nichts unter den Tisch.
4132      Falls die Symmetriegruppe des Fullerens die Ordnung 4 oder 6 besitzt,
4133      ist es moeglich, anhand der gespeicherten Zahlen n und n2 auf die Existenz einer
4134      Drehspiegelung zu schliessen (deren einzelne Bestandteile nicht als Symmetrien in dem
4135      Fulleren vorhanden sind).
4136      Eine Drehspiegelung erkennt man daran, dass der Automorphismus im Gegensatz zur
4137      Ebenenspiegelung keine Ecken auf sich selbst oder benachbarte Ecken abbildet (letzteres
4138      ist durch die Mindestgroesse eines Fullerens gewaehrleistet).
4139      Falls der Automorphismus eine Ordnung besitzt, die groesser als 2 ist, so erkennt
4140      man die Drehspiegelung unmittelbar, denn Ebenenspiegelungen haben immer die Ordnung 2.
4141 
4142      Ein Beispiel fuer ein Problem mit Drehspiegelungen:
4143      Die Symmetriegruppe C3h besteht aus einer Dreierdrehung und einer Ebenenspiegelung senk-
4144      recht zur Dreierdrehung. Das Programm koennte einen Automorphismus bilden, der einer
4145      6er-Drehspiegelung gleichkommt. Dabei wuerde dann sogar die Ebenenspiegelung uebersehen.  */
4146 
4147   /* Teil 2:  Nun werden alle Spiegelungen untersucht und die Zahl und die Art der
4148               Spiegelungen ermittelt */
4149 
4150   n2 = 0;                    /* n2: laufende Nummer des aktuellen Automorphismus */
4151   while (ms_laenge>0) {      /* Liste mit Spiegelungen durchforsten und dabei aufloesen */
4152     k1 = map[1][0].invers;
4153     k2 = mini_spiegel[ms_laenge-1];     /* es wird immer der letzte Pfad in der Liste betrachtet */
4154     bilde_f_sp(&f[0],k1,k2,map[0][0].name);
4155     // Fehler bei Detektierung von Cs mit Fixkanten -- Aenderung: GB 13.2.2016
4156     if (symm_ord==2) ord=2; // GB
4157     else// GB
4158       {//GB
4159 
4160 	/* Automorphismus, bei dem k1 auf k2 abgebildet wird, wird gebildet */
4161 	ord = 0;                  /* Ordnung des Automorphismus */
4162 	/* es reicht, den Funktionswert der Kante k1={e1,e2} zu verfolgen, da k1!=k2,
4163 	   also k1 keine Fixkante unter f, also f[e1]!=e1 oder f[e2]!=e2 */
4164 	e1 = k1->ursprung;
4165 	e2 = k1->name;
4166 	do {
4167 	  e1 = f[e1];
4168 	  e2 = f[e2];
4169 	  ord++;
4170 	  // commented out by GB: if (ord>12) {fprintf(stderr,"Ordnung eines Automorphismus groesser als 12!\n"); exit(41);}
4171 	} while (((e1!=k1->ursprung) || (e2!=k1->name)) && ord<=2);   /* bis Identitaet erreicht oder
4172 									 bis klar ist, dass es sich um Drehspiegelung handelt (wegen ord>2) */
4173 	/* Nun wird ueberprueft, ob es sich bei der Spiegelung um eine reine Ebenenspiegelung oder um eine
4174 	   Drehspiegelung handelt. Bei einer Spiegelung mit der Ordnung >2  handelt es sich eindeutig um
4175 	   eine Drehspiegelung. Bei einer Spiegelung mit der Ordnung 2 ist zu pruefen, ob der Automorphismus
4176 	   Punkte auf sich selbst oder auf benachbarte Punkte abbildet (dann reine Ebenenspiegelung).
4177 	   Der aktuelle Automorphismus ist noch im Array f vorhanden.     */
4178       } //GB
4179     if (ord==1) ord=2; /* GB: wenn eine gerichtete Kante fix ist unter einem orientierungsumkehrenden Automorphismus
4180 			               ist die Ordnung 2 */
4181     dreh = 1;                /* falls keine andere Entdeckung:  Drehspiegelung */
4182     if (ord==2) {            /* Ebenenspiegelung oder Punktspiegelung ? */
4183       i=1;
4184       while (dreh && i<=map[0][0].name) {
4185         if (f[i]==map[i][0].name || f[i]==map[i][1].name || f[i]==map[i][2].name || f[i]==i) {dreh=0;}
4186         i++;
4187       }
4188     }
4189     if (!dreh) {n2++;}
4190     ms_laenge--;                                           /* letzter Pfad wird geloescht */
4191   }               /* while ms_laenge>0 */
4192   /* Jetzt ist die Anzahl der Ebenenspiegelungen (n2) bekannt */
4193 
4194   /* Es folgt die Bestimmung der Symmetriegruppe. */
4195   switch(symm_ord) {
4196     case 1:  return(C1__);
4197     case 2:  if (n)  {return(C2__);}
4198              else {
4199                if (n2) {return(Cs__);}
4200                else    {return(Ci__);}
4201              }
4202     case 3:  return(C3__);
4203     case 4:  if (!n2) {
4204                if (n==3) {return(D2__);}
4205                else      {return(S4__);}
4206              }
4207              else {
4208                if (n2==2) {return(C2v__);}
4209                else       {return(C2h__);}
4210              }
4211     case 6:  if (!n2) {
4212                if (n==4) {return(D3__);}
4213                else      {return(S6__);}
4214              }
4215              else {
4216                if (n2==3) {return(C3v__);}
4217                else       {return(C3h__);}
4218              }
4219     case 8:  if (n2==3)  {return(D2h__);}
4220              else        {return(D2d__);}
4221     case 10: return(D5__);
4222     case 12: if (!n2) {
4223                BOOL d6=0;
4224                for (i=0; i<n; i++) {if (ordnung[i]==6) {d6=1;} }
4225                if (d6) {return(D6__);}
4226                else    {return(T__);}
4227              }
4228              else {
4229 	       if (n2==4) {return(D3h__);}
4230                else       {return(D3d__);}
4231              }
4232     case 20: if (n2==6) {return(D5h__);}
4233              else       {return(D5d__);}
4234     case 24: { if (n2==7) {return(D6h__);}
4235                if (n2==6) {
4236                  BOOL d6=0;
4237                  for (i=0; i<n; i++) {if (ordnung[i]==6) {d6=1;} }
4238                  if (d6)  {return(D6d__);}
4239                  else     {return(Td__);}
4240                }
4241                else {return(Th__);}
4242              }
4243     case 60: return(I__);
4244     case 120: return(Ih__);
4245     default:  {fprintf(stderr,"Unbekannte Ordnung %d! %d\n",symm_ord,code[1]);  exit(42);}
4246   }      /* switch symm_ord */
4247 
4248 }             /* if code[1]!=1 */
4249 
4250 
4251 /* Es folgt dasselbe fuer Bauchbinden */
4252 
4253 if (code[1]==1) {      /* Bauchbinde  (redundante if-Abfrage) */
4254   /* Bei der Bauchbinde befindet sich der Originalpfad in der miniliste. Also wird einfach
4255      der erste Pfad in der Liste als Originalpfad genommen. */
4256   /* Bei der Bauchbinde sind verschiedene Symmetrien zu untersuchen, bei denen die
4257      Bauchbinde auf sich selbst abgebildet wird (so dass diese Symmetrien nicht
4258      direkt aus der miniliste abzulesen sind). Dies sind Drehungen um die Achse
4259      senkrecht zur Bauchbinde und Spiegelungen an Ebenen senkrecht zur Bauchbinde.
4260      Falls die Bauchbinde das Fulleren in zwei gleiche Teile zerteilt (lowercode==uppercode),
4261      so kommen noch Drehspiegelungen um die Achse senkrecht zur Bauchbinde und
4262      Zweierdrehungen um die Achse, die durch die Mittelpunkte zweier gegenueberliegender Kanten der
4263      Bauchbinde verlaeuft, hinzu. Falls die Bauchbinde das Fulleren in zwei ungleiche Teile zerteilt,
4264      so werden diese Symmetrien in der miniliste festgehalten und muessen erst spaeter
4265      betrachtet werden. */
4266 
4267   KNOTENTYP f1[24][2];   /* speichert bei gefundenen SPIEGELEBENEN eine Beispielkante */
4268                          /* 15 als Maximalzahl wuerde ausreichen (bei Ih__) */
4269   KNOTENTYP f2[32][2];   /* speichert bei gefundenen DREHUNGEN eine Beispielkante */
4270                          /* 31 als Maximalzahl wuerde ausreichen (bei I__ und Ih__) */
4271   KNOTENTYP g[N+1];
4272   char ordnung2;        /* Ordnung bei Spiegelungen */
4273   char drehung;         /* Art der Drehung um Achse senkrecht zur Bauchbinde */
4274   char sp_ebene;        /* Spiegelebene(n) senkrecht zur Bauchbinde */
4275   char drehsp;          /* Drehspiegelung um Achse senkrecht zur Bauchbinde */
4276   char zdrehung;        /* Zweierdrehung(en) wie oben beschrieben. */
4277 
4278   n = 0;                          /* Anzahl der gefundenen Drehungen */
4279   i = (code[0]/2)/code[3];        /* Drehung im oberen Teil des Fullerens  */
4280   j = (code[0]/2)/code[11];       /* Drehung im unteren Teil des Fullerens */
4281   drehung = i<j ? i : j;          /* groesser auf keinen Fall */
4282   if (i%drehung || j%drehung) {drehung = 1;}  /* Drehung um die Achse senkrecht zur Bauchbinde */
4283   if (drehung>1) {                /* Drehung in die Liste eintragen */
4284     k2 = miniliste[0];
4285     for (j=1; j<=knoten_auf_pfad/drehung; j++) {
4286       if (j%2) {k2 = k2->invers->prev;}  else  {k2 = k2->invers->next;}
4287     }
4288     f2[n][0] = k2->ursprung;     /* Beispielkante */
4289     f2[n][1] = k2->name;
4290     ordnung[n] = drehung;
4291     n++;
4292   }
4293 
4294   /* Nun wird versucht, Spiegelebenen zu ermitteln, die senkrecht auf der Bauchbinde
4295      stehen. Wenn es eine solche Spiegelebene gibt, dann schneidet sie die Bauchbinde
4296      in zwei Ecken. Es ist nicht moeglich, dass die Spiegelebene die Bauchbinde in
4297      einer Ecke und einer Kante oder in zwei Kanten schneidet.
4298      Also werden im folgenden je zwei gegenueberliegende Ecken betrachtet. Ausgehend
4299      von den Winkeln, die diese Ecken einschliessen, wird eine nicht ordnungserhaltene
4300      Abbildung gebildet und es wird untersucht, ob es sich dabei um einen Automorphismus
4301      der Ordnung 2 handelt.
4302      Damit nicht jede Spiegelebene doppelt betrachtet wird, reicht es aus bzw. ist es
4303      sogar erforderlich, nur die Ecken auf einer Haelfte des Pfades zu betrachten.
4304      Die gegenueberliegenden Ecken tauchen im Programmcode nicht auf.
4305      Sobald eine Spiegelebene gefunden wurde, wird die Suche nach weiteren Spiegelebenen
4306      vereinfacht, denn die Anzahl der Spiegelebenen senkrecht zur Bauchbinde entspricht
4307      dem Wert von "drehung" und die Spiegelebenen treten in regelmaessigen Abstaenden auf.
4308      Es verdoppelt sich die Symmetrieordnung unabhaengig von der Anzahl der Spiegelebenen. */
4309 
4310   n2 = 0;            /* Anzahl der gefundenen Spiegelebenen */
4311   sp_ebene = 1;      /* noch keine gefundene Spiegelebene */
4312   k1 = miniliste[0];               /* erste Kante */
4313   k2 = k1;
4314   j=1; i=0;
4315   while (j<=knoten_auf_pfad/2) {     /* den halben Pfad entlanggehen */
4316     if (j%2) {k2 = k1->invers->prev;}  else  {k2 = k1->invers->next;}
4317     /* Nun ist k2 im Pfad der Nachfolger von k1 */
4318     /* Wenn durch den Knoten k1->name eine Spiegelebene verlaeuft, so wird k1 auf k2->invers
4319        abgebildet und umgekehrt. Man kann nun eine nicht ordnungserhaltene Funktion f bilden,
4320        die k1 auf k2->invers abbildet, und eine nicht ordnungserhaltene Funktion g, die k2->invers auf
4321        k1 abbildet. Wenn g die Umkehrfunktion zu f ist, so ist f ein nicht ordnungserhaltender
4322        Automorphismus mit ordnung 2, es liegt also eine Spiegelebene vor (denn k1->name = k2->invers->name,
4323        es exisitiert also ein Fixpunkt). */
4324     if (sp_ebene==1 || (sp_ebene==2 && i==knoten_auf_pfad/(2*drehung))) {      /* Suche lohnt sich */
4325       if (bilde_f_und_g_sp(&f[0],&g[0],k1,k2->invers,map[0][0].name)) {
4326         sp_ebene=2;    /* fuendig */
4327         f1[n2][0] = f[miniliste[0]->ursprung];    f1[n2][1] = f[miniliste[0]->name];
4328         n2++;
4329         i=0;           /* Zaehler fuer jetzt beginnende schnelle Suche */
4330       }
4331     }
4332     k1 = k2;       /* zur naechsten Kante des Pfades */
4333     j++;  i++;
4334   }                    /* while j */
4335 
4336   /* Nun werden die oben beschriebenen Zweierdrehungen und Drehspiegelungen betrachtet, und zwar
4337      die Zweierdrehungen nur dann, wenn lowercode==uppercode.
4338      Zunaechst zu den Zweierdrehungen. Sobald man eine Zweierdrehung gefunden hat, ergeben sich
4339      Anzahl und Lage von (eventuell) weiteren Zweierdrehungen aus dem Wert von "drehung".
4340      Zu der Ordnung der Symmetriegruppe tragen die weiteren Zweierdrehungen nichts bei.
4341      Wie bei den Spiegelebenen werden die Kanten der Bauchbinde betrachtet und es werden ordnungs-
4342      erhaltende Funktionen gebildet, bei denen eine Kante k1 auf k1->invers abgebildet wird und
4343      umgekehrt.
4344      Eine auf diese Weise ermittelte Zweierdrehung kann nicht Bestandteil einer Sechserdrehung sein,
4345      da um den Mittelpunkt einer Kante nur Zweierdrehungen moeglich sind.
4346      Theoretisch kann eine solche Zweierdrehung Bestandteil einer Viererdrehspiegelung sein. Dies
4347      wird in diesem Zusammenhang ebenfalls geprueft. Falls eine Viererdrehspiegelung vorliegt, so
4348      wird die Kante k1 auf die "gegenueberliegende" Kante (bezogen auf die Laenge der Bauchbinde)
4349      abgebildet. Eine Viererdrehspiegelung ist nur dann interessant, wenn es die einzige innerhalb
4350      des Fullerens ist. Insbesondere liegt dann auch nur EINE Zweierdrehung und KEINE Ebenenspiegelung
4351      vor. Es wird also nur bei der ersten gefundenen Zweierdrehung geprueft und auch nur dann, wenn
4352      drehung==1 (keine weitere Drehung) und m_laenge==1 und sp_ebene==1. */
4353 
4354   zdrehung = drehsp = 1;                    /* 1 = noch nichts gefunden, 2 = gefunden */
4355   if (codecmp_kn(code+2,code+10,8)==0) {               /* lowercode==uppercode */
4356     k1 = miniliste[0];               /* erste Kante */
4357     j=1;  i=0;
4358     while (j<=knoten_auf_pfad/2) {     /* den halben Pfad entlanggehen */
4359       if (zdrehung==1 || (zdrehung==2 && i==knoten_auf_pfad/(2*drehung))) {            /* Suche lohnt sich */
4360         if (bilde_f_und_g(&f[0],&g[0],k1,k1->invers,map[0][0].name)) {
4361           f2[n][0] = f[miniliste[0]->ursprung];    f2[n][1] = f[miniliste[0]->name];
4362           ordnung[n] = 2;
4363           n++;
4364           if (zdrehung==1 && m_laenge==1 && sp_ebene==1 && drehung==1) {   /* Drehspiegelung? */
4365             k2 = k1;
4366             for (ii=0; ii<knoten_auf_pfad/2; ii++) {
4367               if ((j+ii)%2) {k2 = k2->invers->prev;} else {k2 = k2->invers->next;}  /* halber Pfad */
4368             }
4369             if (bilde_f_und_g_sp(&f[0],&g[0],k1,k2,map[0][0].name)) {
4370                 fprintf(stderr,"Z-Viererdrehspiegelung\n");  /* sollte eine derartige Drehspiegelung
4371                                                     tatsaechlich auftreten, so ist sie eine Zeile wert */
4372                 drehsp=4;
4373             }
4374             /* Drehspiegel-Abbildung von k1 nach k2->invers braucht nicht betrachtet zu werden:
4375                dasselbe Ergebnis wegen zdrehung=2 */
4376           }
4377           i=0;            /* Zaehler fuer jetzt beginnende schnelle Suche */
4378           zdrehung=2;     /* fuendig */
4379         }
4380       }
4381       if (j%2) {k1 = k1->invers->prev;}  else  {k1 = k1->invers->next;}  /* zur naechsten Kante des Pfades */
4382       j++;   i++;
4383     }                /*while */
4384   }                  /* if */
4385 
4386   /* Nun ist noch zu pruefen, ob eine Drehspiegelung mit einer Drehung um die Bauchbinde vorliegt.
4387      Die einzigen interessanten Faelle sind
4388      Ci, S4 und S6. Liegt einer dieser Faelle vor, so gibt es keine Spiegelebene (also sp_ebene==1 als
4389      Voraussetzung) und nur einen Listeneintrag (also m_laenge==1) und keine weitere Drehung (zdrehung==1).
4390      drehung==1:        moeglicherweise Punktspiegelung
4391      drehung==2:        moeglicherweise Viererdrehspiegelung
4392      drehung==3:        moeglicherweise Sechserdrehspiegelung
4393      =>  drehung==n/2:  moeglicherweise n-Drehspiegelung
4394      Fuer eine n-Drehspiegelung muss die Laenge des Pfades durch n teilbar sein (damit zugehoerige
4395      n/2-Drehung moeglich ist), darf aber nicht durch 2n teilbar sein. */
4396   if (m_laenge==1 && sp_ebene==1 && drehung<=3 && zdrehung==1 && knoten_auf_pfad%(2*drehung)==0 &&
4397       knoten_auf_pfad%(4*drehung)!=0)  {
4398     k1 = miniliste[0];            /* erste Kante */
4399     k2 = k1;
4400     for (j=1; j<=knoten_auf_pfad/(2*drehung); j++) {   /* einen Teil des Pfades entlanggehen */
4401       if (j%2) {k2 = k2->invers->prev;}  else  {k2=k2->invers->next;}
4402     }
4403     /* Wenn eine Drehspiegelung der Ordnung 2*drehung vorliegt, so wird durch sie k1 auf k2 abgebildet
4404        und umgekehrt. */
4405     if (bilde_f_und_g_sp(&f[0],&g[0],k1,k2,map[0][0].name)) {drehsp=2*drehung;}    /* fuendig */
4406   }    /* if */
4407 
4408   symm_ord = m_laenge * drehung * sp_ebene * zdrehung;   /* Mindestordnung der Symmetriegruppe */
4409   /* Fast immer ist dies auch die tatsaechliche Ordnung der Symmetriegruppe. Falls m_laenge>1,
4410      so kann es jedoch sein, dass zwei Pfade sowohl durch eine Drehung als auch durch eine Spiegelung
4411      aufeinander abgebildet werden (minierg==6). Falls diese Drehungen oder Spiegelungen nicht auch
4412      auf eine andere Weise entdeckt werden koennen, so ist die tatsaechliche Ordnung der Symmetriegruppe
4413      hoeher als symm_ord. Folgende Beobachtung wurde gemacht:  Wenn zwischen zwei Bauchbinden eines
4414      Fullerens die Relation minierg==6 auftritt, dann auch zwischen allen anderen Bauchbinden des
4415      Fullerens. */
4416 
4417   if (m_laenge==1) {       /* schnelle Entscheidung anhand der symm_ord moeglich */
4418     switch (symm_ord) {
4419       case 1:   if (drehsp==2) {return(Ci__);} else {return(C1__);}
4420       case 2:{  if (drehsp==4) {return(S4__);}
4421                 if (drehung==2 || zdrehung==2 || (m_laenge==2 && minierg[1]==2)) {return(C2__);}
4422                 if (sp_ebene==2) {return(Cs__);}
4423                 break;}
4424       case 3:   if (drehsp==6) {return(S6__);} else {return(C3__);}
4425       case 10:  return(D5__);
4426     }    /* switch */
4427   }      /* if */
4428 
4429   /*  Nun werden alle Eintraege in der miniliste untersucht.   */
4430 
4431   /* Es treten folgende Probleme im Vergleich zu Sandwiches und Brillen auf:
4432      1.  Ein Eintrag in der miniliste muss nicht aus einer Drehung resultieren, sondern
4433          kann auch von einer Ebenenspiegelung stammen. Deshalb muss zu jedem Eintrag
4434          eine ordnungserhaltende und eine nicht ordnungserhaltende Funktion gebildet
4435          werden.  Allerdings kann man sich die Liste minierg[] zunutze machen, die
4436          Auskunft darueber gibt, welche Funktion Aussicht auf Erfolg verspricht.
4437      2.  Es steht nicht fest, wohin der Anfang des Originalpfades abgebildet wird, da die
4438          Bauchbinde keinen fest definierten Anfang besitzt. Deshalb muss der "Anfang" der
4439          Originalbauchbinde (mit "Original" ist miniliste[0] gemeint) auf alle Kanten der
4440 	 in der miniliste (weiter hinten) gespeicherten Bauchbinde
4441          abgebildet werden. Es ergeben sich verschiedene Abbildungen. Teilweise handelt es
4442          sich dabei natuerlich nicht um Automorphismen. Die verbleibenden Spiegelabbildungen, bei
4443          denen es sich wirklich um Automorphismen handelt, koennen sogar unterschiedliche
4444          Ordnungen haben (Beispiel:  drehung==5 und in der miniliste steht Ebenenspiegelung
4445          an Ebene parallel zur Bauchbinde.  Eine Abbildung spiegelt nur => Ordnung 2. Eine
4446          andere Abbildung spiegelt und macht eine Fuenfteldrehung um die Bauchbinde
4447          => Ordnung 10).  Sobald eine Ebenenspiegelung gefunden wurde, eruebrigt sich NICHT die Suche
4448          nach anderen Spiegelabbildungen zwischen den beiden betrachteten Bauchbinden, denn
4449          andere Spiegelebenen koennen gefunden werden: Es ist zwar nicht moeglich, dass zwei verschiedene
4450          Spiegelebenen eine einzelne Kante aufeinander abbilden, aber es ist moeglich, dass zwei verschie-
4451          dene Spiegelebenen zwei verschiedene Bauchbinden als Gesamtes jeweils aufeinander abbilden,
4452          wobei die einzelnen Kanten der Bauchbinden jeweils unterschiedlich aufeinander abgebildet werden
4453          (Beispiel:  Fulleren Nummer 145886 bei C100).  */
4454 
4455   while (m_laenge>1) {      /* Liste durchforsten und dabei aufloesen */
4456     /* Zunaechst wird versucht, weitere Spiegelebenen zu ermitteln, die senkrecht auf der Bauchbinde
4457        stehen, die mit k1 beginnt, und die diese Bauchbinde auf sich selbst abbilden.
4458        Das Verfahren ist dasselbe wie oben. Es kann sein, dass eine
4459        gefundene Spiegelebene bereits gespeichert ist, weil sie z.B. gleichzeitig senkrecht auf zwei
4460        Bauchbinden steht. Deshalb muessen neu gefundene Spiegelebenen mit bereits gefundenen
4461        Spiegelebenen verglichen werden. */
4462     if (sp_ebene==2) {     /* falls bei Originalpfad Spiegelebene vorhanden <=> so auch hier */
4463       k1 = miniliste[m_laenge-1];               /* erste Kante */
4464       k2 = k1;
4465       gefunden = 0;         /* noch keine Spiegelebene gefunden */
4466       j=1; i=0;
4467       while (j<=knoten_auf_pfad/2) {     /* den halben Pfad entlanggehen */
4468         if (j%2) {k2 = k1->invers->prev;}  else  {k2 = k1->invers->next;}
4469         if (gefunden==0 || (gefunden==1 && i==knoten_auf_pfad/(2*drehung))) {      /* Suche lohnt sich */
4470           if (bilde_f_und_g_sp(&f[0],&g[0],k1,k2->invers,map[0][0].name)) {
4471             gefunden=1;    /* fuendig */
4472             alt = ii = 0;
4473             while (!alt && ii<n2) {          /* Spiegelung bereits gespeichert? */
4474               if (f1[ii][0]==f[miniliste[0]->ursprung] && f1[ii][1]==f[miniliste[0]->name]) {alt=1;}
4475               ii++;
4476             }
4477             if (!alt) {f1[n2][0]=f[miniliste[0]->ursprung];    f1[n2][1]=f[miniliste[0]->name];    n2++;}
4478             i=0;           /* Zaehler fuer jetzt beginnende schnelle Suche */
4479           }
4480         }
4481         k1 = k2;       /* zur naechsten Kante des Pfades */
4482         j++;  i++;
4483       }                    /* while j */
4484     }     /* if sp_ebene==2 */
4485 
4486     /* Nun wird versucht, weitere Drehungen zu ermitteln, die die Bauchbinde auf sich selbst abbilden.
4487        Auch hier muessen neu gefundene Drehungen mit bereits gefundenen Drehungen verglichen werden. */
4488     /* zunaechst zur inneren Drehung */
4489     if (drehung>1) {     /* falls bei Originalpfad innere Drehung <=> so auch hier */
4490       k2 = miniliste[m_laenge-1];
4491       for (j=1; j<=knoten_auf_pfad/drehung; j++) {
4492         if (j%2) {k2 = k2->invers->prev;}  else  {k2 = k2->invers->next;}
4493       }
4494       if (bilde_f_und_g(&f[0],&g[0],miniliste[m_laenge-1],k2,map[0][0].name)) {    /* Abbildung holen */
4495         alt = ii = ord = 0;
4496         while (!alt && ii<n) {           /* Drehung bereits gespeichert? */
4497           if (ordnung[ii]==drehung) {
4498             e1 = miniliste[0]->ursprung;  e2 = miniliste[0]->name;  i = 0;
4499             do {
4500               e1 = f[e1];   e2 = f[e2];   i++;
4501             } while (i<drehung && (e1!=f2[ii][0] || e2!=f2[ii][1]));
4502             if (i<drehung) {alt=1;}
4503           }
4504           ii++;
4505         }
4506         if (!alt) {
4507           f2[n][0] = f[e1];     /* Beispielkante */
4508           f2[n][1] = f[e2];
4509           ordnung[n] = drehung;
4510           n++;
4511         }
4512       }       /* if */
4513     }         /* if drehung>1 */
4514 
4515     /* Nun zu den Zweierdrehungen an den Kantenzentren der Bauchbinde */
4516     if (zdrehung==2) {          /* Zweierdrehung(en) beim Originalpfad <=> so auch hier */
4517       k1 = miniliste[m_laenge-1];               /* erste Kante */
4518       j=1;  i=0;  gefunden=0;
4519       while (j<=knoten_auf_pfad/2) {            /* den halben Pfad entlanggehen */
4520         if (gefunden==0 || (gefunden==1 && i==knoten_auf_pfad/(2*drehung))) {            /* Suche lohnt sich */
4521           if (bilde_f_und_g(&f[0],&g[0],k1,k1->invers,map[0][0].name)) {
4522             gefunden=1;     /* fuendig */
4523             alt = ii = 0;
4524             while (!alt && ii<n) {
4525               if (ordnung[ii]==2) {
4526                 if (f2[ii][0]==f[miniliste[0]->ursprung] && f2[ii][1]==f[miniliste[0]->name]) {alt=1;}
4527               }
4528               ii++;
4529             }
4530             if (!alt) {
4531               f2[n][0] = f[miniliste[0]->ursprung];    f2[n][1] = f[miniliste[0]->name];
4532               ordnung[n] = 2;  n++;
4533             }
4534             i=0;         /* Zaehler fuer jetzt beginnende schnelle Suche */
4535           }
4536         }
4537         if (j%2) {k1 = k1->invers->prev;}  else  {k1 = k1->invers->next;}  /* zur naechsten Kante des Pfades */
4538         j++;   i++;
4539       }                /* while */
4540     }
4541 
4542     /* Nun werden Abbildungen zwischen der Bauchbinde 0 und der letzten Bauchbinde in der Liste
4543        betrachtet, und zwar wie oben beschrieben. */
4544     k1 = miniliste[0];
4545     k2 = miniliste[m_laenge-1];      /* es wird immer der letzte Pfad in der Liste betrachtet */
4546     ordnung2 = 0;           /* Ordnung des gefundenen nicht ordnungserhaltenden Automorphismus */
4547     j = 1;
4548     while (j<=knoten_auf_pfad) {            /* den Bildpfad entlanggehen */
4549       if (minierg[m_laenge-1]&2) {          /* Drehung moeglich */
4550         if (bilde_f_und_g(&f[0],&g[0],k1,k2,map[0][0].name)) {
4551           /* ordnungserhaltenden Automorphismus gefunden */
4552           ord = 0;                   /* Ordnung des Automorphismus ermitteln */
4553           e1 = k1->ursprung;  e2 = k1->name;
4554           do {
4555             e1 = f[e1];  e2 = f[e2];
4556             ord++;
4557             if (ord>12) {fprintf(stderr,"Ordnung eines Automorphismus groesser als 12!\n"); exit(43);}
4558           } while ((e1!=k1->ursprung) || (e2!=k1->name));   /* bis Identitaet erreicht */
4559           alt = ii = 0;             /* mit bereits gefundenen Drehungen vergleichen */
4560           while (!alt && ii<n) {           /* Drehung bereits gespeichert? */
4561             if (ordnung[ii]==ord) {
4562               e1 = k1->ursprung;  e2 = k1->name;  i = 0;
4563               do {
4564                 e1 = f[e1];   e2 = f[e2];   i++;
4565               } while (i<ord && (e1!=f2[ii][0] || e2!=f2[ii][1]));
4566               if (i<ord) {alt=1;}
4567             }
4568             ii++;
4569           }
4570           if (!alt) {
4571             f2[n][0] = f[e1];     /* Beispielkante */
4572             f2[n][1] = f[e2];     /* e1 und e2  haben wieder die urspruenglichen Werte */
4573             ordnung[n] = ord;
4574 	    n++;
4575           }          /* if */
4576         }            /* if */
4577 
4578         /* dasselbe mit spiegelverkehrtem Pfad */
4579         if (bilde_f_und_g(&f[0],&g[0],k1,k2->invers,map[0][0].name)) {
4580           /* ordnungserhaltenden Automorphismus gefunden */
4581           ord = 0;                   /* Ordnung des Automorphismus ermitteln */
4582           e1 = k1->ursprung;  e2 = k1->name;
4583           do {
4584             e1 = f[e1];  e2 = f[e2];
4585             ord++;
4586             if (ord>12) {fprintf(stderr,"Ordnung eines Automorphismus groesser als 12!\n"); exit(44);}
4587           } while ((e1!=k1->ursprung) || (e2!=k1->name));   /* bis Identitaet erreicht */
4588           alt = ii = 0;             /* mit bereits gefundenen Drehungen vergleichen */
4589           while (!alt && ii<n) {           /* Drehung bereits gespeichert? */
4590             if (ordnung[ii]==ord) {
4591               e1 = k1->ursprung;  e2 = k1->name;  i = 0;
4592               do {
4593                 e1 = f[e1];   e2 = f[e2];    i++;
4594               } while (i<ord && (e1!=f2[ii][0] || e2!=f2[ii][1]));
4595               if (i<ord) {alt=1;}
4596             }
4597             ii++;
4598           }
4599           if (!alt) {
4600             f2[n][0] = f[e1];     /* Beispielkante */
4601             f2[n][1] = f[e2];
4602             ordnung[n] = ord;
4603             n++;
4604           }          /* if */
4605         }          /* if */
4606       }         /* if minierg&2 */
4607 
4608       if (minierg[m_laenge-1]&4) {            /* Ebenenspiegelung moeglich */
4609         if (bilde_f_und_g_sp(&f[0],&g[0],k1,k2->invers->prev,map[0][0].name)) {
4610           /* nicht ordnungserhaltenden Automorphismus gefunden */
4611           ord = 0;                   /* Ordnung des Automorphismus */
4612           /* da {e1,e2} eventuell Fixkante ist, muss eine weitere Kante {e1,e3} betrachtet werden */
4613           e1 = k1->ursprung;  e2 = k1->name;  e3 = k1->prev->name;
4614           do {
4615             e1 = f[e1];  e2 = f[e2];  e3 = f[e3];
4616             ord++;
4617             if (ord>12) {fprintf(stderr,"Ordnung eines Automorphismus groesser als 12!\n"); exit(45);}
4618           } while ((e1!=k1->ursprung) || (e2!=k1->name) || (e3!=k1->prev->name));  /* Identitaet erreicht */
4619           if (ordnung2==0 || ordnung2>ord)  {ordnung2=ord;}
4620 	  if (ord>drehsp) {drehsp=ord;}     /* groesste gefundene Drehspiegelung speichern */
4621             /* falls in Wirklichkeit Ebenenspiegelung => egal, denn => n2>0 => drehsp wird nicht abgefragt */
4622           if (ord==2) {                /* testen: ist gefundene Funktion Ebenenspiegelung? */
4623             i = dreh = 1;
4624             while (dreh && i<=map[0][0].name) {            /* Fixpunkte/Beruehrungspunkte suchen */
4625               if (f[i]==map[i][0].name || f[i]==map[i][1].name || f[i]==map[i][2].name || f[i]==i) {dreh=0;}
4626               i++;
4627             }
4628             if (!dreh) {              /* Ebenenspiegelung gefunden */
4629               alt = ii = 0;
4630               while (!alt && ii<n2) {          /* Spiegelung bereits gespeichert? */
4631                 if (f1[ii][0]==f[k1->ursprung] && f1[ii][1]==f[k1->name]) {alt=1;}
4632                 ii++;
4633               }
4634               if (!alt) {f1[n2][0]=f[k1->ursprung];    f1[n2][1]=f[k1->name];   n2++;}
4635             }     /* if */
4636           }       /* if */
4637         }         /* if */
4638 
4639         /* dasselbe mit spiegelverkehrtem Pfad */
4640         if (bilde_f_und_g_sp(&f[0],&g[0],k1,k2->invers->prev->invers,map[0][0].name)) {
4641           /* nicht ordnungserhaltenden Automorphismus gefunden */
4642           ord = 0;                   /* Ordnung des Automorphismus */
4643           /* da {e1,e2} eventuell Fixkante ist, muss eine weitere Kante {e1,e3} betrachtet werden */
4644           e1 = k1->ursprung;  e2 = k1->name;  e3 = k1->prev->name;
4645           do {
4646             e1 = f[e1];   e2 = f[e2];   e3 = f[e3];
4647             ord++;
4648             if (ord>12) {fprintf(stderr,"Ordnung eines Automorphismus groesser als 12!\n"); exit(46);}
4649           } while ((e1!=k1->ursprung) || (e2!=k1->name) || (e3!=k1->prev->name));   /* Identitaet erreicht */
4650           if (ordnung2==0 || ordnung2>ord)  {ordnung2=ord;}
4651           if (ord>drehsp) {drehsp=ord;}    /* groesste gefundene Drehspiegelung speichern */
4652 	  if (ord==2) {               /* testen: ist gefundene Funktion Ebenenspiegelung? */
4653             i = dreh = 1;
4654             while (dreh && i<=map[0][0].name) {
4655               if (f[i]==map[i][0].name || f[i]==map[i][1].name || f[i]==map[i][2].name || f[i]==i) {dreh=0;}
4656               i++;
4657             }
4658             if (!dreh) {              /* Ebenenspiegelung gefunden */
4659               alt = ii = 0;
4660               while (!alt && ii<n2) {          /* Spiegelung bereits gespeichert? */
4661                 if (f1[ii][0]==f[k1->ursprung] && f1[ii][1]==f[k1->name]) {alt=1;}
4662                 ii++;
4663               }
4664               if (!alt) {f1[n2][0]=f[k1->ursprung];    f1[n2][1]=f[k1->name];   n2++;}
4665             }     /* if */
4666           }       /* if */
4667         }         /* if */
4668       }           /* if (minierg&4) */
4669 
4670       k2 = k2->invers->prev->invers->next;     /* zwei Kanten weiter */
4671       j+=2;
4672     }                /* while j */
4673 
4674     m_laenge--;    /* letzter (untersuchter) Pfad wird geloescht */
4675   }     /* while m_laenge>1 */
4676 
4677   /* Nun werden Drehungen, die doppelt gezaehlt wurden, aus der Liste ordnung[] genommen. Folgender
4678      Fall:
4679      - Sechserdrehung in der Liste:   eine Zweierdrehung und eine Dreierdrehung zuviel, aber nur
4680        dann,  wenn die Sechserdrehung aus zwei verschiedenen Pfaden rekonstruiert wurde und nicht,
4681        wenn die Sechserdrehung aus dem Wert von "drehung" folgt.
4682      Die Inhalte der Arrays f1 und f2 werden nicht zusammen mit den Inhalten von ordnung verschoben,
4683      da sie nicht mehr gebraucht werden.  */
4684   if (drehung!=6) {
4685     j=0;
4686     while (j<n) {
4687       if (ordnung[j]==6) {
4688         ii = 0;   i = 0;
4689         while (ii<1 && i<n) {
4690           if (ordnung[i]==3) {
4691             if (i>j) {ordnung[i]=ordnung[n-1];  n--;  ii++;}
4692             else     {ordnung[i]=ordnung[j-1];  ordnung[j-1]=ordnung[j];     /* i<j */
4693                       ordnung[j]=ordnung[n-1];  n--;  ii++;  j--;}
4694           }
4695           else  {i++;}
4696         }
4697         if (ii<1) {fprintf(stderr,"Es fehlt eine Dreierdrehung.\n"); exit(47);}
4698         ii = 0;   i = 0;
4699         while (ii<1 && i<n) {
4700           if (ordnung[i]==2) {
4701             if (i>j) {ordnung[i]=ordnung[n-1];  n--;  ii++;}
4702             else     {ordnung[i]=ordnung[j-1];  ordnung[j-1]=ordnung[j];
4703                       ordnung[j]=ordnung[n-1];  n--;  ii++;  j--;}
4704           }
4705           else  {i++;}
4706         }
4707         if (ii<1) {fprintf(stderr,"Es fehlt eine Zweierdrehung.\n"); exit(48);}
4708         j=n;     /* Es tritt hoechstens eine Sechserdrehung auf => Abbruch */
4709       }   /* if */
4710       j++;
4711     }     /* while */
4712   }       /* if */
4713 
4714   /* Jetzt ist die Anzahl der Ebenenspiegelungen (n2) und die Anzahl (n) und Art (ordnung[]) der
4715      Drehungen bekannt. */
4716   /* Es folgt die Bestimmung der Symmetriegruppe. */
4717 
4718   /* Testblock: funktioniert das Programm richtig? */
4719   /* der gesamte Switch-Block kann entfallen, sobald das Vertrauen in die Prozedur gross genug ist */
4720   switch(n2) {
4721     case 0: {switch(n) {
4722                case 0:  {if (drehsp!=2) {fprintf(stderr, "%lld: Fehler bei Ci %d\n", graphenzahl[map[0][0].name]+1,
4723                                          drehsp); exit(49);}
4724                          break;}
4725                case 1:  {if (drehsp==4) {if (ordnung[0]!=2)
4726                             {fprintf(stderr,"%lld: Fehler bei S4\n", graphenzahl[map[0][0].name]+1); exit(50);} }
4727 	                 if (drehsp==6) {if (ordnung[0]!=3)
4728                             {fprintf(stderr,"%lld: Fehler bei S6\n", graphenzahl[map[0][0].name]+1); exit(51);} }
4729 		         if (ordnung[0]!=2 && ordnung[0]!=3)
4730                             {fprintf(stderr, "%lld: Fehler bei C%d\n", graphenzahl[map[0][0].name]+1, ordnung[0]);
4731                              exit(52);}
4732 		         break;}
4733 	       case 3:  {if (ordnung[0]!=2 || ordnung[1]!=2 || ordnung[2]!=2)
4734                             {fprintf(stderr, "%lld: Fehler bei D2\n", graphenzahl[map[0][0].name]+1); exit(53);}
4735 	                 break;}
4736 	       case 4:  {if (ordnung[0]+ordnung[1]+ordnung[2]+ordnung[3]!=9)
4737                             {fprintf(stderr, "%lld: Fehler bei D3\n", graphenzahl[map[0][0].name]+1); exit(54);}
4738 	                 break;}
4739 	       case 6:  {if (ordnung[0]+ordnung[1]+ordnung[2]+ordnung[3]+ordnung[4]+ordnung[5] !=15)
4740 	                    {fprintf(stderr, "%lld: Fehler bei D5\n", graphenzahl[map[0][0].name]+1); exit(55);}
4741                          break;}
4742 	       case 7:  {BOOL d6=0;  int k=1;
4743                          for (i=0; i<7; i++) {k*=(int)(ordnung[i]); if (ordnung[i]==6) {d6=1;} }
4744                          if (d6) {if (k!=64*6)
4745                                   {fprintf(stderr, "%lld: Fehler bei D6\n", graphenzahl[map[0][0].name]+1); exit(56);} }
4746                          else    {if (k!=81*8)
4747                                   {fprintf(stderr, "%lld: Fehler bei T\n", graphenzahl[map[0][0].name]+1); exit(57);} }
4748          		 break;
4749 		        }
4750                case 31: break;
4751 	       default: {fprintf(stderr, "%lld: Fehler 0 %d\n", graphenzahl[map[0][0].name]+1, n);  exit(58);}
4752 	     }
4753 	     break;}
4754     case 1: {switch(n) {
4755                case 0:  break;
4756    	       case 1:  {switch(ordnung[0]) {
4757 	                   case 2:  break;
4758 	   		   case 3:  break;
4759 			   default: {fprintf(stderr, "%lld: Fehler 1 1 %d\n", graphenzahl[map[0][0].name]+1,
4760                                      ordnung[0]); exit(59);}
4761 		        } break;}
4762                default: {fprintf(stderr, "%lld: Fehler 1 %d\n", graphenzahl[map[0][0].name]+1, n); exit(60);}
4763 	     }
4764 	     break;}
4765     case 2: {switch(n) {
4766                case 1:  {if (ordnung[0]!=2)
4767                             {fprintf(stderr, "%lld: Fehler bei C2v\n", graphenzahl[map[0][0].name]+1); exit(61);}
4768                          break;}
4769 	       case 3:  {if (ordnung[0]!=2 || ordnung[1]!=2 || ordnung[2]!=2)
4770 	                    {fprintf(stderr, "%lld: Fehler bei D2d\n", graphenzahl[map[0][0].name]+1); exit(62);}
4771                          break;}
4772 	       default: {fprintf(stderr, "%lld: Fehler 2 %d\n", graphenzahl[map[0][0].name]+1, n);  exit(63);}
4773 	     }
4774 	     break;}
4775     case 3: {switch(n) {
4776                case 1:  {if (ordnung[0]!=3)
4777                             {fprintf(stderr, "%lld: Fehler bei C3v\n", graphenzahl[map[0][0].name]+1);  exit(64);}
4778                          break;}
4779 	       case 3:  {if (ordnung[0]!=2 || ordnung[1]!=2 || ordnung[2]!=2)
4780                             {fprintf(stderr, "%lld: Fehler bei D2h\n", graphenzahl[map[0][0].name]+1);  exit(65);}
4781                          break;}
4782 	       case 4:  {if (ordnung[0]+ordnung[1]+ordnung[2]+ordnung[3]!=9)
4783                             {fprintf(stderr, "%lld: Fehler bei D3d\n", graphenzahl[map[0][0].name]+1);  exit(66);}
4784                          break;}
4785 	       case 7:  {int k=1;
4786                          for (i=0; i<7; i++) {k*=(int)(ordnung[i]);}
4787                          if (k!=81*8)
4788                             {fprintf(stderr, "%lld: Fehler bei Th\n", graphenzahl[map[0][0].name]+1);  exit(67);}
4789                          break;}
4790 	       default: {fprintf(stderr, "%lld: Fehler 3 %d\n", graphenzahl[map[0][0].name]+1, n);  exit(68);}
4791 	     }
4792 	     break;}
4793     case 4: {if (n!=4 || ordnung[0]+ordnung[1]+ordnung[2]+ordnung[3]!=9)
4794                 {fprintf(stderr, "%lld: Fehler bei D3h\n", graphenzahl[map[0][0].name]+1); exit(69);}
4795              break;}
4796     case 5: {if (n!=6 || ordnung[0]*ordnung[1]*ordnung[2]*ordnung[3]*ordnung[4]*ordnung[5]!=32*5)
4797                 {fprintf(stderr, "%lld: Fehler bei D5d\n", graphenzahl[map[0][0].name]+1); exit(77);}
4798              break;}
4799     case 6: {switch(n) {
4800                case 6: {if (ordnung[0]*ordnung[1]*ordnung[2]*ordnung[3]*ordnung[4]*ordnung[5]!=32*5)
4801                             {fprintf(stderr, "%lld: Fehler bei D5h\n", graphenzahl[map[0][0].name]+1); exit(70);}
4802                         break;}
4803 	       case 7: {BOOL d6=0;  int k=1;
4804                         for (i=0; i<7; i++) {k*=(int)(ordnung[i]); if (ordnung[i]==6) {d6=1;} }
4805                         if (d6) {if (k!=64*6)
4806                                 {fprintf(stderr, "%lld: Fehler bei D6d\n", graphenzahl[map[0][0].name]+1); exit(71);} }
4807                         else    {if (k!=81*8)
4808                                 {fprintf(stderr, "%lld: Fehler bei Td\n", graphenzahl[map[0][0].name]+1); exit(72);} }
4809                         break;}
4810   	       default: {fprintf(stderr, "%lld: Fehler 6 %d\n", graphenzahl[map[0][0].name]+1, n); exit(73);}
4811 	     }
4812 	     break;}
4813     case 7: {BOOL d6=0; int k=1;
4814              for (i=0; i<7; i++) {k*=(int)(ordnung[i]); if (ordnung[i]==6) {d6=1;} }
4815              if (d6==0 || n!=7 || k!=64*6)
4816                 {fprintf(stderr, "%lld: Fehler bei D6h\n", graphenzahl[map[0][0].name]+1); exit(74);}
4817              break;}
4818     case 15: {if (n!=31) {fprintf(stderr, "%lld: Fehler bei Ih\n", graphenzahl[map[0][0].name]+1); exit(75);}
4819               break;}
4820     default: {fprintf(stderr, "%lld: Fehler %d %d\n", graphenzahl[map[0][0].name]+1, n2, n); exit(76);}
4821   }
4822 
4823   /* Nun tatsaechliche Auswertung */
4824   switch(n2) {
4825     case 0: {switch(n) {
4826                case 0:  return(Ci__);
4827 	       case 1:  {if (drehsp==4) {return(S4__);}
4828 	                 if (drehsp==6) {return(S6__);}
4829 		         switch(ordnung[0]) {
4830 		    	   case 2:  return(C2__);
4831 			   case 3:  return(C3__);
4832 			   default: exit(78);
4833 		         }
4834 		         break;}
4835   	       case 3:  return(D2__);
4836 	       case 4:  return(D3__);
4837 	       case 6:  return(D5__);
4838 	       case 7:  {BOOL d6=0;
4839                          for (i=0; i<7; i++) {if (ordnung[i]==6) {d6=1;} }
4840                          if (d6) {return(D6__);}
4841                          else    {return(T__);}
4842 		        }
4843                case 31: return(I__);
4844 	       default: exit(79);
4845 	     }
4846 	     break;}
4847     case 1: {switch(n) {
4848                case 0:  return(Cs__);
4849 	       case 1:  switch(ordnung[0]) {
4850 	                   case 2:  return(C2h__);
4851 		  	   case 3:  return(C3h__);
4852 			   default: exit(80);
4853 		        }
4854                default: exit(0);
4855 	     }
4856 	     break;}
4857     case 2: {switch(n) {
4858                case 1:  return(C2v__);
4859 	       case 3:  return(D2d__);
4860 	       default: exit(81);
4861 	     }
4862 	     break;}
4863     case 3: {switch(n) {
4864                case 1:  return(C3v__);
4865     	       case 3:  return(D2h__);
4866 	       case 4:  return(D3d__);
4867 	       case 7:  return(Th__);
4868 	       default: exit(82);
4869 	     }
4870 	     break;}
4871     case 4: return(D3h__);
4872     case 5: return(D5d__);
4873     case 6: {switch(n) {
4874                case 6: return(D5h__);
4875 	       case 7: {BOOL d6=0;
4876                         for (i=0; i<7; i++) {if (ordnung[i]==6) {d6=1;} }
4877                         if (d6) {return(D6d__);}
4878                         else    {return(Td__);}
4879                        }
4880 	       default: exit(83);
4881 	     }
4882 	     break;}
4883     case 7: return(D6h__);
4884     case 15: return(Ih__);
4885     default: exit(84);
4886   }   /* switch */
4887 
4888 }      /* if code[1]==1 */
4889 
4890 }      /* Abgrenzung des Symmetrieteils (neue Variablen) */
4891  return 1; /* wird nie erreicht -- nur um Compilerwarnungen vorzubeugen */
4892 }      /* Ende der Prozedur */
4893 
4894 
4895 /**********************CHECKSIZE_RIGHT_2**************************************/
4896 
4897 /* bestimmt die groesse der flaeche rechts von edge -- ist da keine gibt's
4898    hier aber keine Probleme, sondern 6 wird zurueckgegeben -- dient nur
4899    zur Ueberpruefung, ob da ein 5-Eck ist.
4900 
4901    Es wird allerdings angenommen, dass edge->name nicht aussen ist
4902 */
4903 
4904 
checksize_right_2(KANTE * edge)4905 int checksize_right_2( KANTE* edge)
4906 {
4907 KANTE *run;
4908 int zaehler=1;
4909 
4910 for (run=edge->invers->prev; run != edge; run=run->invers->prev)
4911   { if (run->name==aussen) return(6); zaehler++; }
4912 return(zaehler);
4913 }
4914 
4915 
4916 
4917 
4918 /**********************CHECKSIZE_2**************************************/
4919 
4920 /* bestimmt die groesse der flaeche links von edge -- ist da keine gibt's
4921    hier aber keine Probleme, sondern 6 wird zurueckgegeben -- dient nur
4922    zur Ueberpruefung, ob da ein 5-Eck ist.
4923 
4924    Es wird allerdings angenommen, dass edge->name nicht aussen ist
4925 */
4926 
4927 
checksize_2(KANTE * edge)4928 int checksize_2( KANTE* edge)
4929 {
4930 KANTE *run;
4931 int zaehler=1;
4932 
4933 for (run=edge->invers->next; run != edge; run=run->invers->next)
4934   { if (run->name==aussen) return(6);
4935     zaehler++;  }
4936 return(zaehler);
4937 }
4938 
4939 
4940 
4941 
4942 /******************VERGLEICHE_SYMM************TH**************************/
4943 /*  Diese Funktion prueft, ob die Nummer "nr" im Array "symm" auftritt,
4944     wobei die ersten "symm_len" Arrayelemente belegt sind.               */
4945 
vergleiche_symm(char nr)4946 BOOL vergleiche_symm(char nr) {
4947   int i;
4948   for (i=0; i<symm_len; i++) {
4949     if (symm[i]==nr) {return(True);}
4950   }
4951   return(False);
4952 }
4953 
4954 
4955 /***********************TESTE_UND_SCHREIBE*******TH***********************/
4956 
4957 /* ueberprueft ein fertiges Fulleren, testet es auf Kanonizitaet und schreibt
4958    es gegebenenfalls auf */
4959 
teste_und_schreibe(PLANMAP map,KNOTENTYP * code)4960 void teste_und_schreibe(PLANMAP map, KNOTENTYP *code)
4961 { int erg;
4962 
4963 (non_iso_graphenzahl[map[0][0].name])++;
4964 if ((erg=minitest(map,code))) {
4965   (graphenzahl[map[0][0].name])++;
4966   if (symm_len==0 || vergleiche_symm(erg)) codiereplanar(map);
4967   (symm_anz[erg])++;                  /* fuer die Symmetriestatistik */
4968 }
4969 
4970 }
4971 
4972 
4973 /***********************SUCHE_ITEM**************************************/
4974 
suche_item(KNOTENTYP * adresse)4975 ITEMLISTE *suche_item(KNOTENTYP *adresse)
4976 {
4977 int i, laenge;
4978 SEQUENZLISTE *sq;
4979 
4980 laenge=8-adresse[0];
4981 
4982 sq=mapliste.sechser[adresse[1]];
4983 
4984 for (i=2; i<laenge; i++)
4985   { if (sq->number_next <= adresse[i]) return(nil);
4986     if (sq->next_level[adresse[i]]==nil) return(nil);
4987     sq=sq->next_level[adresse[i]]; }
4988 return(sq->items);
4989 }
4990 
4991 
4992 /***********************SUCHE_ITEM_BB**************************************/
4993 
suche_item_bb(KNOTENTYP * adresse)4994 BBITEMLISTE *suche_item_bb(KNOTENTYP *adresse)
4995 {
4996 
4997 BBSEQUENZLISTE *sq;
4998 
4999 sq=bbliste.sechser[adresse[1]];
5000 
5001 if (sq->number_next <= adresse[2]) return(nil);
5002 return(sq->items[adresse[2]]);
5003 }
5004 
5005 
5006 
5007 /*********************ADD_POLYGON_INVERS***********************************/
5008 
add_polygon_invers(int n,PLANMAP map,KANTE * start,KANTE ** lastout)5009 void add_polygon_invers(int n, PLANMAP map, KANTE *start, KANTE **lastout)
5010 /* fuegt ein weiteres polygon einer Reihe an. Dabei ist n die groesse des polygons.
5011    Angefuegt wird immer an start. Ueber lastout wird die letzte Aussenkante des
5012    Polygons zurueckgegeben.
5013    Es arbeitet wie add_polygon nur im anderen Drehsinn. Das wird fuer die REkonstruktion
5014    der Patches gebraucht
5015    Im Falle, dass nur eine Kante eingefuegt werden muss, wird *lastout auf die naechste
5016    zu benutzende Aussenkante gesetzt. Die ist nicht mit dem gebauten Polygon
5017    inzident. Im Falle, dass es sie nicht gibt, wird *lastout auf nil gesetzt.
5018 
5019    angefuegt wird in den Winkel in prev-Richtung, d.h. zwischen start und start->prev
5020 
5021  */
5022 
5023 
5024 {
5025 int i, new_tempknz, tempknz;
5026 KANTE *ende, *run;
5027 int common_vertices;
5028 
5029 
5030 if (start->name != aussen) { fprintf(stderr,"ERROR ADD_P_INV not starting at external edge\n");
5031 			     exit(86); }
5032 
5033 if (IPR && (n==5))
5034   {
5035     if (checksize_2(start->prev)==5) is_ipr=0;
5036     for (ende=start->prev->invers->prev, common_vertices=2; ende->name != aussen;
5037 	  ende=ende->invers->prev) {if (checksize_2(ende)==5) is_ipr=0;
5038                                      common_vertices++;
5039 				   }
5040   }
5041 else for (ende=start->prev->invers->prev, common_vertices=2; ende->name != aussen;
5042 	  ende=ende->invers->prev) common_vertices++;
5043 
5044 
5045 if (n<common_vertices)
5046    { fprintf(stderr,"polygon to insert (inv) too small !\n");
5047      exit(87); }
5048 
5049 /* es muessen also n-common_vertices knoten hinzugefuegt werden */
5050 
5051 tempknz=map[0][0].name;
5052 new_tempknz=tempknz+n-common_vertices;
5053 
5054 if (n-common_vertices==0) /* dann kommt kein knoten dazu */
5055   { start->name=ende->ursprung; start->invers=ende;
5056     ende->name=start->ursprung; ende->invers=start;
5057 
5058     for (ende=start->next->invers->next, common_vertices=2;
5059 	 (ende->name != aussen) && (common_vertices<6);
5060          ende=ende->invers->next) common_vertices++;
5061     if (common_vertices<6) *lastout=ende; /* ein common_vertices+1 -- Eck ist noch moeglich */
5062     else { *lastout=nil;
5063 	   if (ende==start->next) /* dann ist nur noch eine 5-Eck Luecke */
5064 	     { for (i=anzahl_5ek+5, run=start->invers; anzahl_5ek<i;
5065 		  anzahl_5ek++, run=run->invers->next) { F_eck_kanten[anzahl_5ek]=run;
5066 							 if (IPR)
5067 							   if (checksize_right_2(run)==5) is_ipr=0; }
5068 	     }
5069 	 }
5070   }
5071 else
5072   {
5073     if (n-common_vertices==1) /* dann kommt nur ein knoten dazu */
5074       {
5075 	tempknz++;
5076 	start->name=tempknz; start->invers=map[tempknz];
5077 	map[tempknz][0].name=start->ursprung; map[tempknz][0].invers=start;
5078 	map[tempknz][1].name=ende->ursprung; map[tempknz][1].invers=ende;
5079 	ende->name=tempknz; ende->invers=map[tempknz]+1;
5080 	map[tempknz][2].name=aussen; map[tempknz][2].invers=nil;
5081 	*lastout=map[tempknz]+2;
5082 	map[0][0].name=tempknz;
5083       }
5084     else
5085       {
5086 
5087 	/* es bleibt: mindestens zwei neue knoten */
5088 
5089 	tempknz++;
5090 	start->name=tempknz; start->invers=map[tempknz];
5091 	map[tempknz][0].name=start->ursprung; map[tempknz][0].invers=start;
5092 	map[tempknz][1].name=tempknz+1; map[tempknz][1].invers=map[tempknz+1];
5093 	map[tempknz][2].name=aussen; map[tempknz][2].invers=nil;
5094 
5095 	for (tempknz++; tempknz<new_tempknz; tempknz++)
5096 	  { map[tempknz][0].name=tempknz-1; map[tempknz][0].invers=map[tempknz-1]+1;
5097 	    map[tempknz][1].name=tempknz+1; map[tempknz][1].invers=map[tempknz+1];
5098 	    map[tempknz][2].name=aussen; map[tempknz][2].invers=nil; }
5099 
5100 	/* und nun noch den letzten knoten */
5101 	map[tempknz][0].name=tempknz-1; map[tempknz][0].invers=map[tempknz-1]+1;
5102 	map[tempknz][1].name=ende->ursprung; map[tempknz][1].invers= ende;
5103 	ende->name=tempknz; ende->invers=map[tempknz]+1;
5104 	map[tempknz][2].name=aussen; map[tempknz][2].invers=nil;
5105 	*lastout=map[tempknz]+2;
5106 	map[0][0].name=tempknz;
5107       } /* ende zweites else */
5108   } /* ende erstes else */
5109 
5110 if (n==5)
5111   for (i=anzahl_5ek+5, run=start; anzahl_5ek<i;
5112        anzahl_5ek++, run=run->invers->next) F_eck_kanten[anzahl_5ek]=run;
5113 
5114 return;
5115 }
5116 
5117 
5118 /***************************BAUE_KUPPE********************************/
5119 
baue_kuppe(PLANMAP map,int bblaenge,FLAECHENTYP code[],KANTE ** anfang,int flaechenzahl)5120 void baue_kuppe(PLANMAP map, int bblaenge, FLAECHENTYP code[], KANTE **anfang, int flaechenzahl)
5121 {
5122 int i, puffer, codestelle, zaehler, flaechenzaehler;
5123 KANTE *run;
5124 
5125 
5126 
5127 puffer=2*bblaenge;
5128 
5129 if (*anfang==nil) /* d.h. Bauchbinde und obere Kuppe bauen und Anfang zurueckgeben */
5130   {
5131         map[1][0].name=puffer; map[1][0].invers=map[puffer]+1;
5132 	map[1][1].name=aussen; map[1][1].invers=nil;
5133 	map[1][2].name=2; map[1][2].invers=map[2];
5134 
5135    for (i=2; i<2*bblaenge; i++)
5136       { map[i][0].name=i-1; map[i][0].invers=map[i-1]+2;
5137 	map[i][1].name=i+1; map[i][1].invers=map[i+1];
5138 	map[i][2].name=aussen; map[i][2].invers=nil;
5139 	i++;
5140         map[i][0].name=i-1; map[i][0].invers=map[i-1]+1;
5141 	map[i][1].name=aussen; map[i][1].invers=nil;
5142 	map[i][2].name=i+1; map[i][2].invers=map[i+1];
5143       }
5144 	map[puffer][0].name=puffer-1; map[puffer][0].invers=map[puffer-1]+2;
5145 	map[puffer][1].name=1; map[puffer][1].invers=map[1];
5146 	map[puffer][2].name=aussen; map[puffer][2].invers=nil;
5147 
5148 	map[0][0].name= puffer;
5149 	*anfang=map[2]+2;
5150 
5151 	for (run=map[1]+1, zaehler=1; zaehler<= bblaenge*code[0]; zaehler++ )
5152 	  { add_polygon_invers(6, map, run, &run);
5153 	    if (run==nil) { fprintf(stderr,"ERROR: nil-edge while building hexagon rings\n");
5154 			    exit(88); }
5155 	  }
5156 	flaechenzaehler=zaehler;
5157 	for (codestelle=2, zaehler=1; run != nil; zaehler++, flaechenzaehler++ )
5158 	  {
5159 	    if ((codestelle<8) && (code[codestelle]==zaehler))
5160 	      { add_polygon_invers(5, map, run, &run); codestelle++; }
5161 	    else add_polygon_invers(6, map, run, &run);
5162 	  }
5163         if (flaechenzaehler != flaechenzahl)
5164 	  { fprintf(stderr,"Baue_Kuppe: Could not insert enough faces: ");
5165 	    fprintf(stderr,"%d instead of %d\n (upper half)\n",flaechenzaehler,flaechenzahl);
5166 	    exit(89); }
5167       } /* ende if *anfang==nil) */
5168 else /* d.h. untere Kuppe bauen */
5169   {
5170   for (run= *anfang, zaehler=1; zaehler <= bblaenge*code[0]; zaehler++ )
5171       { add_polygon_invers(6, map, run, &run);
5172 	if (run==nil) { fprintf(stderr,"ERROR: nil-edge while building hexagon rings\n");
5173     		    exit(90); }
5174       }
5175     flaechenzaehler=zaehler;
5176     for (codestelle=2, zaehler=1; run != nil; zaehler++, flaechenzaehler++ )
5177       { if ((codestelle<8) && (code[codestelle]==zaehler))
5178           { add_polygon_invers(5, map, run, &run); codestelle++; }
5179         else add_polygon_invers(6, map, run, &run);
5180       }
5181         if (flaechenzaehler != flaechenzahl)
5182 	  { fprintf(stderr,"Baue_Kuppe: Could not insert enough faces: ");
5183 	    fprintf(stderr,"%d instead of %d\n (upper half)\n",flaechenzaehler,flaechenzahl);
5184 	    exit(91); }
5185   } /* ende else */
5186 
5187 }
5188 
5189 
5190 
5191 /*********************BAUCHBINDE****************************************/
5192 
5193 /* Der erste Fall der Fullerenkonstruktion: Fullerene mit Bauchbinde */
5194 /*           ___________________________
5195 	    /                           \
5196 	    |                           |
5197 	    |                           |
5198 	    |                           |
5199 	    \__________________________/       */
5200 
5201 
5202 /* konvention: Die obere haelfte is die mit mehr sechsecken. Ist die
5203 Anzahl der sechsecke gleich, so ist es die mit dem groesseren code ohne
5204 Beruecksichtigung der verschiebung. Wenn eine code-kombination betrachtet
5205 wird, wo die haelfte mit weniger sechsecken noch 6-Eck-Ringe hat, ist sie
5206 eh nicht minimal, da der Gesamt-code rekonstruiert von der bauchbinde aus,
5207 die man erhaelt, wenn man die Ringe nach oben verschiebt, kleiner ist. */
5208 
5209 /* gesamtcode: (pfadlaenge,1,lowercode[],uppercode[],verschiebung)
5210    dabei wird beim vergleich die stelle, die in den codes die
5211    verschiebungsmoeglichkeiten beschreibt, nicht beruecksichtigt
5212    gesamtcodelaenge: 19 stellen */
5213 
5214 
bauchbinde(int min_sechsecke,int max_sechsecke)5215 void bauchbinde(int min_sechsecke, int max_sechsecke)
5216 {
5217 int sechsecke, i, j, k, bblaenge, upper6gons, lower6gons;
5218 KNOTENTYP adresse[4];
5219 KANTE *anfang, *merkeanfang; /* eine kante auf dem Rand zum Anfangen */
5220 KANTE *run;
5221 PLANMAP map;
5222 BBITEMLISTE *upitem, *lowitem;
5223 KNOTENTYP code[20];
5224 int modulozaehler;
5225 
5226 modulozaehler=rest;
5227 
5228 init_map(map);
5229 
5230 adresse[0]=6;
5231 code[1]=1; code[19]=leer;
5232 
5233 for (bblaenge=minbbl; bblaenge <= maxbbl; bblaenge++)
5234   if (bblmark[bblaenge])
5235   { adresse[2]=bblaenge;
5236     code[0]=2*bblaenge;
5237     for (sechsecke=min_sechsecke; sechsecke <= max_sechsecke; sechsecke++)
5238     for (upper6gons=sechsecke, lower6gons=0; upper6gons >= lower6gons;
5239 	 upper6gons--, lower6gons++)
5240          { adresse[1]=upper6gons;
5241 	   for (upitem=suche_item_bb(adresse); upitem != nil;
5242 		upitem=upitem->next_item)
5243 	       { adresse[1]=lower6gons; merkeanfang=nil;
5244 		 for (k=0; k<8; k++) code[k+10]=upitem->code[k];
5245 		 for (lowitem=suche_item_bb(adresse); lowitem!=nil; lowitem=lowitem->next_item)
5246 		   if ((lowitem->code[0]==0) &&
5247 		        ((upper6gons>lower6gons) || (codecmp(upitem->code+2,lowitem->code+2,6)>=0)))
5248 		     /* hier geht schon die minimalitaet ein: Wenn es einen 6-Eck-Ring gibt, kann der
5249 			nach oben verschoben werden und upper6gons wird noch groesser, lowercode
5250 			noch kleiner, der code also besser
5251 			Im Fall upper6gons==lower6gons,"(uppercode+2)<(lowercode+2)",aber upper6gons hat
5252 			einen 6-eck-ring, kann ein besserer code durch verschieben des ringes und vertauschen
5253 			von oben und unten gebaut werden  */
5254 		     { modulozaehler++;
5255 		       if (modulozaehler==mod) modulozaehler=0;
5256 		       if (!mod || (modulozaehler==0))
5257 			 { /* so dass nur gebaut wird, wenn auch ein passendes Unterteil gefunden wird
5258 			      und auch dann nur einmal: */
5259 			   if (merkeanfang==nil) { map[0][0].name=0;
5260 						   anzahl_5ek=0;
5261 						   baue_kuppe(map,bblaenge,upitem->code,&merkeanfang,upper6gons+6); }
5262 			   for (k=0; k<8; k++) code[k+2]=lowitem->code[k];
5263 			   for (i=0, anfang=merkeanfang; (i<lowitem->code[1]) && (i<upitem->code[1]); i++,
5264 				anfang=anfang->prev->invers->prev->invers->prev)
5265 			     { code[18]=i;
5266 			       anzahl_5ek=30;
5267 			       baue_kuppe(map,bblaenge,lowitem->code,&anfang,lower6gons+6);
5268 			       if ( is_ipr ) teste_und_schreibe(map,code); else is_ipr=1;
5269 			       /* Falls IPR nicht gesetzt ist, ist is_ipr immer 1 */
5270 			       /* Aufraeumen: */
5271 			       for (run=anfang, j=0; j<bblaenge;
5272 				    j++, run=run->next->invers->next->invers->next) run->name = aussen;
5273 			       map[0][0].name -= (2*lower6gons + 10 -bblaenge);
5274 			     } /* ende for ueber moegliche Marken bei lowitems */
5275 			 } /* ende if modulo */
5276 		     } /* ende for ueber lowitems */
5277 	       } /* ende for ueber upitems */
5278 	 } /* ende for ueber 6-Eckverteilung */
5279   } /* ende for ueber bauchbindenlaenge */
5280 } /* ende funktion */
5281 
5282 
5283 
5284 /***********************SUCHESTART********************************/
5285 
suchestart(KANTE * start)5286 KANTE *suchestart( KANTE *start)
5287 /* belegt eine sequenz und sucht die kanonische Kante mit dem kleinsten Namen
5288    arbeitet "invers", d.h. es wird als Innenrand gesehen, der gefuellt werden
5289    muss. Wird aufgerufen fuer Brille und Sandwich. Start muss eine Kante sein, die
5290    ins innere zeigt.*/
5291 
5292 {
5293 int i, j, k, zaehler, position;
5294 KANTE *run;
5295 int sequenz[7];
5296 KANTE *seqkanten[7];
5297 int puffer[7];
5298 char kan[7];
5299 
5300 
5301 
5302 while (start->next->invers->next->invers->next->name == aussen)
5303                       start=start->next->invers->next->invers->next;
5304 /* Sucht 2 Kanten hintereinander nach aussen -- zu unterscheiden vom namen aussen, was
5305    auch nach innen heissen kann. Duerfte nur fuer bauchbinden eine Endlosschleife sein */
5306 
5307 for (i=0; i<7; i++) { sequenz[i]=leer; seqkanten[i]=nil; kan[i]=0; }
5308 
5309 position=0;
5310 seqkanten[0]=start;
5311 
5312 
5313 for (zaehler=1, run=start;
5314      run->prev->invers->prev->invers->prev->name == aussen;
5315      run=run->prev->invers->prev->invers->prev) zaehler++;
5316 sequenz[0]=zaehler; position=1; seqkanten[1]=nil;
5317 for (run=run->prev->invers->prev->invers->prev->invers->prev; run->name != aussen;
5318      run=run->invers->prev)
5319 { sequenz[position]=0; position++; seqkanten[position]=nil; }
5320 /* naechste Kante vor nicht-0-sequenz suchen -- entsprechende innenkanten gibt es nicht
5321    und muessen sich dementsprechend auch nicht gemerkt werden */
5322 
5323 
5324 while (run != start)
5325 {
5326 seqkanten[position]=run;
5327 for (zaehler=1;
5328      run->prev->invers->prev->invers->prev->name == aussen;
5329      run=run->prev->invers->prev->invers->prev) { zaehler++; }
5330 sequenz[position]=zaehler; position++; seqkanten[position]=nil;
5331 for (run=run->prev->invers->prev->invers->prev->invers->prev; run->name != aussen;
5332      run=run->invers->prev)
5333 { sequenz[position]=0; position++; seqkanten[position]=nil; }
5334 }
5335 
5336 
5337 sequenz[position]=leer; seqkanten[position]=nil;
5338 
5339 kan[0]=sequenz_kanonisch(sequenz);
5340 
5341 
5342 for (i=0; sequenz[i] != leer; i++)
5343   { for (j=i, k=0; sequenz[j]!=leer; j++, k++) puffer[k]=sequenz[j];
5344     for (j=0; j<i; j++, k++) puffer[k]=sequenz[j];
5345     puffer[k]=leer;
5346     kan[i]=sequenz_kanonisch(puffer);
5347   }
5348 
5349 
5350 
5351 for (i=0, run=nil; sequenz[i] != leer; i++)
5352   { if (kan[i])
5353       if ((run==nil) || (seqkanten[i]->ursprung < run->ursprung)) run=seqkanten[i];
5354   }
5355 
5356 /* Jetzt die vorige Innenkante suchen, um rechts davon dann einfuegen zu koennen */
5357 for (run=run->next->invers->next->invers->next; run->name != aussen; run=run->invers->next);
5358 
5359 
5360 return(run);
5361 
5362 
5363 }
5364 
5365 /*******************BERECHNE_BRILLENADRESSEN*************************/
5366 
5367 /* berechnet die adressen 2 und 3 im Brillenfall .
5368    uebergeben werden l1 l3 und lgesamt. berechnet werden die
5369    sequenzen */
5370 
berechne_brillenadressen(int l1,int lg,int l3,KNOTENTYP * seg,KNOTENTYP * se3)5371 void berechne_brillenadressen( int l1, int lg, int l3, KNOTENTYP *seg,
5372 			      KNOTENTYP *se3 )
5373 {int l2, zaehler;
5374  int bogen1, bogen3;
5375 
5376 l2 = lg - l1 - l3;
5377 
5378 
5379 if ((l1%2) != 0) lg--;
5380 
5381 if ((l3 % 2) ==0)   /* l3 gerade */
5382   { se3[0]=4; se3[2]= (l3-2)/2; se3[3]=0; }
5383 else { se3[0]=5; se3[2]= (l3-1)/2; lg--; }
5384 
5385 /* Jetzt die grosse Sequenz: */
5386 
5387 if ((l2 % 2) == 0) /* "normale" Brille */
5388   {
5389     if (l1%2) /* d.h. ungerade -- bestimmt den Umlaufsinn */
5390        { if ((lg % 2)==0) seg[2]=lg/2; else seg[2]= (lg-1)/2;
5391          zaehler=3;
5392 	 if (l3 % 2) { seg[zaehler]=0; zaehler++; }
5393 	 seg[zaehler]= (l2-2)/2; zaehler++;
5394 	 if (l1 % 2) { seg[zaehler]=0; zaehler++; }
5395 	 seg[0]=8-zaehler;
5396        }
5397     else /* d.h. l1 gerade -- anderer Umlaufsinn */
5398        { if ((lg % 2)==0) seg[2]=lg/2; else seg[2]= (lg-1)/2;
5399          zaehler=3;
5400 	 if (l1 % 2) { seg[zaehler]=0; zaehler++; }
5401 	 seg[zaehler]= (l2-2)/2; zaehler++;
5402 	 if (l3 % 2) { seg[zaehler]=0; zaehler++; }
5403 	 seg[0]=8-zaehler;
5404        }
5405   }/* ende "normale" Brille */
5406 else /* d.h. "verbogene" Brille */
5407   {
5408     if (l1%2) bogen1= (l1+l2-2)/2; else bogen1=(l1+l2-1)/2;
5409     if (l3%2) bogen3= (l3+l2-2)/2; else bogen3=(l3+l2-1)/2;
5410     /* um das gleich kanonisch geordnet zu haben, muss da unterschieden werden */
5411     if (l1%2){
5412              /* l1 >= l3 reicht nicht, um die folgende Fallunterscheidung zu vermeiden */
5413              if ((bogen1 > bogen3) || ((bogen1==bogen3) && ((l3 % 2) == 0)))
5414 	       { seg[2]=bogen1;
5415 		 zaehler=3;
5416 		 if (l3 % 2) { seg[zaehler]=0; zaehler++; }
5417 		 seg[zaehler]=bogen3; zaehler++;
5418 		 if (l1 % 2) { seg[zaehler]=0; zaehler++; }
5419 		 seg[0]=8-zaehler;
5420 	       }
5421 	     else /* d.h. bogen3 kommt zuerst */
5422 	       { seg[2]=bogen3;
5423 		 zaehler=3;
5424 		 if (l1 % 2) { seg[zaehler]=0; zaehler++; }
5425 		 seg[zaehler]=bogen1; zaehler++;
5426 		 if (l3 % 2) { seg[zaehler]=0; zaehler++; }
5427 		 seg[0]=8-zaehler;
5428 	       }
5429 	   }
5430     else /* d.h. l1 gerade */
5431       {
5432 	/* keine Fallunterscheidung, da if immer true durch konvention l1>=l3 */
5433         /* if ((bogen1 > bogen3) || ((bogen1==bogen3) && ((l1 % 2) == 0))) */
5434 	         seg[2]=bogen1;
5435 		 seg[3]=bogen3;
5436 		 zaehler=4;
5437 		 if (l3 % 2) { seg[zaehler]=0; zaehler++; }
5438 		 seg[0]=8-zaehler;
5439        }
5440   } /* ende verbogene brille */
5441 
5442 }
5443 
5444 /********************BAUE_BRILLE***********************************/
5445 
5446 /* baut eine Brille. Dabei ist die Orientierung von Knoten mit
5447    ungerader Nummer auf dem Pfad  immer vorher->aussen->nachher
5448    GEWAEHLT.  Da zu jedem Patch frueher oder spaeter
5449    auch das Spiegelbild behandelt wird, ist diese Festlegung moeglich,
5450    aber Achtung -- das ist wichtig fuer die kanonische Darstellung */
5451 
baue_brille(int pfadlaenge,int laenge_1,int laenge_3,PLANMAP map,KANTE ** anfang_1,KANTE ** anfang_2,KANTE ** anfang_3)5452 void baue_brille(int pfadlaenge,int laenge_1,int laenge_3,PLANMAP map,
5453 		 KANTE **anfang_1, KANTE **anfang_2, KANTE **anfang_3)
5454 {
5455 int stelle_2, knotenzahl, i;
5456 KANTE *aussenzeiger, *letzte_Kante, *startkante_1, *startkante_2;
5457 
5458 knotenzahl=pfadlaenge-1;
5459 
5460 /* zuerst:
5461 
5462     knotenzahl-------stelle_2----------stelle1-------
5463                                                     |
5464                                            1        |
5465 					   |        |
5466 					   2--3-----
5467 ohne die zykelschliessenden Kanten */
5468 
5469 
5470 
5471 map[1][1].name=2; map[1][1].invers=map[2]+0;
5472 for (i=1; i<=knotenzahl; i++)
5473   { map[i][0].name=i-1; map[i][0].invers=map[i-1]+1;
5474     map[i][1].name=aussen; map[i][1].invers=nil;
5475     map[i][2].name=i+1; map[i][2].invers=map[i+1]+0;
5476     i++;
5477     if (i<=knotenzahl)
5478       { map[i][0].name=i-1; map[i][0].invers=map[i-1]+2;
5479 	map[i][2].name=aussen; map[i][2].invers=nil;
5480 	map[i][1].name=i+1; map[i][1].invers=map[i+1]+0; }
5481    }
5482 
5483 /* Knoten 1 und Knoten knotenzahl haben jetzt falsche vorher bzw nachher
5484    werte, sie muessen jetzt mit der Brille verklebt werden */
5485 
5486 if ((laenge_1%2)==0) aussenzeiger=map[laenge_1]+2; else aussenzeiger=map[laenge_1]+1;
5487 
5488 aussenzeiger->name=1; aussenzeiger->invers=map[1]+0;
5489 map[1][0].name=laenge_1; map[1][0].invers=aussenzeiger;
5490 
5491 stelle_2=pfadlaenge-laenge_3;
5492 if ((stelle_2%2)==0) aussenzeiger=map[stelle_2]+2; else aussenzeiger=map[stelle_2]+1;
5493 if ((knotenzahl%2)==0) letzte_Kante=map[knotenzahl]+1; else letzte_Kante=map[knotenzahl]+2;
5494 
5495 letzte_Kante->name=stelle_2; letzte_Kante->invers=aussenzeiger;
5496 aussenzeiger->name=knotenzahl; aussenzeiger->invers=letzte_Kante;
5497 
5498 map[0][0].name=knotenzahl;
5499 
5500 /* Jetzt die anfangskanten belegen: */
5501 
5502 if ((laenge_1 %2)==0) { startkante_1=map[2]+2; startkante_2=map[1]+1; }
5503                      /* dann zeigt die Aussenkante von Knoten 2 ins innere von zykel_1 */
5504                else  { startkante_2=map[2]+2; startkante_1=map[1]+1; }
5505 *anfang_1=suchestart(startkante_1);
5506 *anfang_2=suchestart(startkante_2);
5507 
5508 if ((knotenzahl%2)==0)
5509   { if ((laenge_3 % 2)==0) startkante_1=map[knotenzahl-1]+1;
5510        else startkante_1=map[knotenzahl]+2; }
5511   else /* d.h. knotenzahl ungerade */
5512   { if ((laenge_3 % 2)==0) startkante_1=map[knotenzahl-1]+2;
5513        else startkante_1=map[knotenzahl]+1; }
5514 *anfang_3=suchestart(startkante_1);
5515 
5516 } /* ende funktion */
5517 
5518 
5519 
5520 /*********************INSERT_PATCH*********************************/
5521 
insert_patch(PLANMAP map,KANTE * anfang,ITEMLISTE * item,int flaechenzahl,int fuenfecke)5522 void insert_patch(PLANMAP map, KANTE *anfang, ITEMLISTE *item, int flaechenzahl, int fuenfecke)
5523 {
5524 
5525 FLAECHENTYP *code;
5526 KANTE *run;
5527 int zaehler, codestelle;
5528 
5529 code=item->code;
5530     for (codestelle=0, zaehler=1, run=anfang; run != nil; zaehler++ )
5531       {
5532 	if ((codestelle<fuenfecke) && (code[codestelle]==zaehler))
5533           { add_polygon_invers(5, map, run, &run); codestelle++; }
5534         else add_polygon_invers(6, map, run, &run);
5535       }
5536         if (zaehler != flaechenzahl)
5537 	  { fprintf(stderr,"Insert_patch: Could not insert enough faces: ");
5538 	    fprintf(stderr,"%d instead of %d\n (insert_patch)\n",zaehler,flaechenzahl);
5539 	    exit(92); }
5540 }
5541 
5542 
5543 /**********************DELETE_PATCH**************************************/
5544 
delete_patch(PLANMAP map,KANTE * anfang,KNOTENTYP * adresse)5545 void delete_patch(PLANMAP map, KANTE *anfang, KNOTENTYP *adresse)
5546 {
5547 int sqlaenge, randlaenge, i, j, knotenverlust;
5548 KANTE *run;
5549 
5550 sqlaenge=6-adresse[0];
5551 for (i=2, randlaenge=sqlaenge; i<= 1+sqlaenge; i++) randlaenge+=(2*adresse[i]);
5552 
5553 knotenverlust=(3*adresse[0])+randlaenge;
5554 knotenverlust= knotenverlust/2;  /* diese konstruktion nur Sicherheitshalber, damit kein
5555 				    Compiler die Ordnung "erst 3a[0]+r" aufloest */
5556 knotenverlust= knotenverlust+(2*adresse[1])+1-randlaenge;
5557 /*alles nur Euler-Formel*/
5558 
5559 map[0][0].name = map[0][0].name - knotenverlust;
5560 
5561 for (i=1+sqlaenge; adresse[i]==0; i--);
5562 for ( run=anfang ; i>1 ; i--)
5563   { if (adresse[i])
5564       { for (j=0; j < adresse[i]; j++)
5565 	  {
5566 	    run->name=aussen; run->invers=nil; run = run->next->invers->next->invers->next; }
5567 	run=run->invers->next;
5568       }
5569     else { run=run->invers->next; }
5570   }
5571 }
5572 
5573 
5574 
5575 /*********************BRILLE****************************************/
5576 
5577 /* Der zweite Fall der Fullerenkonstruktion: Fullerene mit Brille */
5578 /*
5579 
5580                           | l2 |
5581                  _________________________
5582         	/       |         |       \
5583                |   l3   |         |   l1   |
5584                 \______/           \______/
5585 
5586 
5587                  _______ 	 oder
5588                /        \
5589               |          |
5590                \_________|_____________________
5591                                      |         \
5592                                      |          |
5593                                       \________/
5594 
5595 Der Unterschied ist, ob das Mittelstueck l2 gerade oder ungerade viele
5596 Kanten enthaelt --- kombinatorisch ist es einfach ein Graph mit 2
5597 Knoten, die durch eine Kante verbunden sind und jeder hat eine
5598 Schleife (eine "Hantel").
5599 
5600 Die Brille wird als Pfad mit Anfang und Ende interpretiert mit l1 >=
5601 l3, d.h. erste Schleife nicht kleiner als zweite und Orientierung um
5602 ungerade Knoten vorher->aussen->nachher
5603 
5604 Die Markierungen sind die nach dieser Ordnung vom kleinsten Knoten
5605 ausgehenden Kanten mit folgender kanonischer Sequenz. Sie sind an der
5606 letzten Innenkante des ersten einzufuegenden Polygons.
5607 
5608 
5609 Der gesamtcode: (pfadlaenge,2,l1,l3,code1[],code2[],code3[])
5610 gesamtcodelaenge:16
5611 
5612  */
5613 
5614 
5615 
brille(int min_sechsecke,int max_sechsecke)5616 void brille(int min_sechsecke, int max_sechsecke)
5617 {
5618 int knotenzahl, pfadlaenge, s1ps2;
5619 int laenge_1, laenge_3;
5620 KNOTENTYP adresse_1[6], adresse_2[6],adresse_3[6];
5621 int sixgons_1, sixgons_2, sixgons_3; /* zur besseren lesbarkeit -- es koennte auch immer adresse_i[1]
5622 					benutzt werden */
5623 KANTE *anfang_1, *anfang_2, *anfang_3; /* eine kanonische Kante auf dem Rand zum Anfangen */
5624 ITEMLISTE *item_1, *item_2, *item_3;
5625 BOOL gebaut_1, gebaut_2, ipr_fault_item2;
5626 PLANMAP map;
5627 KNOTENTYP code[20];
5628 int j, czmerke_1, czmerke_2, czmerke_3;
5629 int modulozaehler;
5630 
5631 modulozaehler=rest;
5632 
5633 knotenzahl= 20 + 2*max_sechsecke;
5634 
5635 init_map(map);
5636 
5637 code[1]=2;
5638 
5639 for (pfadlaenge=2*minbrillenglas+1; pfadlaenge <= knotenzahl+1; pfadlaenge++)
5640   { /* EINZIGE Konvention: laenge_1 >= laenge_3 --- dann darf keine konvention
5641        fuer die 6-Ecke mehr erfolgen ! */
5642     code[0]=pfadlaenge;
5643     for (laenge_1=minbrillenglas; (laenge_1 <= maxbrillenglas) &&
5644 	                            (laenge_1 < pfadlaenge-minbrillenglas); laenge_1++)
5645       if (brillenglasmark[laenge_1])
5646       { if ((laenge_1 % 2)==0)
5647 	  { adresse_1[0]=4; adresse_1[2]=(laenge_1-2)/2; adresse_1[3]=0; }
5648         else { adresse_1[0]=5; adresse_1[2]=(laenge_1-1)/2; }
5649 	code[2]=laenge_1;
5650 	for (sixgons_1=0; sixgons_1 <= max_sechsecke; sixgons_1++)
5651 	  /* auch hier kann man besser abschaetzen */
5652 	  { adresse_1[1]=sixgons_1;
5653 	    for (item_1=suche_item(adresse_1); item_1 != nil; item_1=item_1->next_item)
5654 	      {
5655 		czmerke_1=4+adresse_1[0];
5656 		for (j=4; j<czmerke_1; j++) code[j]=item_1->code[j-4];
5657  		for (laenge_3=minbrillenglas;
5658 		     (laenge_3 <= laenge_1) && (laenge_1+laenge_3 < pfadlaenge); laenge_3++)
5659 		 if (brillenglasmark[laenge_3])
5660  		 {
5661 		   modulozaehler++;
5662 		   if (modulozaehler==mod) modulozaehler=0;
5663 		   if (!mod || (modulozaehler==0))
5664 		     {
5665 		       code[3]=laenge_3;
5666 		       berechne_brillenadressen(laenge_1,pfadlaenge,laenge_3,adresse_2,adresse_3);
5667 		       gebaut_1=0; /* Man koennte auch patch_1 immer in der aeusseren
5668 				      Schleife bauen und dann die Brille verschieden fortsetzen, aber erst Brille bauen
5669 				      und dann die patches einkleben erscheint mir sympathischer und weniger fehleranfaellig --
5670 				      wenn auch von der Komplexitaet her ein wenig schlechter */
5671 		       for (sixgons_2=0; sixgons_2 <= max_sechsecke-sixgons_1; sixgons_2++)
5672 			 { s1ps2=sixgons_1 + sixgons_2;
5673 			   adresse_2[1]=sixgons_2;
5674 			   for (sixgons_3=max_sechsecke-s1ps2; (sixgons_3>=min_sechsecke-s1ps2) && (sixgons_3>=0);
5675 				sixgons_3--)
5676 			     {
5677 			       adresse_3[1]=sixgons_3;
5678 			       for (item_2=suche_item(adresse_2); item_2 != nil; item_2=item_2->next_item)
5679 				 { is_ipr=1; ipr_fault_item2=0;
5680 				   gebaut_2=0;
5681 				   czmerke_2=czmerke_1+adresse_2[0];
5682 				   for (j=czmerke_1; j<czmerke_2; j++) code[j]=item_2->code[j-czmerke_1];
5683 				   for (item_3=suche_item(adresse_3); (item_3 != nil) && (!ipr_fault_item2);
5684 					item_3=item_3->next_item)
5685 				     { czmerke_3=czmerke_2+adresse_3[0];
5686 				       for (j=czmerke_2; j<czmerke_3; j++) code[j]=item_3->code[j-czmerke_2];
5687 				       if (gebaut_1==0) {
5688 					 anzahl_5ek=0;
5689 					 baue_brille(pfadlaenge,laenge_1,laenge_3,map, &anfang_1, &anfang_2,&anfang_3);
5690 					 insert_patch(map,anfang_1,item_1,sixgons_1+adresse_1[0],adresse_1[0]);
5691 					 gebaut_1=1;
5692 				       }
5693 				       if (gebaut_2==0)
5694 					 { anzahl_5ek=5*adresse_1[0];
5695 					   insert_patch(map,anfang_2,item_2,sixgons_2+adresse_2[0],adresse_2[0]);
5696 					   gebaut_2=1;
5697 					   if (is_ipr==0) ipr_fault_item2=1;}
5698 				       anzahl_5ek=5*(12-adresse_3[0]);
5699 				       if (is_ipr)
5700 					 { insert_patch(map,anfang_3,item_3,sixgons_3+adresse_3[0],adresse_3[0]);
5701 					   if (is_ipr) teste_und_schreibe(map,code); else is_ipr=1;
5702 					   delete_patch(map,anfang_3,adresse_3); }
5703 				     } /* ende for ueber item_3 */
5704 				   if (gebaut_2) delete_patch(map,anfang_2,adresse_2);
5705 				 } /* ende for ueber item_2 */
5706 			     } /* ende for ueber sixgons_3 */
5707 			 } /* ende for ueber sixgons_2 */
5708 		       map[0][0].name=0; /* entspricht loeschen von map */
5709 		     }
5710  		 } /* ende for ueber laenge_3 */
5711 	      } /* ende for ueber item_1 */
5712 	  } /* ende for ueber sixgons_1 */
5713       } /* ende for ueber laenge_1 */
5714   } /* ende for ueber pfadlaenge */
5715  } /* ende funktion */
5716 
5717 
5718 /*********************BERECHNE_ADRESSE3********************************/
5719 
berechne_adresse3(int l1,int l3,KNOTENTYP adresse[])5720 void berechne_adresse3(int l1, int l3, KNOTENTYP adresse[])
5721 {
5722 int sl1, sl3;
5723 
5724 if (l1%2) { sl1=(l1-1)/2;
5725 	    if (l3%2) { sl3=(l3-1)/2; adresse[0]=4;
5726 			if (sl3>sl1) { adresse[2]=sl3; adresse[3]=sl1; }
5727 			else { adresse[2]=sl1; adresse[3]=sl3; }
5728 		      } else /* d.h. l3 gerade */
5729 			{ sl3=(l3-2)/2;
5730 			  adresse[0]=3;
5731 			  if (sl3>sl1) { adresse[2]=sl3; adresse[3]=0; adresse[4]=sl1; }
5732 			  else { adresse[2]=sl1;
5733 				 adresse[3]=sl3; adresse[4]=0; }
5734 			}
5735 	  }
5736 
5737 else { sl1=(l1-2)/2;
5738        if (l3%2) { sl3=(l3-1)/2;
5739 		   adresse[0]=3;
5740 		   if (sl3>sl1) { adresse[2]=sl3; adresse[3]=0; adresse[4]=sl1; }
5741 		   else { adresse[2]=sl1; adresse[3]=sl3; adresse[4]=0; }
5742 		 } else /*d.h. l3 gerade */
5743 		   { sl3=(l3-2)/2;
5744 		     adresse[0]=2;
5745 		     if (sl3>sl1) { adresse[2]=sl3; adresse[3]=0; adresse[4]=sl1; adresse[5]=0; }
5746 		     else { adresse[2]=sl1; adresse[3]=0; adresse[4]=sl3; adresse[5]=0; }
5747 		   }
5748      }
5749  }
5750 
5751 
5752 /*********************BAUE_SANDWICH***********************************/
5753 
baue_sandwich(PLANMAP map,int laenge_1,int laenge_2,int laenge_3,KANTE ** anfang_1,KANTE ** anfang_2,KANTE ** anfang_3)5754 void baue_sandwich(PLANMAP map, int laenge_1, int laenge_2, int laenge_3,
5755 		   KANTE **anfang_1, KANTE **anfang_2, KANTE **anfang_3)
5756 
5757 { int stelle_2, knotenzahl, i, stelle, pfadlaenge;
5758 KANTE *aussenzeiger, *letzte_Kante, *startkante_1, *startkante_2,*startkante_3;
5759 
5760 pfadlaenge=laenge_1+laenge_2+laenge_3; knotenzahl=pfadlaenge-1;
5761 
5762 
5763 map[1][1].name=2; map[1][1].invers=map[2]+0;
5764 for (i=1; i<=knotenzahl; i++)
5765   { map[i][0].name=i-1; map[i][0].invers=map[i-1]+1;
5766     map[i][1].name=aussen; map[i][1].invers=nil;
5767     map[i][2].name=i+1; map[i][2].invers=map[i+1]+0;
5768     i++;
5769     if (i<=knotenzahl) {
5770       map[i][0].name=i-1; map[i][0].invers=map[i-1]+2;
5771       map[i][2].name=aussen; map[i][2].invers=nil;
5772       map[i][1].name=i+1; map[i][1].invers=map[i+1]+0;
5773     }
5774   }
5775 
5776 /* Knoten 1 und Knoten knotenzahl haben jetzt falsche vorher bzw
5777    nachher werte, sie muessen jetzt mit dem Sandwich verklebt werden */
5778 
5779 stelle=laenge_1+laenge_2;
5780 if ((stelle%2)==0) aussenzeiger=map[stelle]+2; else aussenzeiger=map[stelle]+1;
5781 
5782 aussenzeiger->name=1; aussenzeiger->invers=map[1]+0;
5783 map[1][0].name=stelle; map[1][0].invers=aussenzeiger;
5784 
5785 if ((laenge_1%2)==0) aussenzeiger=map[laenge_1]+2;
5786 else aussenzeiger=map[laenge_1]+1;
5787 if ((knotenzahl%2)==0) letzte_Kante=map[knotenzahl]+1; else letzte_Kante=map[knotenzahl]+2;
5788 
5789 letzte_Kante->name=laenge_1; letzte_Kante->invers=aussenzeiger;
5790 aussenzeiger->name=knotenzahl; aussenzeiger->invers=letzte_Kante;
5791 
5792 map[0][0].name=knotenzahl;
5793 
5794 /* Jetzt die anfangskanten belegen: */
5795 
5796 if (laenge_2==1) stelle_2= stelle+1; else stelle_2=stelle-1;
5797 if (stelle %2) { startkante_1=map[1]+1; startkante_2=map[stelle_2]+2; startkante_3=map[2]+2; }
5798 /* dann zeigt die Aussenkante von Knoten 1 ins innere von zykel_1 */
5799 else { startkante_1=map[2]+2; startkante_2=map[stelle_2]+1; startkante_3=map[1]+1; }
5800 *anfang_1=suchestart(startkante_1);
5801 *anfang_2=suchestart(startkante_2);
5802 *anfang_3=suchestart(startkante_3);
5803 
5804 } /* ende funktion */
5805 
5806 
5807 
5808 
5809 
5810 
5811 
5812 /************************SANDWICH***************************************/
5813 
5814 /* Sandwich ist der 3. Fall :
5815 
5816                           l1
5817 		   --------------------
5818 		 /                      \
5819 		/      l2 oder l3        \
5820        	       O--------------------------O
5821 	        \                        /
5822 		 \     l2 oder l3       /
5823  		   --------------------
5824 
5825 d.h.:
5826 
5827 		        l1
5828 		  -----------------
5829  		/                   \
5830 	       O                     |
5831 	         ______l2___________/
5832 		/
5833 	       |                   ^
5834 	       |                   |
5835 	        \______l3_________/
5836 
5837 oder das Spiegelbild:
5838 
5839 		        l1
5840 		  -----------------
5841 	        /                   \
5842 	       O                     |
5843 	          ______l3_________> |
5844 		 /                   |
5845 		|                    |
5846 		|                    |
5847 		 \______l2__________/
5848 
5849 
5850  l2 muss immer ungerade sein !
5851 
5852 Konvention: Die Orientierung um Knoten 1 und damit alle ungeraden
5853 Knoten auf dem Pfad ist vorher->aussen->nachher und desweiteren:
5854 l1 >= l3
5855 
5856 Der gesamtcode: (pfadlaenge,3,l1,l2,code1[],code2[],code3[])
5857 gesamtcodelaenge:16
5858 
5859 
5860 */
5861 
5862 
5863 
sandwich(int min_sechsecke,int max_sechsecke)5864 void sandwich (int min_sechsecke, int max_sechsecke)
5865 
5866 {
5867 int knotenzahl, maxpfadlaenge, s1ps2;
5868 int laenge_1, laenge_2, laenge_3;
5869 KNOTENTYP adresse_1[6], adresse_2[6], adresse_3[6];
5870 int sixgons_1, sixgons_2, sixgons_3; /* zur besseren lesbarkeit -- es koennte auch
5871 					immer adresse_i[1] benutzt werden. s_1 ist
5872 					die Anzahl der 6-Ecke zwischen l1 und l2. s_2 zwischen
5873 					l2 und l3 und s_3..... analog fuer adresse und item */
5874 KANTE *anfang_1, *anfang_2, *anfang_3; /* eine kanonische Kante auf dem Rand zum Anfangen */
5875 ITEMLISTE *item_1, *item_2, *item_3;
5876 int randl_p1, randl_p2, randl_p3;
5877 BOOL gebaut_1, gebaut_2, ipr_fault_item2;
5878 PLANMAP map;
5879 KNOTENTYP code[20];
5880 int j, czmerke_1, czmerke_2, czmerke_3;
5881 int modulozaehler;
5882 
5883 modulozaehler=rest;
5884 /* l1--l2  und  l2--l3  bilden je ein brillenglas */
5885 
5886 
5887 knotenzahl= 20 + 2*max_sechsecke; maxpfadlaenge=knotenzahl+1;
5888 init_map(map);
5889 code[1]=3;
5890 
5891 for (laenge_1=(min_2_3_4 /2); laenge_1 <= maxpfadlaenge-minbrillenglas; laenge_1++)
5892   {
5893   code[2]=laenge_1;
5894   for (laenge_2=1; laenge_2 <= maxpfadlaenge-min_2_3_4; laenge_2 += 2) /* muss immer ungerade sein ! */
5895   { randl_p1=laenge_1+laenge_2;
5896     if (brillenglasmark[randl_p1])
5897     { /* l1+l2 umrahmt patch 1 */
5898        code[3]=laenge_2;
5899  	if (randl_p1%2) { adresse_1[0]=5; adresse_1[2]=(randl_p1-1)/2; }
5900  	 else { adresse_1[0]=4; adresse_1[2]=(randl_p1-2)/2; adresse_1[3]=0; }
5901  	for (sixgons_1=0; sixgons_1 <= max_sechsecke; sixgons_1++)
5902  	 {
5903 	   adresse_1[1]=sixgons_1;
5904 	   for (item_1=suche_item(adresse_1); item_1 != nil; item_1=item_1->next_item)
5905 	     {
5906 	       modulozaehler++;
5907 	       if (modulozaehler==mod) modulozaehler=0;
5908 	       if (!mod || (modulozaehler==0))
5909 		 {
5910 		   czmerke_1=4+adresse_1[0];
5911 		   for (j=4; j<czmerke_1; j++) code[j]=item_1->code[j-4];
5912 		   for (laenge_3=1; ((randl_p1 + laenge_3) <= maxpfadlaenge) && (laenge_1>= laenge_3); laenge_3++)
5913 		     { randl_p2=laenge_2+laenge_3;
5914 		       randl_p3=laenge_3+laenge_1;
5915 		       if (brillenglasmark[randl_p2] && zwei_3_4_mark[randl_p3])
5916 			 { code[0]=laenge_3 + randl_p1;
5917 			   gebaut_1=0;
5918 			   if (randl_p2%2) { adresse_2[0]=5; adresse_2[2]=(randl_p2-1)/2; }
5919 			   else { adresse_2[0]=4; adresse_2[2]=(randl_p2-2)/2; adresse_2[3]=0; }
5920 			   /* fuer den patch zwischen l1 und l3 ist die Lage leider komplizierter */
5921 			   berechne_adresse3(laenge_1,laenge_3,adresse_3);
5922 			   for (sixgons_2=0; sixgons_2 <= max_sechsecke-sixgons_1; sixgons_2++)
5923 			     { s1ps2=sixgons_1 + sixgons_2;
5924 			       adresse_2[1]=sixgons_2;
5925 			       for (sixgons_3=max_sechsecke-s1ps2; (sixgons_3>=min_sechsecke-s1ps2) && (sixgons_3>=0);
5926 				    sixgons_3--)
5927 				 {
5928 				   adresse_3[1]=sixgons_3;
5929 				   for (item_2=suche_item(adresse_2); item_2 != nil; item_2=item_2->next_item)
5930 				     { is_ipr=1; ipr_fault_item2=0;
5931 				       gebaut_2=0;
5932 				       czmerke_2=czmerke_1+adresse_2[0];
5933 				       for (j=czmerke_1; j<czmerke_2; j++) code[j]=item_2->code[j-czmerke_1];
5934 				       for (item_3=suche_item(adresse_3); (item_3 != nil) && (!ipr_fault_item2);
5935 					    item_3=item_3->next_item)
5936 					 {
5937 					   czmerke_3=czmerke_2+adresse_3[0];
5938 					   for (j=czmerke_2; j<czmerke_3; j++) code[j]=item_3->code[j-czmerke_2];
5939 					   /* Der Kern */
5940 					   if (gebaut_1==0)
5941 					     { anzahl_5ek=0;
5942 					       baue_sandwich(map,laenge_1,laenge_2,laenge_3,&anfang_1,&anfang_2,&anfang_3);
5943 					       gebaut_1=1;
5944 					       insert_patch(map,anfang_1,item_1,sixgons_1+adresse_1[0],adresse_1[0]); }
5945 					   if (gebaut_2==0)
5946 					     { anzahl_5ek= 5*adresse_1[0];
5947 					       insert_patch(map,anfang_2,item_2,sixgons_2+adresse_2[0],adresse_2[0]);
5948 					       gebaut_2=1;
5949 					       if (is_ipr==0) ipr_fault_item2=1; }
5950 					   anzahl_5ek=5*(12-adresse_3[0]);
5951 					   if (is_ipr)
5952 					     { insert_patch(map,anfang_3,item_3,sixgons_3+adresse_3[0],adresse_3[0]);
5953 					       if (is_ipr) teste_und_schreibe(map,code); else is_ipr=1;
5954 					       delete_patch(map,anfang_3,adresse_3); }
5955 					   /* Ende Kern */
5956 
5957 
5958 					 } /* ende for ueber item_3 */
5959 				       if (gebaut_2) delete_patch(map,anfang_2,adresse_2);
5960 				     } /*ende for ueber item_2 */
5961 				 } /* ende for ueber sixgons_3 */
5962 			     } /* ende for ueber sixgons_2 */
5963 			   map[0][0].name=0; /* entspricht loeschen */
5964 			 } /* ende if randl_p2 und randl_p3 OK */
5965 		     } /* ende for ueber laenge_3 */
5966 		 }
5967 	     } /* ende for ueber item_1 */
5968 	 } /* ende for ueber sixgons_1 */
5969      } /* ende if randl_p1 OK */
5970   } /* ende for ueber laenge_2; */
5971 } /* ende for ueber laenge_1 */
5972 
5973 } /* ende funktion */
5974 
5975 
5976 /**************************MAIN*********************************************/
5977 
main(argc,argv)5978 int main(argc,argv)
5979 
5980 int argc; char *argv[];
5981 
5982 { int sechsecke, i, puffer, do_case;
5983   char strpuf[filenamenlaenge], strpuf2[filenamenlaenge], strdummy[filenamenlaenge];
5984   struct stat buf;
5985   char name[4];     /* TH - fuer die Option "symm" */
5986   FLAECHENTYP dummycode[12]={UCHAR_MAX,UCHAR_MAX,UCHAR_MAX,0,0,0,0,0,0,0,0,0};
5987   FLAECHENTYP *dummypointer;
5988 
5989 #ifndef NOTIMES
5990   clock_t savetime=0, buffertime;
5991   struct tms TMS;
5992 #endif //NOTIMES
5993 
5994   int separate_logfile = 1;
5995 
5996 #ifdef __GNUC__
5997 #ifdef __alpha__
5998 fprintf(stderr,"With gcc on alphas some errors might occur if you use -O3 or more.\n");
5999 fprintf(stderr,"This is a bug of the compiler.\n");
6000 fprintf(stderr,"Please use cc on alphas -- the result will be a faster program anyway.\n");
6001 exit(0);
6002 #endif
6003 #endif
6004 
6005 
6006 for (i=1;i<=N;i++) graphenzahl[i]=non_iso_graphenzahl[i]=0;
6007 
6008 do_brille=do_sandwich=do_bauchbinde=1;
6009 
6010 do_case=0;
6011 
6012 
6013 symmstring[0] = 0;       /* TH - Filekennung loeschen */
6014 
6015 if (argc<2) exit(93);
6016 
6017 
6018 knotenzahl=atoi(argv[1]);
6019 if ((knotenzahl%2) || (knotenzahl<20)) { fprintf(stderr,"Impossible vertex number. \n"); exit(94); }
6020 
6021 min_sechsecke=max_sechsecke=sechsecke=(knotenzahl-20)/2;
6022 
6023 
6024 if (knotenzahl >= leer) { fprintf(stderr,"Number of vertices too large for the data-types used. \n"); exit(95); }
6025 if (aussen >= leer) { fprintf(stderr,"Definition of \"S\" too large for the data-types used. \n"); exit(96); }
6026 if (S+12 > FL_MAX) { fprintf(stderr,"Definition of \"S\" too large for the data-types used for FLAECHENTYP. \n");
6027 		     exit(97); }
6028 
6029 if (sechsecke > S) { fprintf(stderr,"Fix the constant \"S\" to at least %d\n",sechsecke); exit(98); }
6030 
6031 codenumber=listenlaenge=0;
6032 
6033 for (i=2; i<argc; i++)
6034     switch (argv[i][0])
6035       {
6036       case 'i': { if (strcmp(argv[i],"ipr")==0) IPR=1;
6037 		    else { fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(99); }
6038 		  break; }
6039 
6040       case 'h': { if (strcmp(argv[i],"hexspi")==0) hexspi=1;
6041 		    else { fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(100); }
6042 		  break; }
6043 
6044       case 's': { if (strcmp(argv[i],"start")==0)
6045 		    { i++; puffer=atoi(argv[i]);
6046 		      if ((puffer%2) || (puffer<20))
6047 			{ fprintf(stderr,"Impossible vertex number to start. \n"); exit(101); }
6048 		      min_sechsecke=(puffer-20)/2; }
6049                     else
6050 		      if (strcmp(argv[i],"stdout")==0) to_stdout=1;
6051                     else
6052 		      if (strcmp(argv[i],"spistat")==0) spistat=1;
6053                     else
6054 		      if (strcmp(argv[i],"spiralcheck")==0) spiralcheck=1;
6055                     else
6056                       if (strcmp(argv[i],"symstat")==0) symstat=1;   /* TH */
6057                     else
6058                       if (strcmp(argv[i],"symm")==0) {               /* TH */
6059                         int j=28, ii;
6060                         BOOL gefunden = False;
6061  			symstat=1;                /* immer -- kostet ja nichts extra */
6062                         i++;
6063                         if (i<argc) {
6064                           while (j>0 && !gefunden) {
6065                             for (ii=0; ii<=3; ii++) {
6066                               name[ii] = (symm_name[j][ii]==' ') ? '\0' : symm_name[j][ii];
6067                             }
6068                             if (strcmp(argv[i],name)==0) {      /* Symmetrie j gefunden */
6069                               gefunden = True;
6070                               if (!vergleiche_symm(j))   /* Symmetrie noch nicht in Liste */
6071                                 {symm[symm_len++] = j;
6072                                  strcat(symmstring,(char *)"_"); strcat(symmstring,name);}
6073                             }
6074                             j--;
6075                           }
6076                         }
6077                         if (!gefunden)
6078                            {fprintf(stderr,"Unknown symmetry identifier. \n"); exit(102);}
6079                         break;
6080                       }  /* if */
6081 		    else { fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(103); }
6082 		  break; }
6083       case 'c': { if (strcmp(argv[i],"code")==0)
6084 		    { i++; codenumber=atoi(argv[i]); }
6085 		  else
6086 		    if (strcmp(argv[i],"case")==0)
6087 		    { i++; do_case=atoi(argv[i]);
6088 		      switch (do_case)
6089 			{ case 1: { do_brille=do_sandwich=0; do_bauchbinde=1; break; }
6090 			  case 2: { do_brille=1; do_sandwich=do_bauchbinde=0; break; }
6091 			  case 3: { do_brille=do_bauchbinde=0; do_sandwich=1; break; }
6092 			 default: { fprintf(stderr,"No such case !\n"); exit(104); }
6093 			}
6094 		      }
6095 		    else { fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(105); }
6096 		  break; }
6097       case 'p': { if (strcmp(argv[i],"pid")==0) {fprintf(stdout,"%d\n",getpid());  fflush(stdout);}
6098                   else {fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(119);}
6099                   break;
6100                 }
6101       case 'q': { if (strcmp(argv[i],"quiet")==0) quiet=1;
6102                   else {fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(120);}
6103                   break;
6104                 }
6105       case 'l': { if (strcmp(argv[i],"list")==0)
6106 		    { i++; listenlaenge=atoi(argv[i]); }
6107 		  else if (strcmp(argv[i],"logerr")==0) {
6108 		    logfile = stderr;
6109 		    separate_logfile = 0;
6110 		  }
6111 		  else { fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(106); }
6112 		  break; }
6113 
6114       case 'm': { if (strcmp(argv[i],"mod")==0)
6115 		    { i++; rest=atoi(argv[i]); i++; mod=atoi(argv[i]);
6116 		      if ((mod<=0) || (rest<0) || (rest>=mod))
6117 		        { fprintf(stderr,"Bad values for option mod \n"); exit(0); }
6118 		    }
6119 		    else { fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(106); }
6120 		  break; }
6121 
6122 
6123 
6124       default: { fprintf(stderr,"Nonidentified option: %s \n",argv[i]); exit(107); }
6125       }
6126 
6127 
6128 switch (codenumber)
6129   {
6130   case 0: break;
6131   case 1:
6132   case 8: { for (i=20+(2*min_sechsecke); i<=knotenzahl; i+=2)
6133 	      { if (IPR) sprintf(strpuf,"Full_codes_%d_ipr",i);
6134 		  else sprintf(strpuf,"Full_codes_%d",i);
6135 		if (do_case) { sprintf(strpuf2,"_c%d",do_case); strcat(strpuf,strpuf2); }
6136 		if (mod) { sprintf(strpuf2,"_m_%d_%d",rest,mod); strcat(strpuf,strpuf2); }
6137                 if (symm_len>0)    {strcat(strpuf,symmstring);}
6138 		if (to_stdout) fil[i]=stdout; else fil[i]=fopen(strpuf,"wb");
6139 		if (!to_stdout) write_header_fil[i]=1;
6140 	        if (fil[i]==nil) { fprintf(stderr,"Can not open file %s. \n",strpuf); exit(109);}
6141 	      }
6142 	    break; }
6143   case 2: { for (i=20+(2*min_sechsecke); i<=knotenzahl; i+=2)
6144 	      { if (IPR) sprintf(strpuf,"Spiral_codes_%d_ipr",i);
6145 		  else sprintf(strpuf,"Spiral_codes_%d",i);
6146 		if (do_case) { sprintf(strpuf2,"_c%d",do_case); strcat(strpuf,strpuf2); }
6147 		if (mod) { sprintf(strpuf2,"_m_%d_%d",rest,mod); strcat(strpuf,strpuf2); }
6148                 if (symm_len>0)    {strcat(strpuf,symmstring);}
6149 		if (to_stdout) fil[i]=stdout; else fil[i]=fopen(strpuf,"wb");
6150 		if (!to_stdout) write_header_fil[i]=1;
6151 	        if (fil[i]==nil) { fprintf(stderr,"Can not open file %s. \n",strpuf); exit(110);}
6152 	      }
6153 	    spiralcheck=1;
6154 	    last_code[0]=FL_MAX;
6155 	    break; }
6156   case 3: { spiralcheck=1;
6157             if (listenlaenge==0) listenlaenge=2000;
6158             for (i=20+(2*min_sechsecke); i<=knotenzahl; i+=2)
6159 	      { (codeliste[i].code)[0]=0;
6160 		if (IPR) sprintf(strpuf,"Spiral_codes_%d_ipr",i);
6161 		  else sprintf(strpuf,"Spiral_codes_%d",i);
6162 		if (do_case) { sprintf(strpuf2,"_c%d",do_case); strcat(strpuf,strpuf2); }
6163 		if (mod) { sprintf(strpuf2,"_m_%d_%d",rest,mod); strcat(strpuf,strpuf2); }
6164                 if (symm_len>0)    {strcat(strpuf,symmstring);}
6165 		if (to_stdout) fil[i]=stdout; else fil[i]=fopen(strpuf,"wb");
6166                 if (!to_stdout) write_header_fil[i]=1;
6167 	        if (fil[i]==nil) { fprintf(stderr,"Can not open file %s. \n",strpuf); exit(111);}
6168 		lastcode[i]=(FLAECHENTYP **)malloc(sizeof(FLAECHENTYP *));
6169 		if (lastcode[i] ==nil) { fprintf(stderr,"Can not get memory for lastcode. \n"); exit(112); }
6170 		(*(lastcode[i]))=(FLAECHENTYP *)malloc(sizeof(FLAECHENTYP)*12);
6171 		(*(lastcode[i]))[0]=FL_MAX;
6172 	      }
6173 	    break; }
6174   case 4: spiralcheck=1; break; /* Nur nicht-spiral-codes schreiben */
6175   case 5: { spiralcheck=1;
6176             for (i=20+(2*min_sechsecke); i<=knotenzahl; i+=2)
6177 	      { if (IPR) sprintf(strpuf,"Full_codes_%d_ipr",i);
6178 		  else sprintf(strpuf,"Full_codes_%d",i);
6179 		if (do_case) { sprintf(strpuf2,"_c%d",do_case); strcat(strpuf,strpuf2); }
6180 		if (mod) { sprintf(strpuf2,"_m_%d_%d",rest,mod); strcat(strpuf,strpuf2); }
6181                 if (symm_len>0)    {strcat(strpuf,symmstring);}
6182 		if (to_stdout) fil[i]=stdout; else fil[i]=fopen(strpuf,"wb");
6183 	        if (fil[i]==nil) { fprintf(stderr,"Can not open file %s. \n",strpuf); exit(113);}
6184                 if (!to_stdout) write_header_fil[i]=1;
6185 	      }
6186 	    break; }
6187 
6188   case 6: { break; }
6189 
6190   case 7: { break; }
6191 
6192   default: { fprintf(stderr,"No coding number %d. \n", codenumber); exit(114); }
6193   }
6194 
6195 if (hexspi && !spiralcheck)
6196   { fprintf(stderr,"The option \"hexspi\" must be used together with some code involving spiral checking \n");
6197     exit(115); }
6198 
6199 if (spistat && (min_sechsecke != max_sechsecke))
6200   { fprintf(stderr,"The option \"spistat\" must be used only for fullerenes of ONE size \n");
6201     exit(116); }
6202 
6203 if (spistat) for (i=0; i<=12*max_sechsecke+120; i++) spiralnumbers[i]=0;
6204 
6205 
6206 if (IPR)
6207   {  if (min_sechsecke==max_sechsecke) sprintf(logfilename,"Full_gen_%d_ipr",knotenzahl);
6208     else sprintf(logfilename,"Full_gen_%d_%d_ipr",knotenzahl,(2*min_sechsecke)+20); }
6209 else
6210   {  if (min_sechsecke==max_sechsecke) sprintf(logfilename,"Full_gen_%d",knotenzahl);
6211   else sprintf(logfilename,"Full_gen_%d_%d",knotenzahl,(2*min_sechsecke)+20); }
6212 
6213   if (do_case) { sprintf(strpuf2,"_c%d",do_case); strcat(logfilename,strpuf2); }
6214   if (mod) { sprintf(strpuf2,"_m_%d_%d",rest,mod); strcat(logfilename,strpuf2); }
6215   if (spiralcheck) { sprintf(no_spiral_filename,"No_spiral_");
6216 		     strcat(no_spiral_filename,logfilename+9);
6217 		     sprintf(strdummy,"rm %s",no_spiral_filename);
6218 		     if (!stat(strdummy,&buf)) {
6219                          if(system (strdummy)==-1){
6220                              fprintf(stderr,"Could not execute system call.\n");
6221                          }
6222                      }
6223 		     sprintf(no_penta_spiral_filename,"No_pentagon_spiral_");
6224 		     strcat(no_penta_spiral_filename,logfilename+9);
6225 		     sprintf(strdummy,"rm %s",no_penta_spiral_filename);
6226 		     if (!stat(strdummy,&buf)) {
6227                          if(system (strdummy)==-1){
6228                              fprintf(stderr,"Could not execute system call.\n");
6229                          }
6230                      }
6231 		      }
6232   if (hexspi) { sprintf(no_hexa_spiral_filename,"No_hexagon_spiral_");
6233 		strcat(no_hexa_spiral_filename,logfilename+9);
6234 		sprintf(strdummy,"rm %s",no_hexa_spiral_filename);
6235 		if (!stat(strdummy,&buf)) {
6236                      if(system (strdummy)==-1){
6237                          fprintf(stderr,"Could not execute system call.\n");
6238                      }
6239                 }
6240 	      }
6241 
6242 if (!quiet)
6243   {
6244     strcat(logfilename,".log");
6245     if (separate_logfile) logfile=fopen(logfilename,"w");
6246     if (logfile==nil) { fprintf(stderr,"Can not open file %s. \n",logfilename); exit(118);}
6247     fprintf(logfile,"Minimal vertex number: %d \n",(2*min_sechsecke)+20);
6248     fprintf(logfile,"Maximal vertex number: %d \n",knotenzahl);
6249     fprintf(logfile,"Code_type: %d \n",codenumber);
6250     if (codenumber==3) fprintf(logfile,"List length: %d \n",listenlaenge);
6251     if (separate_logfile) fclose(logfile);
6252   }
6253 
6254 
6255 initialize_list();
6256 
6257 baue_patches(sechsecke);
6258 #ifndef NOTIMES
6259 times(&TMS);
6260 savetime= TMS.tms_utime;
6261 if (!quiet)
6262   { fprintf(stderr,"Time for generating the patches: %.1f seconds \n",(double)savetime/time_factor);
6263     if (separate_logfile) {
6264       logfile=fopen(logfilename,"a");
6265       fprintf(logfile,"Time for generating the patches: %.1f seconds \n",(double)savetime/time_factor);
6266       fclose(logfile);
6267     }
6268   }
6269 #endif //NOTIMES
6270 
6271 if (do_bauchbinde)
6272 {
6273 bauchbinde(min_sechsecke,max_sechsecke);
6274 #ifndef NOTIMES
6275 times(&TMS);
6276 buffertime= TMS.tms_utime;
6277 if (!quiet)
6278   { fprintf(stderr,"Time for case 1 (Jordan-Curve Petrie Path): %.1f seconds \n",(double)(buffertime-savetime)/time_factor);
6279     if (separate_logfile) {
6280       logfile=fopen(logfilename,"a");
6281       fprintf(logfile,"Time for case 1 (Jordan-Curve Petrie Path): %.1f seconds \n",(double)(buffertime-savetime)/time_factor);
6282       fclose(logfile);
6283     }
6284   }
6285 savetime=buffertime;
6286 #endif //NOTIMES
6287 }
6288 
6289 if (do_brille)
6290 {
6291 brille(min_sechsecke,max_sechsecke);
6292 #ifndef NOTIMES
6293 times(&TMS);
6294 buffertime= TMS.tms_utime;
6295 if (!quiet)
6296   { fprintf(stderr,"Time for case 2 (Dumb-bell): %.1f seconds \n",(double)(buffertime-savetime)/time_factor);
6297     if (separate_logfile) {
6298       logfile=fopen(logfilename,"a");
6299       fprintf(logfile,"Time for case 2 (Dumb-bell): %.1f seconds \n",(double)(buffertime-savetime)/time_factor);
6300       fclose(logfile);
6301     }
6302     savetime=buffertime;
6303   }
6304 #endif //NOTIMES
6305 }
6306 
6307 if (do_sandwich)
6308 {
6309 sandwich(min_sechsecke,max_sechsecke);
6310 #ifndef NOTIMES
6311 times(&TMS);
6312 buffertime= TMS.tms_utime;
6313 if (!quiet)
6314   { fprintf(stderr,"Time for case 3 (Sandwich): %.1f seconds \n\n",(double)(buffertime-savetime)/time_factor);
6315     if (separate_logfile) {
6316       logfile=fopen(logfilename,"a");
6317       fprintf(logfile,"Time for case 3 (Sandwich): %.1f seconds \n\n",(double)(buffertime-savetime)/time_factor);
6318       fclose(logfile);
6319     }
6320   }
6321 #endif //NOTIMES
6322 }
6323 
6324 if (codenumber==3)
6325   for (i=20+(2*min_sechsecke); i<=knotenzahl; i++) { dummypointer=dummycode; ausgabe(codeliste+i,i,&dummypointer); }
6326 
6327 
6328 if (!quiet)
6329  {
6330    fprintf(stderr,"MAPLIST: number of patches: %d\n",mapliste.total_maps);
6331    fprintf(stderr,"BBLIST: number of items in list: %d  number of patches: %d\n\n",bbliste.total_items,bbliste.total_maps);
6332    for (i=20+(2*min_sechsecke); i<=20+(2*max_sechsecke); i+=2)
6333      fprintf(stderr,"Generated %lld maps on %d vertices -- reduced to %lld non-isomorphic maps. \n",non_iso_graphenzahl[i],i,graphenzahl[i]);
6334    if (spistat) for (i=0; i<=12*max_sechsecke+120; i++)
6335      if (spiralnumbers[i]) fprintf(stderr,"Fullerenes with %d spirals: %d \n",i,spiralnumbers[i]);
6336    if (spiralcheck) fprintf(stderr,"Graphs without a spiral starting at a pentagon: %d \n",no_penta_spiral);
6337    if (hexspi) fprintf(stderr,"Graphs without a spiral starting at a hexagon: %d \n",no_hexa_spiral);
6338    if (symstat) schreibe_symmetriestatistik();
6339 #ifndef NOTIMES
6340   fprintf(stderr,"\nTotal generation time: %.1f seconds \n",(double)buffertime/time_factor);
6341 #endif //NOTIMES
6342    fprintf(stderr,"end of program\n");
6343 
6344    if (separate_logfile) {
6345      logfile=fopen(logfilename,"a");
6346      fprintf(logfile,"MAPLIST: number of patches: %d\n",mapliste.total_maps);
6347      fprintf(logfile,"BBLIST: number of items in list: %d  number of patches: %d\n\n",bbliste.total_items,bbliste.total_maps);
6348      for (i=20+(2*min_sechsecke); i<=20+(2*max_sechsecke); i+=2)
6349        fprintf(logfile,"Generated %lld maps on %d vertices -- reduced to %lld non-isomorphic maps. \n",non_iso_graphenzahl[i],i,graphenzahl[i]);
6350      if (spistat) for (i=0; i<=12*max_sechsecke+120; i++)
6351        if (spiralnumbers[i]) fprintf(logfile,"Fullerenes with %d spirals: %d \n",i,spiralnumbers[i]);
6352      if (spiralcheck) fprintf(logfile,"Graphs without a spiral starting at a pentagon: %d \n",no_penta_spiral);
6353      if (hexspi) fprintf(logfile,"Graphs without a spiral starting at a hexagon: %d \n",no_hexa_spiral);
6354      if (symstat) {    /* schreibe Symmetriestatistik */
6355        int j=0;
6356        fprintf(logfile,"Symmetries:\n");
6357        for (i=1; i<=28; i++) {
6358 	 if (symm_anz[i]>0) {
6359 	   fprintf(logfile,"  %s: %10d ",symm_name[i],symm_anz[i]);
6360 	   j++;
6361 	   if (j%4==0) {fprintf(logfile,"\n");}
6362 	 }
6363        }
6364        if (j%4) {fprintf(logfile,"\n");}
6365      }
6366 #ifndef NOTIMES
6367      fprintf(logfile,"\nTotal generation time: %.1f seconds \n",(double)buffertime/time_factor);
6368 #endif //NOTIMES
6369      fprintf(logfile,"end of program\n");
6370    }
6371  }
6372 
6373 return(0);
6374 }
6375 
6376