// Original C++ solution (slower):
#include<iostream>

#include<sstream>

#include<fstream>

#include<cstring>

#include<cmath>

#include<ctime>

#include<cstdio>

#include<cstdlib>

#include<string>

#include<string.h>

#include<math.h>

#include<cassert>

#include<iomanip>

#include<utility>

#include<bitset>

#include<set>

#include<map>

#include<list>

#include<queue>

#include<deque>

#include<stack>

#include<vector>

#include<functional>

#include<algorithm>

//#include<memory.h>

#include<assert.h>

#include<numeric>

#include<limits.h>

using namespace std;

int n;

int a[2005];

bool e[2005][2005];

bool vis[2005];

vector<int>t,res,g[2005],ans[2005];

int gcd(int x,int y){if(x%y)return gcd(y,x%y);else return y;}

void dfs(int x)

{

	if(x==n)

	{

		for(int i=0;i<n;i++)

		{

			if(vis[i])continue;

			g[n].push_back(i);

			t.push_back(i);

			dfs(i);

		}

	}

	vis[x]=1;

	for(int i=0;i<n;i++)if(e[x][i]&&!vis[i])

	{

		g[x].push_back(i);

		t.push_back(i);

		dfs(i);

	}

}

int main()

{

	scanf("%d",&n);

	for(int i=0;i<n;i++)scanf("%d",&a[i]);

	sort(a,a+n);

	for(int i=0;i<n;i++)vis[i]=false;

	for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(gcd(a[i],a[j])!=1)e[i][j]=1;else e[i][j]=0;

	t.push_back(n);

	dfs(n);

	for(int i=n;i>=0;i--)

	{

		int x=t[i];

		for(int j=0;j<g[x].size();j++)

		{

			int y=g[x][j];

			res.clear();

			for(int k1=0,k2=0;k1<ans[x].size()||k2<ans[y].size();)if(k2==ans[y].size()||(k1<ans[x].size()&&ans[x][k1]>ans[y][k2]))res.push_back(ans[x][k1++]);else res.push_back(ans[y][k2++]);

			ans[x]=res;

		}

		ans[x].insert(ans[x].begin(),x);

	}

	for(int i=1;i<=n;i++)

	{

		printf("%d",a[ans[n][i]]);

		if(i==n)puts("");else printf(" ");

	}

	return 0;

}

// Optimized solution to the same problem (faster):
#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <algorithm>

#include <vector>



#define rep(i,x,y) for (int i=x;i<=y;i++)

#define dep(i,y,x) for (int i=y;i>=x;i--)

#define sz(x) (int)(x.size())



using namespace std;



typedef long long LL; 

typedef unsigned long long uLL;



const int maxn=2000+7;



struct Edge{

 int v,next;

} E[maxn*maxn];



int n,m,Esize,p,q,last[maxn],a[maxn],s[maxn];

vector<int> v[maxn],temp;



bool vis[maxn];



int gcd(int x,int y) {return (y==0)?(x):(gcd(y,x%y));}



void addedge(int x,int y)

{

 E[++Esize]=(Edge){y,last[x]},last[x]=Esize;

 E[++Esize]=(Edge){x,last[y]},last[y]=Esize;

 // M[x][y]=M[y][x]=1;

}



void merge(int x,int y)

{

 temp.resize(sz(v[x]));

 rep(i,0,sz(v[x])-1) temp[i]=v[x][i];

 

 p=0,q=0,m=sz(temp)+sz(v[y]),v[x].resize(m);

 rep(i,0,m-1)

 {

  if (p>=sz(temp)) {v[x][i]=v[y][q],++q;continue;}

  if (q>=sz(v[y])) {v[x][i]=temp[p],++p;continue;}



  if (temp[p]>v[y][q]) v[x][i]=temp[p],++p; else v[x][i]=v[y][q],++q;

 }

}



void DFS(int k)

{

 vis[k]=1;

 for (int i=last[k];i;i=E[i].next)

 {

  int nxt=E[i].v;

  if (vis[nxt]) continue;



  DFS(nxt);

  merge(k,nxt);v[nxt].clear();

 }

 

 m=sz(v[k]);

 rep(i,0,m-1) s[i+1]=v[k][i];

 v[k].resize(m+1);

 v[k][0]=a[k];

 rep(i,1,m) v[k][i]=s[i];

}



int main()

{

 scanf("%d",&n);

 rep(i,1,n) scanf("%d",&a[i]);

 

 sort(a+1,a+n+1);

 rep(i,1,n/2) swap(a[i],a[n-i+1]);

 

 rep(i,1,n-1)

  rep(j,i+1,n)

   if (gcd(a[i],a[j])>1) addedge(i,j);

 

 memset(vis,0,sizeof(vis));

 dep(i,n,1)

  if (!vis[i])

  {

   DFS(i);

   merge(0,i);

  }

 

 rep(i,1,n-1) printf("%d ",v[0][i-1]);

 printf("%d\n",v[0][n-1]);



 // system("pause");

 return 0;

}


// Fastest known solution for this problem: