isundil hace 10 años
padre
commit
5949a49d7d
Se han modificado 8 ficheros con 257 adiciones y 13 borrados
  1. 3 1
      Makefile
  2. 48 6
      main.c
  3. 13 0
      output.c
  4. 4 4
      params.c
  5. 35 0
      rubiks.c
  6. 25 2
      rubiks.h
  7. 45 0
      solver.c
  8. 84 0
      stack.c

+ 3 - 1
Makefile

@@ -5,8 +5,10 @@ SRC=	main.c				\
 		std.c				\
 		params.c			\
 		generator.c			\
+		solver.c			\
 		rubiks.c			\
 		rubiks_transform.c	\
+		stack.c				\
 		output.c
 
 OBJ=$(SRC:.c=.o)
@@ -15,7 +17,7 @@ CC=		clang
 
 CFLAGS=	-W -g3
 
-LDFLAGS=	-g3
+LDFLAGS=	-g3 -lm
 
 $(NAME):	$(OBJ)
 	$(CC) $(OBJ) -o $(NAME) $(LDFLAGS)

+ 48 - 6
main.c

@@ -15,15 +15,15 @@ int generate(char **params, char *av0)
 	srand(time(NULL) * getpid());
 	if (!parse_params(params, &p, av0))
 	{
-		xfree(p.output);
+		xfree(p.file);
 		return -1;
 	}
-	if (p.output == NULL)
+	if (p.file == NULL)
 		f = stdout;
-	else if ((f = fopen(p.output, "a+")) == NULL)
+	else if ((f = fopen(p.file, "a+")) == NULL)
 	{
-		fprintf(stderr, "Cannot open %s for writting\n", p.output);
-		free(p.output);
+		fprintf(stderr, "Cannot open %s for writting\n", p.file);
+		free(p.file);
 		return -1;
 	}
 	for (i=0; i < p.count; i++)
@@ -33,7 +33,47 @@ int generate(char **params, char *av0)
 		fprintf(f, "\n");
 		free(r);
 	}
-	xfree(p.output);
+	if (p.file)
+		fclose(f);
+	xfree(p.file);
+	return 0;
+}
+
+int solve(char **params, char *av0)
+{
+	t_params p;
+	t_rubiks *output;
+	FILE *f;
+	char buffer[55];
+
+	if (!parse_params(params, &p, av0))
+	{
+		xfree(p.file);
+		return -1;
+	}
+	if (p.file == NULL)
+		f = stdin;
+	else if ((f = fopen(p.file, "r")) == NULL)
+	{
+		fprintf(stderr, "Cannot open %s for writting\n", p.file);
+		free(p.file);
+		return -1;
+	}
+	while (fread(buffer, 55, 1, f) == 1)
+	{
+		buffer[54] = '\0';
+		t_stack *result = doSolve(buffer, p.nbMovment);
+		output = rubik_create(buffer);
+		spatial_show(output);
+		rubik_output(output, stdout);
+		solution_output(result, stdout);
+		printf("\n");
+		free(output);
+		stack_destroy(result);
+	}
+	if (p.file)
+		fclose(f);
+	xfree(p.file);
 	return 0;
 }
 
@@ -42,6 +82,8 @@ int main(int ac, char **av)
 	(void) ac;
 	if (av[1] && (!strcmp(av[1], "generate") || !strcmp(av[1], "gen")))
 		return generate(&av[2], av[0]);
+	else if (av[1] && !strcmp(av[1], "solve"))
+		return solve(&av[2], av[0]);
 	fprintf(stderr, "Expected valid action\n");
 	usage(av[0]);
 	return -1;

+ 13 - 0
output.c

@@ -41,3 +41,16 @@ void spatial_show(t_rubiks *rub)
 	printf("+---+---+---+\n");
 }
 
