Problem: Jamie has recently found undirected weighted graphs with the following properties very interesting:

  * The graph is connected and contains exactly n vertices and m edges. 
  * All edge weights are integers and are in range [1, 109] inclusive. 
  * The length of shortest path from 1 to n is a prime number. 
  * The sum of edges' weights in the minimum spanning tree (MST) of the graph is a prime number. 
  * The graph contains no loops or multi-edges. 



If you are not familiar with some terms from the statement you can find definitions of them in notes section. 

Help Jamie construct any graph with given number of vertices and edges that is interesting!

Input

First line of input contains 2 integers n, m <image> — the required number of vertices and edges.

Output

In the first line output 2 integers sp, mstw (1 ≤ sp, mstw ≤ 1014) — the length of the shortest path and the sum of edges' weights in the minimum spanning tree.

In the next m lines output the edges of the graph. In each line output 3 integers u, v, w (1 ≤ u, v ≤ n, 1 ≤ w ≤ 109) describing the edge connecting u and v and having weight w. 

Examples

Input

4 4


Output

7 7
1 2 3
2 3 2
3 4 2
2 4 4


Input

5 4


Output

7 13
1 2 2
1 3 4
1 4 3
4 5 4

Note

The graph of sample 1: <image> Shortest path sequence: {1, 2, 3, 4}. MST edges are marked with an asterisk (*).

Definition of terms used in the problem statement:

