Cod sursa(job #3242085)

Utilizator vralexRadu Vasilescu vralex Data 8 septembrie 2024 16:20:35
Problema Fractal Scor 100
Compilator c-64 Status done
Runda Arhiva de probleme Marime 2.66 kb
#include <stdio.h>
#include <stdlib.h>

/*
I use the following terms:

Neighbour on the curve: A point Q on the curve is said
to be a neighbour of point P on the curve if and only if
the segment PQ is on the curve. Notice that the Hilbert
curve is piecewise linear, so it is formed from a certain
number of segments.

Beginning of Hilbert curve: One of the 2 points on the
curve that has exactly one neighbour on the curve. Notice
that, regardless of the curve's order, there are exactly
2 points that can be considered the beginning of the curve.
The rest of the points on the curve have exactly 2 neighbours.

Axis of symmetry: The axis of symmetry of the Hilbert curve
of some order. From the curve drawings shown in the examples,
it is clear that a Hilbert curve has exactly one axis of
symmetry, regardless of the order of the curve. (Maybe
this can be proven rigourously using the defintion
of the Hilbert curve.)

Center of a coordinate system: point with coordinates (1,1)
in that system (just to make it easier we use (1,1) instead
of (0,0)).

Definition of fractal(order,x,y), using the above terms:

fractal(order, x, y) gives the number of segments
that should be traversed to arrive from (1,1) to
(x,y) following a curve of order "order", given a coordinate
system centred at any of the 2 "beginning" points, with the x-axis being
perpendicular to the axis of symmetry and the y-axis parallel to the axis of
symmetry. The positive direction of the axis is chosen such that all points on
the curve have positive coordinates.
*/

int fractal(int order, int x, int y) {
  /* If order = 0, there are no segments on the curve.
  In fact, the curve is just a point in this case.
  If order = 0, then x and y must be 1 for the function call to make sense.
  */
  if (order == 0) return 0;
  int pow2 = (1 << (order - 1));
  // Segments needed to traverse a quarter of the curve: 4^(order-1) - 1.
  // Recurrence is a_(n+1) = 4*a_n + 3, which can be solved to give the above.
  int quarter = (1 << (2 * (order - 1))) - 1;
  // Match the 2nd and 3rd parameters using the correct coordinate systems:
  if (x <= pow2 && y <= pow2) return fractal(order - 1, y, x);
  if (x <= pow2 && y > pow2)
    return quarter + 1 + fractal(order - 1, x, y - pow2);
  if (x > pow2 && y > pow2)
    return 2 * quarter + 2 + fractal(order - 1, x - pow2, y - pow2);
  if (x > pow2 && y <= pow2)
    return 3 * quarter + 3 + fractal(order - 1, pow2 + 1 - y, 2 * pow2 + 1 - x);
}

int main() {
  FILE *fp_in, *fp_out;
  int k, x, y;
  fp_in = fopen("fractal.in", "r");
  fp_out = fopen("fractal.out", "w");
  fscanf(fp_in, "%d %d %d", &k, &x, &y);
  fprintf(fp_out, "%d", fractal(k, x, y));
  fclose(fp_in);
  fclose(fp_out);
  return 0;
}