+static void doSolutionOutput(struct s_stackitem *s, FILE *out, size_t down)
+{
+	if (--down)
+		doSolutionOutput(s->prev, out, down);
+	fprintf(out, "%c", (int) s->value);
+}
+
+void solution_output(t_stack *s, FILE *out)
+{
+	fprintf(out, ".");
+	doSolutionOutput(s->items, out, stack_length(s));
+}
+

+ 4 - 4
params.c

@@ -5,7 +5,7 @@
 
 void usage(char *av0)
 {
-	printf("Usage: %s action [-o filename] [-c count=20] [-move movment=20]\n", av0);
+	printf("Usage: %s action [-f filename] [-c count=20] [-move movment=20]\n", av0);
 	printf("\taction: generate|gen create a new grid\n");
 }
 
@@ -33,12 +33,12 @@ int parse_params(char **params, t_params *p, char *av0)
 {
 	int varNum;
 	p->count = 20;
-	p->output = NULL;
+	p->file = NULL;
 	p->nbMovment = 20;
 
 	for (int i=0; params[i]; ++i)
 	{
-		if (!strcmp(params[i], "-o"))
+		if (!strcmp(params[i], "-f"))
 		{
 			if (!params[i+1])
 			{
@@ -46,7 +46,7 @@ int parse_params(char **params, t_params *p, char *av0)
 				usage(av0);
 				return 0;
 			}
-			p->output = strdup(params[i+1]);
+			p->file = strdup(params[i+1]);
 			i++;
 		}
 		else if (!strcmp(params[i], "-c"))

+ 35 - 0
rubiks.c

@@ -48,6 +48,19 @@ void rubik_applyVect(t_rubiks *r, char v[3])
 	}
 }
 
+void rubik_reverse(t_rubiks *r, char m)
+{
+	char mov[3] = { 0, 0, 0 };
+	int init_m = (int) m;
+
+	mov[2] = (char)(m % 2) ? '-' : '+';
+	m /= 2;
+	mov[1] = '0' + ((char)(m % 3));
+	m /= 3;
+	mov[0] = 'X' + ((char)(m % 3));
+	rubik_applyVect(r, mov);
+}
+
 void rubik_apply(t_rubiks *r, char m)
 {
 	char mov[3] = { 0, 0, 0 };
@@ -86,3 +99,25 @@ t_rubiks *rubik_create(char matrix[54])
 	return result;
 }
 
+int rubik_isDone(const t_rubiks *r)
+{
+	char current;
+	char first;
+	int i, j, k;
+
+	for (i = 0; i < 6; ++i)
+	{
+		first = 1;
+		for (j = 0; j < 3; ++j)
+			for (k = 0; k < 3; ++k)
+			{
+				if (first)
+					current = r->grid[i][j][k];
+				else if (current != r->grid[i][j][k])
+					return 0;
+				first = 0;
+			}
+	}
+	return 1;
+}
+

+ 25 - 2
rubiks.h

@@ -3,7 +3,7 @@
 #include <stdio.h>
 
 typedef struct {
-	char *output;
+	char *file;
 	int count;
 	int nbMovment;
 }	t_params;
@@ -12,6 +12,15 @@ typedef struct {
 	char grid[6][3][3];
 }	t_rubiks;
 
+struct s_stackitem {
+	struct s_stackitem *prev;
+	int value;
+};
+typedef struct s_stack {
+	struct s_stackitem *items;
+	size_t count;
+}	t_stack;
+
 /* params.c */
 void usage(char*);
 int parse_params(char **, t_params *, char *);
@@ -19,6 +28,9 @@ int parse_params(char **, t_params *, char *);
 /* generator.c */
 t_rubiks *doGenerate(t_params *);
 
+/* solver.c */
+t_stack *doSolve(char buffer[54], int nbMovment);
+
 /* std */
 void xfree(void *);
 
@@ -32,8 +44,19 @@ t_rubiks *rubik_create(char [54]);
 t_rubiks *rubik_createempty();
 void rubik_applyVect(t_rubiks *, char [3]);
 void rubik_apply(t_rubiks *, char movment);
