summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/combi.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2017-04-29 18:21:56 -0400
committerFranklin Wei <git@fwei.tk>2017-04-29 18:24:42 -0400
commit881746789a489fad85aae8317555f73dbe261556 (patch)
treecec2946362c4698c8db3c10f3242ef546c2c22dd /apps/plugins/puzzles/src/combi.c
parent03dd4b92be7dcd5c8ab06da3810887060e06abd5 (diff)
downloadrockbox-881746789a489fad85aae8317555f73dbe261556.zip
rockbox-881746789a489fad85aae8317555f73dbe261556.tar.gz
rockbox-881746789a489fad85aae8317555f73dbe261556.tar.bz2
rockbox-881746789a489fad85aae8317555f73dbe261556.tar.xz
puzzles: refactor and resync with upstream
This brings puzzles up-to-date with upstream revision 2d333750272c3967cfd5cd3677572cddeaad5932, though certain changes made by me, including cursor-only Untangle and some compilation fixes remain. Upstream code has been moved to its separate subdirectory and future syncs can be done by simply copying over the new sources. Change-Id: Ia6506ca5f78c3627165ea6791d38db414ace0804
Diffstat (limited to 'apps/plugins/puzzles/src/combi.c')
-rw-r--r--apps/plugins/puzzles/src/combi.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/apps/plugins/puzzles/src/combi.c b/apps/plugins/puzzles/src/combi.c
new file mode 100644
index 0000000..4c5d107
--- /dev/null
+++ b/apps/plugins/puzzles/src/combi.c
@@ -0,0 +1,110 @@
+#include <assert.h>
+#include <string.h>
+
+#include "puzzles.h"
+
+/* horrific and doesn't check overflow. */
+static long factx(long x, long y)
+{
+ long acc = 1, i;
+
+ for (i = y; i <= x; i++)
+ acc *= i;
+ return acc;
+}
+
+void reset_combi(combi_ctx *combi)
+{
+ int i;
+ combi->nleft = combi->total;
+ for (i = 0; i < combi->r; i++)
+ combi->a[i] = i;
+}
+
+combi_ctx *new_combi(int r, int n)
+{
+ long nfr, nrf;
+ combi_ctx *combi;
+
+ assert(r <= n);
+ assert(n >= 1);
+
+ combi = snew(combi_ctx);
+ memset(combi, 0, sizeof(combi_ctx));
+ combi->r = r;
+ combi->n = n;
+
+ combi->a = snewn(r, int);
+ memset(combi->a, 0, r * sizeof(int));
+
+ nfr = factx(n, r+1);
+ nrf = factx(n-r, 1);
+ combi->total = (int)(nfr / nrf);
+
+ reset_combi(combi);
+ return combi;
+}
+
+/* returns NULL when we're done otherwise returns input. */
+combi_ctx *next_combi(combi_ctx *combi)
+{
+ int i = combi->r - 1, j;
+
+ if (combi->nleft == combi->total)
+ goto done;
+ else if (combi->nleft <= 0)
+ return NULL;
+
+ while (combi->a[i] == combi->n - combi->r + i)
+ i--;
+ combi->a[i] += 1;
+ for (j = i+1; j < combi->r; j++)
+ combi->a[j] = combi->a[i] + j - i;
+
+ done:
+ combi->nleft--;
+ return combi;
+}
+
+void free_combi(combi_ctx *combi)
+{
+ sfree(combi->a);
+ sfree(combi);
+}
+
+/* compile this with:
+ * gcc -o combi.exe -DSTANDALONE_COMBI_TEST combi.c malloc.c
+ */
+#ifdef STANDALONE_COMBI_TEST
+
+#include <stdio.h>
+
+void fatal(char *fmt, ...)
+{
+ abort();
+}
+
+int main(int argc, char *argv[])
+{
+ combi_ctx *c;
+ int i, r, n;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: combi R N\n");
+ exit(1);
+ }
+
+ r = atoi(argv[1]); n = atoi(argv[2]);
+ c = new_combi(r, n);
+ printf("combi %d of %d, %d elements.\n", c->r, c->n, c->total);
+
+ while (next_combi(c)) {
+ for (i = 0; i < c->r; i++) {
+ printf("%d ", c->a[i]);
+ }
+ printf("\n");
+ }
+ free_combi(c);
+}
+
+#endif