import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

public class StarSim_artur {

  static final int MAXN = 100100;
  static final long[] x = new long[MAXN], y = new long[MAXN], z = new long[MAXN];

  static int n;
  static long ksqr;

  public static void main(String[] args) throws Exception {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

    int[] dx = new int[] { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
    int[] dy = new int[] { 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, -1, -1, -1 };
    int[] dz = new int[] { 1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1 };

    while (true) {
      StringTokenizer str = new StringTokenizer(in.readLine());
      n = Integer.valueOf(str.nextToken());
      int k = Integer.valueOf(str.nextToken());
      if (n == 0 && k == 0)
        break;
      ksqr = k * 1L * k;

      HashMap<Bucket, LinkedList<Integer>> buckets = new HashMap<Bucket, LinkedList<Integer>>();
      for (int i = 0; i < n; i++) {
        str = new StringTokenizer(in.readLine());
        x[i] = Long.parseLong(str.nextToken());
        y[i] = Long.parseLong(str.nextToken());
        z[i] = Long.parseLong(str.nextToken());

        Bucket b = new Bucket(x[i] / k, y[i] / k, z[i] / k);
        if (!buckets.containsKey(b))
          buckets.put(b, new LinkedList<Integer>());
        buckets.get(b).add(i);
      }

      int total = 0;
      Bucket q = new Bucket(0, 0, 0);
      for (Bucket p : buckets.keySet()) {
        List<Integer> list = buckets.get(p);
        for (int i : list)
          for (int j : list)
            if (j < i)
              total += within(i, j) ? 1 : 0;
            else
              break;
        for (int ind = 0; ind < dx.length; ind++) {
          q.i = p.i + dx[ind];
          q.j = p.j + dy[ind];
          q.k = p.k + dz[ind];
          if (buckets.containsKey(q))
            for (int i : list)
              for (int j : buckets.get(q))
                if (i != j && within(i, j))
                  total++;
        }
      }
      System.out.println(total);
    }
  }

  static boolean within(int i, int j) {
    long k = ksqr;

    long dx = x[i] - x[j];
    k -= dx * dx;
    if (k <= 0)
      return false;

    long dy = y[i] - y[j];
    k -= dy * dy;
    if (k <= 0)
      return false;

    long dz = z[i] - z[j];
    k -= dz * dz;
    if (k <= 0)
      return false;

    return true;
  }

  static class Bucket {
    long i, j, k;

    Bucket(long x, long y, long z) {
      i = x;
      j = y;
      k = z;
    }

    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + (int) (i ^ (i >>> 32));
      result = prime * result + (int) (j ^ (j >>> 32));
      result = prime * result + (int) (k ^ (k >>> 32));
      return result;
    }

    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      Bucket other = (Bucket) obj;
      if (i != other.i)
        return false;
      if (j != other.j)
        return false;
      if (k != other.k)
        return false;
      return true;
    }
  }
}