+void rubik_reverse(t_rubiks *, char movment);
+int rubik_isDone(const t_rubiks *);
 
-/* debug.h */
+/* output.c */
 void spatial_show(t_rubiks *);
 void rubik_output(t_rubiks *, FILE *);
 
+/* tree.c */
+t_stack *stack_create();
+t_stack *stack_copy(const t_stack *);
+void stack_destroy(t_stack*);
+int stack_pop(t_stack *);
+int stack_value(const t_stack *);
+size_t stack_length(const t_stack *);
+void stack_push(t_stack *, int value);
+

+ 45 - 0
solver.c

@@ -0,0 +1,45 @@
+
+#include <math.h>
+#include <stdlib.h>
+#include "rubiks.h"
+
+static void solver_iterate(t_rubiks *r, t_stack *result, size_t maxDeep, t_stack **sol)
+{
+	char movType;
+
+	for (movType =0; movType < 18; ++movType)
+	{
+		if (movType == stack_value(result))
+			continue;
+		stack_push(result, movType);
+		rubik_apply(r, movType);
+		if (rubik_isDone(r))
+		{
+			if (*sol == NULL || stack_length(result) < stack_length(*sol))
+			{
+				if (*sol)
+					stack_destroy(*sol);
+				*sol = stack_copy(result);
+				maxDeep = stack_length(result);
+			}
+		}
+		else if (stack_length(result) < maxDeep)
+			solver_iterate(r, result, maxDeep, sol);
+		stack_pop(result);
+		rubik_reverse(r, movType);
+	}
+}
+
+t_stack *doSolve(char buffer[54], int maxDeep)
+{
+	t_rubiks *r = rubik_create(buffer);
+	t_stack *result = stack_create();
+	t_stack *solution = NULL;
+
+	solver_iterate(r, result, (size_t) maxDeep, &solution);
+
+	free(r);
+	stack_destroy(result);
+	return solution;
+}
+

+ 84 - 0
stack.c

@@ -0,0 +1,84 @@
+
+#include <stdlib.h>
+#include "rubiks.h"
+
+t_stack *stack_create()
+{
+	t_stack *result = (t_stack *)malloc(sizeof(*result));
+	result->items = NULL;
+	result->count = 0;
+	return result;
+}
+
+t_stack *stack_copy(const t_stack *t)
+{
+	t_stack *result = (t_stack *)malloc(sizeof(*result));
+	struct s_stackitem *aitem, *bitem;
+	size_t i;
+
+	result->items = NULL;
+	result->count = t->count;
+	if (result->count)
+	{
+		aitem = malloc(sizeof(*aitem));
+		bitem = t->items;
+
+		aitem->value = bitem->value;
+		result->items = aitem;
+		for (i =1; i < t->count; ++i)
+		{
+			aitem->prev = malloc(sizeof(*aitem));
+			aitem = aitem->prev;
+			bitem = bitem->prev;
+			aitem->prev = NULL;
+			aitem->value = bitem->value;
+		}
+	}
+	return result;
+}
+
+int stack_pop(t_stack *s)
+{
+	int r;
+	struct s_stackitem *oldNode = s->items;
+
+	if (!s->count)
+		return -1;
+	oldNode = s->items;
+	r = oldNode->value;
+	s->items = oldNode->prev;
+	s->count--;
+	free(oldNode);
+	return r;
+}
+
+size_t stack_length(const t_stack *s)
+{
+	return s->count;
+}
+
+int stack_value(const t_stack *s)
+{
+	if (!s->count)
+		return -1;
+	return s->items->value;
+}
+
+void stack_destroy(t_stack *stack)
+{
+	if (!stack)
+		return;
+	while (stack->count)
+		stack_pop(stack);
+	free(stack);
+}
+
+void stack_push(t_stack *st, int v)
+{
+	struct s_stackitem *s = (struct s_stackitem *) malloc(sizeof(*s));
+	s->prev = st->count ? st->items : NULL;
+	s->value = v;
+	st->items = s;
+	st->count++;
+}
+