1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class cie {

  private static int counter = 0;
  private static int d, k, r;
  private static Random rand = new Random();
  private static int[] lastImprovement;

  public static void main(String[] args) {
    d = cielib.podajD();
    k = cielib.podajK();
    r = cielib.podajR();

    int[] current = getAndCheckFirstMidPoint();
    int currentShift = Math.floorDiv(r, 2);
    double shiftRatio = computeShiftRatio();

    // System.out.println("log: " + Math.log(Math.pow(10, 9)) / Math.log(1.5));
    // System.out.println(d + " " + k + " " + r);
    while (counter < k + 1) {
      int[] n = gen_next(current, currentShift);
      current = checkAndReturnBetter(current, n);
      currentShift = (int) Math.max(1, Math.floor(currentShift * shiftRatio));
      // System.out.println("Current shift: " + currentShift + " " +
      // shiftRatio);
    }
  }

  private static double computeShiftRatio() {
    // return 0.9;
    // return Math.log(Math.pow(10, 9)) / Math.log(1.5);
    // r*(p)^k = 1
    // p^k = 1 / r
    // p = (1/r)^(1/k)
    // p = log_k(1/r) = 1 - log_k(r) = 1 - log(r)/log(k)
    return Math.pow(1.0 / r, 1.0 / k);
  }

  private static int[] getAndCheckFirstMidPoint() {
    int[] mid = getMidPoint();
    lastImprovement = mid;
    checkOrEnd(mid);
    return mid;
  }

  private static int[] checkAndReturnBetter(int[] current, int[] n) {
    int res = checkOrEnd(n);
    if (res == 0) {
      return current;
    }
    return n;
  }

  private static int[] getMidPoint() {
    int m = Math.floorDiv(r, 2);
    int[] mid = new int[d];
    for (int i = 0; i < d; i++) {
      mid[i] = m;
    }
    return mid;
  }

  private static int checkOrEnd(int[] t) {
    // System.out.println("Current counter: " + counter);
    if (counter >= k) {
      // System.out.println("Final check: " + getStr(lastImprovement));
      cielib.znalazlem(lastImprovement);
      return 0;
    } else {
      // System.out.println("Checking: " + getStr(t));
      counter += 1;
      int res = cielib.czyCieplo(t);
      // System.out.println("Result: " + res);
      if (res == 1) {
        lastImprovement = t;
      }
      return res;
    }
  }

  private static String getStr(int[] t) {
    List<Integer> List = new ArrayList<>(t.length);
    for (int i = 0; i < t.length; i++) {
      List.add(t[i]);
    }
    return List.stream().map(x -> x.toString()).collect(Collectors.joining(","));
  }

  private static int[] gen_next(int[] t, int m) {
    int[] n = new int[d];
    for (int i = 0; i < d; i++) {
      n[i] = ensureInSquare(t[i] - m + rand.nextInt(2 * m + 1));
    }
    return n;
  }

  private static int ensureInSquare(int x) {
    return Math.max(0, Math.min(x, r));
  }

}