A shortest path in an undirected graph is a sequence of vertices (v1, v2, ... , vk) such that vi is adjacent to vi + 1 1 ≤ i < k and the sum of weight <image> is minimized where w(i, j) is the edge weight between i and j. (<https://en.wikipedia.org/wiki/Shortest_path_problem>)

A prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself. (<https://en.wikipedia.org/wiki/Prime_number>)

A minimum spanning tree (MST) is a subset of the edges of a connected, edge-weighted undirected graph that connects all the vertices together, without any cycles and with the minimum possible total edge weight. (<https://en.wikipedia.org/wiki/Minimum_spanning_tree>)

<https://en.wikipedia.org/wiki/Multiple_edges>

Solution (in JAVA):

Solution:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Random;
import java.util.StringTokenizer;


public class Main {

	public static void main(String[] args) throws IOException, InterruptedException {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}

	static class TaskC {
		static boolean visited[]  ;
		static boolean found = false; 

		static int steps = 0 ;
		static int n ; 
		static boolean memo [][] ; 
		static int dp[][] ; 
		static char matrix[][] ;
		static ArrayList<Integer> p  ;
		public void solve(int testNumber, InputReader in, PrintWriter out) throws IOException, InterruptedException {
			int n =  in.nextInt() ; 
			int m =  in.nextInt() ; 

			if(n==2)
			{
				out.println(7+" "+7);
				out.println("1 2 7");
				return ;
			}

			int prime = m ; 
			for (int i = n-1;; i++)
			{
				if(isPrime(i))
				{
					prime =i ;
					break ;
				}
			}

			int last = prime-(n-1)+1 ; 
			int inf = 100000000 ; 

			int c = m-(n-1) ; 

			out.println(prime+" "+prime);
			for (int i = 1; i <=(n-1); i++)
			{
				if(i!=n-1)out.println(i+" "+(i+1)+" "+1);
				if (i==n-1)out.println(i+" "+(i+1)+" "+last);
			}
			if(c==0)
				return ;
			for (int i = 1; i <=(n-2); i++)
			{
				for (int j = i+2; j <= (n); j++)
				{
					out.println(i+" "+j+" "+inf);
					c--; 
					if(c==0)
						return ; 
				}
			}


		}

		public static int cnt1(int mat[][])  //how many swaps to be a 1 matrix
		{
			int m = mat.length ; 
			int c=0 ; 
			for (int i = 0; i < mat.length; i++)
			{
				for (int j = 0; j < mat.length; j++)
				{
					int x =  (i*m) +j ;
					if(x%2==0 && mat[i][j]==0)
						c++; 
					if(x%2!=0 && mat[i][j]==1)
						c++; 

				}
			}
			return c;
		}
		public static int cnt0(int mat[][])
		{
			int m = mat.length ; 
			int c=0 ; 
			for (int i = 0; i < mat.length; i++)
			{
				for (int j = 0; j < mat.length; j++)
				{
					int x =  (i*m) +j ; 
					if(x%2!=0 && mat[i][j]==0)
						c++; 
					if(x%2==0 && mat[i][j]==1)
						c++; 

				}
			}
			return c;
		}

		public static boolean canFit2(int x1, int y1 , int x2 , int y2 , int x3 , int y3){
			if(x1==x2)
				if(x1==x3)
					return true ; 
				else
					return false ;
			else
				if(x1==x3)
					return false ; 
				else
				{
					long a = 1l*(y2-y1)*(x3-x2) ; 
					long b = 1l*(y3-y2)*(x2-x1) ; 

					if(a==b)
						return true;
					else 
						return false ;

				}

		}
		public static void shuffle(int c[]){
			if(c.length==1)
				return ; 
			for (int i = 0; i < c.length; i++)
			{
				Random rand = new Random();

				int  n = rand.nextInt(c.length-1) + 0;

				int temp = c[i] ; 
				c[i] = c[n] ; 
				c[n] = temp ;
			}
		}
		public static int binary(ArrayList<Long> arr, int l, int r, long x)   /// begin by 0 and n-1
		{
			if (r>=l)
			{
				int mid = l + (r - l)/2;
				if (arr.get(mid) == x)
					return mid;
				if (arr.get(mid)> x)
					return binary(arr, l, mid-1, x);
				return binary(arr, mid+1, r, x);
			}
			return -1;
		}

		/// searching for the index of first elment greater than x
		public static int binary1(ArrayList<Long> arr , long left) {
			int low = 0, high = arr.size(); // numElems is the size of the array i.e arr.size() 
			while (low != high) {
				int mid = (low + high) / 2; // Or a fancy way to avoid int overflow
				if (arr.get(mid) <= left) {
					/* This index, and everything below it, must not be the first element
					 * greater than what we're looking for because this element is no greater
					 * than the element.
					 */
					low = mid + 1;
				}
				else {
					/* This element is at least as large as the element, so anything after it can't
					 * be the first element that's at least as large.
					 */
					high = mid;
				}
			}
			return low ; // return high ; 
		}


		private static boolean triangle(int a, int b , int c){
			if(a+b>c && a+c>b && b+c>a)
				return true ; 
			else 
				return false ;
		}
		private static boolean segment(int a, int b , int c){
			if(a+b==c || a+c==b && b+c==a)
				return true ; 
			else 
				return false ;
		}
		private static int gcdThing(long a, long b) {
			BigInteger b1 = BigInteger.valueOf(a);
			BigInteger b2 = BigInteger.valueOf(b);
			BigInteger gcd = b1.gcd(b2);
			return gcd.intValue();
		}

		public static boolean is(int i){
			if(Math.log(i)/ Math.log(2) ==(int) (Math.log(i)/ Math.log(2)))
				return true ; 
			if(Math.log(i)/ Math.log(3) ==(int) (Math.log(i)/ Math.log(3)) )
				return true ; 
			if(Math.log(i)/ Math.log(6) ==(int) (Math.log(i)/ Math.log(6)) )
				return true ; 

			return false;

		}
		public static boolean contains(int b[] , int x)
		{
			for (int i = 0; i < b.length; i++)
			{
				if(b[i]==x)
					return true ;
			}
			return false ;
		}
		public static int binary(long []arr , long target , int low , long shift) {
			int high = arr.length; 
			while (low != high) {
				int mid = (low + high) / 2; 
				if (arr[mid]-shift <= target) {
					low = mid + 1;
				}
				else {
					high = mid;
				}
			}
			return low ; // return high ; 
		}
		public static boolean isLetter(char x){
			if(x+0 <=122 && x+0 >=97 )
				return true ;
			else if (x+0 <=90 && x+0 >=65 )
				return true ; 
			else return false; 
		}
		public static long getPrimes(long x ){
			if(x==2 || x==3 || x==1)
				return 2 ;
			if(isPrime(x))
				return 5 ;
			for (int i = 2; i*i<=x; i++)
			{
				if(x%i==0 && isPrime(i))
					return getPrimes(x/i) ;
			}
			return -1;
		}
		public static String solve(String x){

			int n = x.length() ; 
			String y = "" ;
			for (int i = 0; i < n-2; i+=2)
			{
				if(ifPalindrome(x.substring(i, i+2)))
					y+= x.substring(i, i+2) ;
				else 
					break ;
			}
			return y+ solve1(x.substring(y.length(),x.length())) ;

		}
		public static String solve1(String x){
			String y = x.substring(0 , x.length()/2) ; 
			return "" ;

		}
		public static String reverse(String x){
			String y ="" ;
			for (int i = 0; i < x.length(); i++)
			{
				y  = x.charAt(i) + y ;
			}
			return y ;
		}

		public static boolean ifPalindrome(String x){
			int numbers[] = new int[10] ; 
			for (int i = 0; i < x.length(); i++)
			{
				int z = Integer.parseInt(x.charAt(i)+"") ; 
				numbers[z] ++ ;
			}
			for (int i = 0; i < numbers.length; i++)
			{
				if(numbers[i]%2!=0)
					return false; 
			}
			return true ;	
		}

		public static int get(int n){
			return n*(n+1)/2 ; 
		}
		//		public static long getSmallestDivisor( long y){
		//			if(isPrime(y))
		//				return -1;
		//
		//			for (long i = 2; i*i <= y; i++)
		//			{
		//				if(y%i ==0)
		//				{
		//					return i;
		//				}
		//			}
		//			return -1;
		//		}
		//		public static void lis(pair []a , int n){
		//			int lis[] = new int[n] ; 
		//			Arrays.fill(lis,1) ; 
		//
		//			for(int i=1;i<n;i++)
		//				for(int j=0 ; j<i; j++)
		//					if (a[i].y>a[j].y &&  lis[i] < lis[j]+1)   
		//						lis[i] = lis[j] + 1;           
		//
		//			int max = lis[0];
		//
		//			for(int i=1; i<n ; i++)
		//				if (max < lis[i])
		//					max = lis[i] ;
		//			System.out.println(max);
		//
		//			ArrayList<Integer> s = new ArrayList<Integer>() ;
		//			for (int i = n-1; i >=0; i--)
		//			{
		//				if(lis[i]==max)
		//				{
		//					s.add(a[i].z);
		//					max --; 
		//				}
		//			}
		//
		//			for (int i = s.size()-1 ; i>=0 ;  i--)
		//			{
		//				System.out.print(s.get(i)+" ");
		//			}
		//
		//			return  ; 
		//		}
		public static int calcDepth(Vertix node){
			if(node.depth>0) return node.depth; 
			// meaning it has been updated before;
			if(node.parent != null)
				return 1+ calcDepth(node.parent);
			else
				return -1;
		}

		public static boolean isPrime (long num){
			if (num < 2) return false;
			if (num == 2) return true;
			if (num % 2 == 0) return false;
			for (int i = 3; i * i <= num; i += 2)
				if (num % i == 0) return false;
			return true;
		}


		public static int[] getDiv(int n)
		{
			int result[] = new int[7] ; 
			ArrayList<Integer>  f = new ArrayList<Integer>() ; 

			while (n%2==0)
			{
				if(!f.contains(2))f.add(2) ;
				n /= 2;
			}

			// n must be odd at this point.  So we can
			// skip one element (Note i = i +2)
			for (int i = 3; i <= Math.sqrt(n); i+= 2)
			{
				// While i divides n, print i and divide n
				while (n%i == 0)
				{
					if(!f.contains(i))f.add(i);
					n /= i;
				}
			}

			// This condition is to handle the case whien
			// n is a prime number greater than 2
			if (n > 2)
				if(!f.contains(n))f.add(n);

			for (int i = 0, j=0; i < f.size(); i++)
			{
				result[j++]=f.get(i);
			}
			return result ;



		}

		//		public static boolean dfs(Vertix v , int target){
		//			try{
		//				visited[v.i]= true ;
		//			} catch (NullPointerException e)
		//			{
		//				System.out.println(v.i);
		//			}
		//			if(v.i == target)
		//
		//				return true ;
		//			for (int i =0 ; i< v.neighbours.size() ; i++)
		//			{ 
		//
		//				Vertix child = v.neighbours.get(i) ;
		//				if(child.i == target){
		//					found = true  ; 
		//				}
		//				if(visited[child.i]==false){
		//					found |= dfs(child, target) ;
		//				}
		//			}
		//			return found; 
		//		}






	}
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public InputReader(InputStream stream) {
			reader = new BufferedReader(new InputStreamReader(stream), 32768);
			tokenizer = null;
		}

		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

	}
	public static class Vertix{
		long i ; 
		int depth ;
		ArrayList<Vertix> neighbours ; 
		Vertix parent ; 
		Vertix child ; 


		public Vertix(long i){
			this.i = i ;
			this.neighbours = new ArrayList<Vertix> () ;
			this.parent = null ;
			depth =-1;
			this.child = null ;
		}
	}

	public static class pair implements Comparable<pair>{
		int x ;  
		int y ;  




		public pair(int x, int y , int z){
			this.x=x ; 
			this.y=y ;


		}

		@Override
		public int compareTo(pair p) {
			if(this.x > p.x)
				return 1 ; 
			else return -1 ;


		}


	}


}