示例#1
0
文件: eu065.c 项目: pbevin/euler
void eu065(char *ans) {
  int N = 99;
  mpz_t n, d, r;

  mpz_init(n);
  mpz_init(d);
  mpz_init(r);

  mpz_set_ui(n, eterm(N));
  mpz_set_ui(d, 1);

  for (int i = N-1; i >= 0; i--) {
    mpz_swap(n, d);
    int t = eterm(i);
    mpz_addmul_ui(n, d, t);
    mpz_gcd(r, n, d);
    mpz_div(n, n, r);
    mpz_div(d, d, r);
  }

  sprintf(ans, "%d", digitsum(n));

  mpz_clear(r);
  mpz_clear(d);
  mpz_clear(n);
}
static
void process_clause(Mclause c, Mstate state)
{
  if (c->subsumed)
    return;
  else if (c->u.active == 0) {
    if (flag(Opt->trace))
      printf("\t\t\t\t\t** BACKUP **\n");
    state->ok = FALSE;
    return;
  }
  else if (c->u.active != 1)
    return;   /* nonunit, so do nothing */
  else {
    /* OK, we have a nonsubsumed unit. */
    Term lit, beta;
    BOOL negated, eq;
    int id;
    int i = 0;
    while (FALSE_TERM(LIT(c,i)))
      i++;
    
    lit = LIT(c,i);
    negated = NEGATED(lit);
    eq = EQ_TERM(lit);

#if 0
    printf("process_clause 1: ");
    p_matom(lit);
#endif

    if (!eq && eterm(lit, &id))
      beta = Domain[negated ? 0 : 1]; /* P(1,2,3) or ~P(1,2,3) */
    else if (eq && eterm(ARG(lit,0),&id) && VARIABLE(ARG(lit,1)))
      beta = ARG(lit,1);  /* f(1,2)=3 or f(1,2)!=3 */
    else if (eq && eterm(ARG(lit,1),&id) && VARIABLE(ARG(lit,0)))
      beta = ARG(lit,0);  /* 3=f(1,2) or 3!=f(1,2) */
    else {
      if (flag(Opt->negprop))
	/* If it is an nterm, index and insert into job list. */
	nterm_check_and_process(lit, state);
      return;  /* We cannot do anything else with the unit. */
    }

    if (eq && negated)
      new_elimination(id, beta, state);  /* f(1,2) != 3 */
    else
      new_assignment(id, beta, state);   /* f(1,2) = 3, P(0), ~P(0) */
  }
}  /* process_clause */
static
void propagate_positive(int id, Mstate state)
{
  Term t;
#if 0
  printf("propagage_positive: "); p_term(Cells[id].eterm);
#endif
  for (t = Cells[id].occurrences; t != NULL; t = t->u.vp) {
    /* foreach term the rule applies to */
    Term curr = t;
    Mclause clause_to_process;
    BOOL index_it;
    /* The following loop iterates up toward the root of the clause,
       rewriting terms.  We stop when we get to a literal, an eterm that
       cannot be rewritten (we then index the eterm in this case), or when
       we get to a non-eterm. */
#if 0
    printf("rewriting: "); p_mclause(containing_mclause(curr));
#endif
    while (!LITERAL(curr) &&            /* stop if literal */
	   !arith_op_term(curr) &&      /* stop if arithmetic term */
	   eterm(curr, &id) &&          /* stop if not eterm */
	   Cells[id].value != NULL) {   /* stop if eterm not evaluable*/
      Term result = Cells[id].value;
      Term parent = curr->container;
      int pos = arg_position(parent, curr);
      state->stack = update_and_push((void **) &(ARG(parent,pos)),
				     result, state->stack);
      Mstats.rewrite_terms++;
      curr = parent;
    }  /* while rewriting upward */

#if 0
    printf("done:      "); p_mclause(containing_mclause(curr));
#endif

    clause_to_process = NULL;  /* set to possible new rule */
    index_it = FALSE;        /* should curr be indexed? */

    if (arith_rel_term(curr) || arith_op_term(curr)) {
      Term parent_lit = containing_mliteral(curr);
      Mclause parent_clause = parent_lit->container;
      if (!parent_clause->subsumed) {
	BOOL evaluated;
	int b = arith_eval(parent_lit, &evaluated);
	if (evaluated) {
	  Term result;
	  if (b != 0 && b != 1)
	    fatal_error("propagate_positive, arith_eval should be Boolean");
	  result = (b ? Domain[1] : Domain[0]);
	  clause_to_process = handle_literal(parent_lit, result, state);
	}
	else if (EQ_TERM(curr))
	  clause_to_process = parent_clause;
      }
    }
    else if (!LITERAL(curr)) {
      /* curr is a term */
      Term parent = curr->container;
      if (id != -1)
	index_it = TRUE;  /* curr is a non-evaluable eterm */
      /* If curr is 1 or 2 steps away from a literal, process it. */
      if (LITERAL(parent))
	clause_to_process = parent->container;
      else {
	parent = parent->container;
	if (LITERAL(parent))
	  clause_to_process = parent->container;
      }
    }
    else {
      /* curr is a literal (equality or nonquality, positive or negative) */
      Mclause parent_clause = curr->container;
      if (!eterm(curr, &id))
	/* non-eterm literal */
	clause_to_process = parent_clause;
      else if (Cells[id].value == NULL) {
	/* non-evaluable eterm literal */
	index_it = TRUE;
	clause_to_process = parent_clause;
      }
      else if (!parent_clause->subsumed) {
	clause_to_process = handle_literal(curr, Cells[id].value, state);
      }
    }  /* literal */

    if (index_it) {
      /* curr is an evaluable term or literal, e.g., f(1,2), but there is
	 no rule for it. Therefore, we index it so that it can be
	 found in case a rule appears later. */
      Mstats.indexes++;
      state->stack = update_and_push((void **) &(curr->u.vp),
				     Cells[id].occurrences, state->stack);
      state->stack = update_and_push((void **) &(Cells[id].occurrences),
				     curr, state->stack);
    }

    if (clause_to_process != NULL) {
      process_clause(clause_to_process, state);
      if (!state->ok)
	return;
    }
  }  /* foreach occurrence (container) of the cell just assigned */
}  /* propagate_positive */