ga.c - brcon2024-hackathons - Bitreichcon 2024 Hackathons
(HTM) git clone git://bitreich.org/brcon2024-hackathons git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/brcon2024-hackathons
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) Submodules
---
ga.c (3316B)
---
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stddef.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 struct machine {
8 uint8_t a;
9
10 uint8_t loads;
11 uint8_t adds;
12 uint8_t subs;
13 uint8_t times;
14 uint8_t noops;
15
16 uint8_t instr;
17 };
18
19 enum {
20 LOAD,
21 ADD,
22 SUB,
23 TIMES,
24 END,
25 };
26
27 #define CODE_LENGTH 16
28 #define POOL_LENGTH 16
29 struct genome {
30 uint8_t code[CODE_LENGTH + 1]; /* +1 sentinal (0) */
31 uint16_t fitness;
32 } pool[POOL_LENGTH];
33
34 uint8_t newcode[CODE_LENGTH];
35
36 void
37 execute(struct machine *m, size_t l, uint8_t code[])
38 {
39 size_t ip;
40 int16_t c;
41
42 for (ip = 0; ip < l;) {
43 switch (code[ip++] & 0x7) {
44 case LOAD:
45 m->loads++;
46 m->a = code[ip++];
47 break;
48 case ADD:
49 m->adds++;
50 c = (int16_t)m->a + code[ip++];
51 if (c > 255)
52 m->a = 0;
53 else
54 m->a = c;
55 break;
56 case SUB:
57 m->subs++;
58 c = (int16_t)m->a - code[ip++];
59 if (c < 0)
60 m->a = 0;
61 else
62 m->a = c;
63 break;
64 case TIMES:
65 m->times++;
66 m->a = (uint16_t)m->a * code[ip++] / 255;
67 break;
68 case END:
69 m->instr++;
70 return;
71 break;
72 default:
73 m->noops++;
74 break;
75 }
76 m->instr++;
77 }
78 }
79
80 void
81 mutate(uint8_t code[], size_t l)
82 {
83 uint8_t i, bi, j;
84
85 for (j = 0; j < 4; j++) {
86 if (rand() % 100 >= 50)
87 continue;
88
89 i = rand() % CODE_LENGTH;
90 bi = rand() % 8;
91
92 code[i] ^= 1 << bi;
93 }
94 }
95
96 #define min(a, b) (((a) < (b)) ? (a) : (b))
97
98 void
99 cross(uint8_t a[], size_t al, uint8_t b[], size_t bl, uint8_t c[], size_t cl)
100 {
101 uint8_t i, si, sl;
102 uint8_t *one, *two;
103
104 if (rand() % 2) {
105 one = a;
106 two = b;
107 } else {
108 one = b;
109 two = a;
110 }
111
112 si = rand() % (min(al, bl) + 1);
113 sl = rand() % (min(al, bl) - si + 1);
114
115 for (i = 0; i < si; i++)
116 c[i] = one[i];
117
118 for (; i < si + sl; i++)
119 c[i] = two[i];
120
121 for (; i < cl; i++)
122 c[i] = one[i];
123 }
124
125 void
126 cross2(uint8_t a[], size_t al, uint8_t b[], size_t bl, uint8_t c[], size_t cl)
127 {
128 uint8_t i;
129
130 for (i = 0; i < al; i++)
131 c[i] = a[i] + b[i];
132 }
133
134 void
135 printcode(uint8_t code[], size_t l)
136 {
137 uint8_t i;
138
139 for (i = 0; i < l;) {
140 switch (code[i++] & 0x7) {
141 case LOAD:
142 printf("LOAD %d ", code[i++]);
143 break;
144 case ADD:
145 printf("ADD %d ", code[i++]);
146 break;
147 case SUB:
148 printf("SUB %d ", code[i++]);
149 break;
150 case TIMES:
151 printf("TIMES %d ", code[i++]);
152 break;
153 case END:
154 printf("END ");
155 return;
156 break;
157 default:
158 printf("NOOP ");
159 break;
160 }
161 }
162 }
163
164 int
165 main(void)
166 {
167 struct machine m;
168 struct genome *g1, *g2, *w1;
169 size_t i, j;
170
171 for (i = 0; i < POOL_LENGTH; i++) {
172 for (j = 0; j < CODE_LENGTH; j++)
173 pool[i].code[j] = rand();
174 pool[i].code[j] = 0;
175 }
176
177 do {
178 g1 = g2 = w1 = NULL;
179
180 for (i = 0; i < POOL_LENGTH; i++) {
181 memset(&m, 0, sizeof(m));
182
183 execute(&m, CODE_LENGTH, pool[i].code);
184 pool[i].fitness = m.a * 255 / (m.instr + m.loads);
185
186 if (!g1 || g1->fitness < pool[i].fitness) {
187 g2 = g1;
188 g1 = &pool[i];
189 } else if (!g2 || g2->fitness < pool[i].fitness) {
190 w1 = g2;
191 g2 = &pool[i];
192 } else if (!w1 || w1->fitness > pool[i].fitness) {
193 w1 = &pool[i];
194 }
195 }
196
197 printf("g1->fitness = %d, g2->fitness = %d, w1->fitness = %d\n", g1->fitness, g2->fitness, w1->fitness);
198 cross(g1->code, CODE_LENGTH, g2->code, CODE_LENGTH, newcode, CODE_LENGTH);
199 mutate(newcode, CODE_LENGTH);
200
201 printcode(newcode, CODE_LENGTH);
202 puts("");
203
204 memcpy(w1->code, newcode, CODE_LENGTH);
205 } while (1);
206 }