
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public class StarSim_zeil {
	
	
	public static class Point {
		public int x, y, z;
		
		public Point (int xx, int yy, int zz)
		{
			x = xx;
			y = yy;
			z = zz;
		}
		
		public String toString ()
		{
			return "(" + x + "," + y + "," + z + ")"; 
		}
		
		public int hashCode() {
			return x + 1299 * y + 37 * z;
		}
		
		public boolean equals (Object obj)
		{
			Point p = (Point)obj;
			return x == p.x && y == p.y && z == p.z;
		}
		
		public long distanceSq (Point p) {
			long dx = x - p.x;
			long dy = y - p.y;
			long dz = z - p.z;
			return dx*dx + dy*dy + dz*dz;
		}
	};

	private static int setNumber = 0;
		
	private int K;
	private int N;
	private Point[] points;
	private HashMap<Point, ArrayList<Point>> hash;
	int xmin, xmax;
	int ymin, ymax;
	int zmin, zmax;
	
	int longestCell;
 
	
	public long rangeSearch (Point center)
	{
		long counter = 0;
		Point cell = selectCellFor (center);
		long Ksq = (long)K * (long)K;
		for (int dx = -1; dx <= 1; ++dx)
			for (int dy = -1; dy <= 1; ++dy) {
				for (int dz = -1; dz <= 1; ++dz) {
					Point nearByCell = new Point(cell.x + dx, cell.y + dy, cell.z + dz);
					ArrayList<Point> nearByPoints = hash.get(nearByCell);
					if (nearByPoints != null) {
						for (Point p: nearByPoints) {
							double dist = p.distanceSq(center);
							double diff = dist - Ksq;
							if (diff < 0.0) {
								//if (!center.equals(p)) 	System.err.println (center + " " + p);
								++counter;
							}
						}
					}
				}
			}
		--counter; // because (center,center) does not count
		return counter;
	}

	private Point selectCellFor(Point p) {
		int ix = (int)((p.x - xmin) / K);
		int iy = (int)((p.y - ymin) / K);
		int iz = (int)((p.z - zmin) / K);
		return new Point(ix, iy, iz);
	}

	

	public StarSim_zeil(int n, Scanner in) {
		N = n;
		points = new Point[n];
		hash = new HashMap<>();
		xmin = ymin = zmin = Integer.MAX_VALUE;
		xmax = ymax = zmax = Integer.MIN_VALUE;
		longestCell=0;
		K = in.nextInt();
		for (int i = 0; i < n; ++i) {
			int x = in.nextInt();
			int y = in.nextInt();
			int z = in.nextInt();
			Point p = new Point(x,y,z);
			points[i] = p;
			xmin = Math.min(xmin, x);
			xmax = Math.max(xmax, x);
			ymin = Math.min(ymin, y);
			ymax = Math.max(ymax, y);
			zmin = Math.min(zmin, z);
			zmax = Math.max(zmax, z);
		}
	}

	
	
	
	public static void main (String[] args) throws FileNotFoundException 
	{
		Scanner in;
		if (args.length == 0)
			in = new Scanner (System.in);
		else
			in = new Scanner(new BufferedReader(new FileReader(args[0])));
		while (in.hasNextInt()) {
			int n = in.nextInt();
			if (n <= 0)
				break;
			new StarSim_zeil(n, in).solve();
			++setNumber;
		}
	}

	private void solve() {
		for (Point p: points) {
			Point cell = selectCellFor(p);
			ArrayList<Point> ptsInCell = hash.get(cell);
			if (ptsInCell == null) {
				ptsInCell = new ArrayList<>();
				hash.put(cell,  ptsInCell);
			}
			ptsInCell.add(p);
			longestCell = Math.max(longestCell, ptsInCell.size());
		}
		long counter = 0;
		for (Point p: points) {
			counter += rangeSearch(p);
		}
			
		System.out.println(counter / 2L);
		/*System.err.println ("Test set " + setNumber + " N=" + N + "  K=" + K
				+ "    longest cell=" + longestCell);*/
	}
	
	
}
