Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
zmx0142857
GitHub Repository: zmx0142857/mini-games
Path: blob/master/c/24points/24points.c
363 views
1
#include <stdio.h>
2
#include <stdbool.h>
3
4
const float digits[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
5
float d[4] = {1, 4, 5, 6};
6
// 4 / (1 - (5 / 6)) 或 6 / ((5 / 4) - 1)
7
8
float add(float x, float y) { return x + y; }
9
float sub(float x, float y) { return x - y; }
10
float mul(float x, float y) { return x * y; }
11
float div(float x, float y) { return x / y; }
12
13
typedef float func(float, float);
14
func *operators[] = {add, sub, mul, div};
15
func *op[3];
16
17
const int size = sizeof(digits) / sizeof(float);
18
const int count = sizeof(d) / sizeof(float);
19
const int node_count = sizeof(op) / sizeof(func*);
20
21
bool has_solution = false;
22
23
char name(int i)
24
{
25
if (op[i] == add)
26
return '+';
27
if (op[i] == sub)
28
return '-';
29
if (op[i] == mul)
30
return '*';
31
if (op[i] == div)
32
return '/';
33
return '?';
34
}
35
36
bool test(float f)
37
{
38
f -= 24;
39
return -1e-5 < f && f < 1e-5;
40
}
41
42
/* 尝试 Catalan(3) = 5 种树形
43
* 0 0 0 0 0
44
* / \ / \ / \
45
* 1 2 1 1 1 1
46
* / \ \ /
47
* 2 2 2 2
48
*/
49
bool try_trees()
50
{
51
if (test(op[0](op[1](d[0], d[1]), op[2](d[2], d[3])))) {
52
printf("(%.0f %c %.0f) %c (%.0f %c %.0f)\n",
53
d[0], name(1), d[1], name(0), d[2], name(2), d[3]);
54
} else if (test(op[0](op[1](op[2](d[0], d[1]), d[2]), d[3]))) {
55
printf("((%.0f %c %.0f) %c %.0f) %c %.0f\n",
56
d[0], name(2), d[1], name(1), d[2], name(0), d[3]);
57
} else if (test(op[0](d[0], op[1](d[1], op[2](d[2], d[3]))))) {
58
printf("%.0f %c (%.0f %c (%.0f %c %.0f))\n",
59
d[0], name(0), d[1], name(1), d[2], name(2), d[3]);
60
} else if (test(op[0](op[1](d[0], op[2](d[1], d[2])), d[3]))) {
61
printf("(%.0f %c (%.0f %c %.0f)) %c %.0f\n",
62
d[0], name(1), d[1], name(2), d[2], name(0), d[3]);
63
} else if (test(op[0](d[0], op[1](op[2](d[1], d[2]), d[3])))) {
64
printf("%.0f %c ((%.0f %c %.0f) %c %.0f)\n",
65
d[0], name(0), d[1], name(2), d[2], name(1), d[3]);
66
} else {
67
return false;
68
}
69
has_solution = true;
70
return true;
71
}
72
73
// 从数组 operators 取出 node_count-pos 个元素, 计次序, 可重复
74
// 存入数组 op 中
75
void calc(int pos)
76
{
77
if (pos == node_count) {
78
try_trees();
79
} else {
80
for (int i = 0; i < count; ++i) {
81
op[pos] = operators[i];
82
calc(pos+1);
83
}
84
}
85
}
86
87
// 打印 d 数组
88
void print()
89
{
90
for (int i = 0; i < count; ++i)
91
printf("%.0f ", d[i]);
92
putchar('\n');
93
}
94
95
void swap(float *i, float *j)
96
{
97
float tmp = *i;
98
*i = *j;
99
*j = tmp;
100
}
101
102
// 产生数组 d 的全排列
103
// 解决 d 中保存的 24 点问题
104
void permutate(int pos)
105
{
106
if (pos == count) {
107
calc(0);
108
} else {
109
for (int i = pos; i < count; ++i) {
110
swap(d+pos, d+i);
111
permutate(pos+1);
112
swap(d+pos, d+i);
113
}
114
}
115
}
116
117
// 从数组 digits+lo 中选取 count-pos 个元素, 不计顺序, 可以重复选取
118
// 按从小到大的次序输出到 d 数组中
119
void choose(int lo, int pos)
120
{
121
if (pos == count) {
122
has_solution = false;
123
permutate(0);
124
if (!has_solution) {
125
printf("[failed] ");
126
print();
127
}
128
} else {
129
for (int i = lo; i < size; ++i) {
130
d[pos] = digits[i];
131
choose(i, pos+1);
132
}
133
}
134
}
135
136
int main()
137
{
138
//permutate(0);
139
choose(0, 0);
140
return 0;
141
}
142
143