import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.
lang.
Math.
*; import static java.
util.
Arrays.
*;
public class A{
Scanner sc
=new Scanner
(System.
in);
int INF=1<<28;
// input
int width, height, n;
int[] ws0, hs0;
// trial
int[] xs, ys;
int[] ws, hs;
int[] ts, ss;
int[] _;
boolean[] us;
int target;
// best
int[] bestXs, bestYs;
int[] bestWs, bestHs;
boolean[] bestUs;
// parameters
int marginX, marginY;
int maxArea;
final double alpha=2.2;
int[] scales;
int nScales;
int scalesOrder;
final int ascending=1, descending=-1;
int[] dx1, dy1;
int[] dx2, dy2;
Xorshift xorShift;
final long timeLimit=4800;
// debug
boolean debug=false, lock=false, draw=false;
long start;
void run(){
start
=System.
currentTimeMillis();
width=sc.nextInt();
height=sc.nextInt();
n=sc.nextInt();
ws0=new int[n];
hs0=new int[n];
for(int i=0; i<n; i++){
ws0[i]=sc.nextInt();
hs0[i]=sc.nextInt();
}
Answer a=solve();
StringBuilder sb=new StringBuilder();
for(int i=0; i<n; i++){
// if x1=y1=x2=y2=-10
// output "-1.0 -1.0 -1.0 -1.0"
sb.append(a.x1[i]/10);
sb.append('.');
sb.append(a.x1[i]%10);
sb.append(' ');
sb.append(a.y1[i]/10);
sb.append('.');
sb.append(a.y1[i]%10);
sb.append(' ');
sb.append(a.x2[i]/10);
sb.append('.');
sb.append(a.x2[i]%10);
sb.append(' ');
sb.append(a.y2[i]/10);
sb.append('.');
sb.append(a.y2[i]%10);
sb.append('\n');
}
println(sb.toString());
}
void load(Param param){
start
=System.
currentTimeMillis();
width=param.w;
height=param.h;
n=param.n;
ws0=param.ws.clone();
hs0=param.hs.clone();
}
void init(){
width*=10;
height*=10;
for(int i=0; i<n; i++){
ws0[i]*=10;
hs0[i]*=10;
}
xs=new int[n];
ys=new int[n];
ws=new int[n];
hs=new int[n];
ts=new int[n];
ss=new int[n];
_=new int[n];
us=new boolean[n];
bestXs=new int[n];
bestYs=new int[n];
bestWs=new int[n];
bestHs=new int[n];
bestUs=new boolean[n];
xorShift=new Xorshift();
}
Answer solve(){
init();
draw=true;
if(n<=15){
solveSmall();
}else{
solveLarge();
}
return output();
}
void solveSmall(){
int[][] scaless=new int[2][];
scaless[0]=new int[]{20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8,
7, 6, 5, 4, 3, 2, 1};
scaless[1]=new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20};
int[] scalesOrders={descending, ascending};
int nScaless=scaless.length;
dx1=new int[]{0};
dy1=new int[]{0};
dx2=new int[]{0, -1, 0, -1};
dy2=new int[]{0, 0, -1, -1};
int[] maxAreas={width*height/1, width*height/3, width*height/5,
width*height/7, width*height/9};
int nMaxAreas=maxAreas.length;
for(int i=0; i<n; i++){
_[i]=i;
}
int bestSumScore=-INF;
for(int trial=0;; trial++){
maxArea=maxAreas[trial%nMaxAreas];
scales=scaless[(trial/nMaxAreas)%nScaless];
scalesOrder=scalesOrders[(trial/nMaxAreas)%nScaless];
nScales=scales.length;
fill(us, false);
int sumScore=0;
for(int i=0; i<n; i++){
target=i;
sumScore+=step2();
}
if(sumScore>bestSumScore){
bestSumScore=sumScore;
updateBest();
}
shuffleSmall(_);
long end
=System.
currentTimeMillis(); if(end-start>timeLimit){
break;
}
}
}
void solveLarge(){
scales=new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
scalesOrder=ascending;
nScales=scales.length;
dx1=new int[]{0, 0, 0, -1, 1};
dy1=new int[]{0, -1, 1, 0, 0};
dx2=new int[]{0, -1, 0, -1};
dy2=new int[]{0, 0, -1, -1};
int min=min(width, height);
int[] marginXs={min/4, min/5, min/6, width/4, width/5, width/6};
int[] marginYs={min/4, min/5, min/6, height/4, height/5, height/6};
int nMargin=marginXs.length;
maxArea=(int)(alpha*width*height/n);
int bestSumScore=-INF;
for(int trial=0;; trial++){
for(int k=0; k<nMargin; k++){
marginX=marginXs[k];
marginY=marginYs[k];
Pair[] pairs=new Pair[n];
for(int i=0; i<n; i++){
double w=ws0[i];
double h=hs0[i];
// n>25
if(trial>0&&n>25){
w+=xorShift.nextDouble()*width/10;
h+=xorShift.nextDouble()*height/10;
}
pairs[i]=new Pair(i, w/h);
}
sort(pairs);
int index=0;
for(int i=0; i<n/2; i++){
_[index++]=pairs[i].key;
_[index++]=pairs[n-1-i].key;
}
if(n%2==1){
_[index++]=pairs[n/2].key;
}
// n<=25
if(trial>0&&n<=25){
for(int s=0; s<2; s++){
int i=xorShift.nextInt(n);
int j=xorShift.nextInt(n);
int t=_[i];
_[i]=_[j];
_[j]=t;
}
}
fill(us, false);
target=0;
int sumScore;
if(width>height){
sumScore=step1x();
}else{
sumScore=step1y();
}
int from=target;
for(int i=from; i<n; i++){
us[_[i]]=false;
}
for(int i=from; i<n; i++){
target=i;
sumScore+=step2();
long end
=System.
currentTimeMillis(); if(end-start>timeLimit){
return;
}
}
if(sumScore>bestSumScore){
bestSumScore=sumScore;
updateBest();
}
}
}
}
void updateBest(){
System.
arraycopy(xs,
0, bestXs,
0, n
); System.
arraycopy(ys,
0, bestYs,
0, n
); System.
arraycopy(ws,
0, bestWs,
0, n
); System.
arraycopy(hs,
0, bestHs,
0, n
); System.
arraycopy(us,
0, bestUs,
0, n
); }
Answer output(){
int[] x1=new int[n];
int[] y1=new int[n];
int[] x2=new int[n];
int[] y2=new int[n];
// answer.*[i]=*[i]*10
for(int i=0; i<n; i++){
if(bestUs[i]){
x1[i]=bestXs[i];
y1[i]=bestYs[i];
x2[i]=bestXs[i]+bestWs[i];
y2[i]=bestYs[i]+bestHs[i];
}else{
x1[i]=y1[i]=x2[i]=y2[i]=-10;
}
}
return new Answer(x1, y1, x2, y2);
}
int step1x(){
int sumScore=0;
int x=marginX;
int h=height-2*marginY;
for(int i=0; i<n; i++){
target=i;
int s;
if(i%2==0){
s=10*h/hs0[_[i]];
}else{
s=10*h/ws0[_[i]];
}
s=min(s, 20);
s=max(s, 1);
if(i%2==0){
ws[_[i]]=ws0[_[i]]*s/10;
hs[_[i]]=hs0[_[i]]*s/10;
}else{
ws[_[i]]=hs0[_[i]]*s/10;
hs[_[i]]=ws0[_[i]]*s/10;
}
xs[_[i]]=x;
ys[_[i]]=marginY;
ts[_[i]]=i%2;
ss[_[i]]=s;
us[_[i]]=true;
if(ys[_[i]]+hs[_[i]]>height){
ys[_[i]]=0;
if(ys[_[i]]+hs[_[i]]>height){
us[_[i]]=false;
}
}
if(xs[_[i]]+ws[_[i]]>width-marginX){
us[_[i]]=false;
break;
}
x+=ws[_[i]];
if(us[_[i]]){
sumScore+=calcScore();
}
}
return sumScore;
}
int step1y(){
int sumScore=0;
int y=marginY;
int w=width-2*marginX;
for(int i=0; i<n; i++){
target=i;
int s;
if(i%2==0){
s=10*w/hs0[_[i]];
}else{
s=10*w/ws0[_[i]];
}
s=min(s, 20);
s=max(s, 1);
if(i%2==0){
ws[_[i]]=hs0[_[i]]*s/10;
hs[_[i]]=ws0[_[i]]*s/10;
}else{
ws[_[i]]=ws0[_[i]]*s/10;
hs[_[i]]=hs0[_[i]]*s/10;
}
xs[_[i]]=marginX;
ys[_[i]]=y;
ts[_[i]]=(i+1)%2;
ss[_[i]]=s;
us[_[i]]=true;
if(xs[_[i]]+ws[_[i]]>width){
xs[_[i]]=0;
if(xs[_[i]]+ws[_[i]]>width){
us[_[i]]=false;
}
}
if(ys[_[i]]+hs[_[i]]+marginY>height){
us[_[i]]=false;
break;
}
y+=hs[_[i]];
if(us[_[i]]){
sumScore+=calcScore();
}
}
return sumScore;
}
int step2(){
final int e4=10000, e8=100000000;
HashSet<Integer> set=new HashSet<Integer>();
set.add(0);
set.add(width);
set.add(height*e4);
set.add(width+height*e4);
for(int i=0; i<target; i++){
if(!us[_[i]]){
continue;
}
int x=xs[_[i]];
int y=ys[_[i]];
int w=ws[_[i]];
int h=hs[_[i]];
for(int k=0; k<dx1.length; k++){
set.add((x+dx1[k])+(y+dy1[k])*e4);
set.add((x+w+dx1[k])+(y+dy1[k])*e4);
set.add((x+dx1[k])+(y+h+dy1[k])*e4);
set.add((x+w+dx1[k])+(y+h+dy1[k])*e4);
}
}
int index=_[target];
us[index]=false;
ws[index]=min(ws0[index], hs0[index])/10;
hs[index]=min(ws0[index], hs0[index])/10;
ArrayList<Integer> candidate=new ArrayList<Integer>();
for(int p : set){
int x=p%e4;
int y=p/e4;
int bit=0;
for(int i=0; i<dx2.length; i++){
xs[index]=x+dx2[i]*ws[index];
ys[index]=y+dy2[i]*hs[index];
if(check()){
bit|=1<<i;
}
}
if(bit!=0){
candidate.add(p+bit*e8);
}
}
boolean ok=false;
int bestScore=-INF;
int bestX=-1, bestY=-1, bestW=-1, bestH=-1, bestT=-1, bestS=-1;
for(int p : candidate){
int x=p%e4;
int y=p/e4%e4;
int bit=p/e8;
for(int k=0; k<2; k++){
for(int j=0; j<dx2.length; j++){
if((bit>>j&1)==0){
continue;
}
for(int i=0; i<nScales; i++){
if(k==0){
ws[index]=ws0[index]*scales[i]/10;
hs[index]=hs0[index]*scales[i]/10;
}else{
ws[index]=hs0[index]*scales[i]/10;
hs[index]=ws0[index]*scales[i]/10;
}
if(ws[index]*hs[index]>maxArea){
if(scalesOrder==ascending){
break;
}else{
continue;
}
}
xs[index]=x+dx2[j]*ws[index];
ys[index]=y+dy2[j]*hs[index];
ts[index]=k;
ss[index]=scales[i];
if(check()){
int score=calcScore();
ok=true;
if(score>bestScore){
bestScore=score;
bestX=xs[index];
bestY=ys[index];
bestW=ws[index];
bestH=hs[index];
bestT=ts[index];
bestS=ss[index];
}
}else if(scalesOrder==ascending){
break;
}
}
}
}
}
us[index]=false;
if(ok&&(target==0||bestScore>0)){
xs[index]=bestX;
ys[index]=bestY;
ws[index]=bestW;
hs[index]=bestH;
ts[index]=bestT;
ss[index]=bestS;
us[index]=true;
}
return us[index]?bestScore:0;
}
boolean check(){
// determine whether target's position is valid or not
int x=xs[_[target]];
int y=ys[_[target]];
int w=ws[_[target]];
int h=hs[_[target]];
if(x<0||x+w>width||y<0||y+h>height){
return false;
}
for(int i=0; i<target; i++){
if(us[_[i]]&&overlapStrict(xs[_[i]], ws[_[i]], x, w)
&&overlapStrict(ys[_[i]], hs[_[i]], y, h)){
return false;
}
}
return true;
}
int calcScore(){
// assume no rects overlap
int score=0;
int x=xs[_[target]];
int y=ys[_[target]];
int w=ws[_[target]];
int h=hs[_[target]];
int t=ts[_[target]];
for(int i=0; i<target; i++){
if(!us[_[i]]){
continue;
}
int x1=max(xs[_[i]], x);
int x2=min(xs[_[i]]+ws[_[i]], x+w);
int y1=max(ys[_[i]], y);
int y2=min(ys[_[i]]+hs[_[i]], y+h);
if(x1<x2&&y1==y2){
score+=(ts[_[i]]==t?-1:1)*(x2-x1);
}
if(y1<y2&&x1==x2){
score+=(ts[_[i]]==t?-1:1)*(y2-y1);
}
}
return score;
}
int calcScoreAll(){
// assume no rects overlap
int score=0;
for(int i=0; i<n; i++){
if(!us[i]){
continue;
}
for(int j=i+1; j<n; j++){
if(!us[j]){
continue;
}
int x1=max(xs[i], xs[j]);
int x2=min(xs[i]+ws[i], xs[j]+ws[j]);
int y1=max(ys[i], ys[j]);
int y2=min(ys[i]+hs[i], ys[j]+hs[j]);
if(x1<x2&&y1==y2){
score+=(ts[i]==ts[j]?-1:1)*(x2-x1);
}
if(y1<y2&&x1==x2){
score+=(ts[i]==ts[j]?-1:1)*(y2-y1);
}
}
}
return score;
}
boolean overlap(int x1, int w1, int x2, int w2){
return x1<=x2+w2&&x2<=x1+w1;
}
boolean overlapStrict(int x1, int w1, int x2, int w2){
return x1<x2+w2&&x2<x1+w1;
}
void shuffleSmall(int[] is){
for(int i=is.length-1; i>=1; i--){
int j=xorShift.nextInt(i+1);
int t=is[i];
is[i]=is[j];
is[j]=t;
}
}
void shuffleLarge(int[] is, int from){
for(int i=is.length-1; i>=from+1; i--){
int j=xorShift.nextInt(i-from+1)+from;
int t=is[i];
is[i]=is[j];
is[j]=t;
}
}
void lock(){
if(debug){
for(; lock;){
try{
e.printStackTrace();
}
}
lock=true;
}
}
}
}
}
public static void main
(String[] args
){ new A().run();
}
}
class Xorshift{
int x, y, z, w;
public Xorshift(){
x=123456789;
y=362436069;
z=521288629;
w=88675123;
}
public Xorshift(int seed){
x=_(seed, 0);
y=_(x, 1);
z=_(y, 2);
w=_(z, 3);
}
int _(int s, int i){
return 1812433253*(s^(s>>>30))+i+1;
}
// 32bit signed
public int nextInt(){
int t=x^(x<<11);
x=y;
y=z;
z=w;
return w=w^(w>>>19)^t^(t>>>8);
}
// error = O(n*2^-32)
public int nextInt(int n){
return (int)(n*nextDouble());
}
// [0, 1) (53bit)
public double nextDouble(){
int a=nextInt()>>>5, b=nextInt()>>>6;
return (a*67108864.0+b)*(1.0/(1L<<53));
}
}
class Pair implements Comparable<Pair>{
int key;
double value;
Pair(int key, double value){
this.key=key;
this.value=value;
}
@Override
public int compareTo(Pair p){
return Double.
compare(value, p.
value); }
}
class Param{
int w, h, n;
int[] ws, hs;
Param(int w, int h, int n, int[] ws, int[] hs){
this.w=w;
this.h=h;
this.n=n;
this.ws=ws.clone();
this.hs=hs.clone();
}
}
class Answer{
int[] x1, y1, x2, y2;
int n;
Answer(int[] x1, int[] y1, int[] x2, int[] y2){
this.x1=x1.clone();
this.y1=y1.clone();
this.x2=x2.clone();
this.y2=y2.clone();
n=x1.length;
}
}
class Scanner{
eat("");
}
}
try{
return br.readLine();
throw new IOError(e);
}
}
boolean hasNext(){
while(!st.hasMoreTokens()){
if(s==null)
return false;
eat(s);
}
return true;
}
hasNext();
return st.nextToken();
}
int nextInt(){
}
}
aW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5sYW5nLio7CmltcG9ydCBqYXZhLm1hdGguKjsKaW1wb3J0IGphdmEuaW8uKjsKCmltcG9ydCBzdGF0aWMgamF2YS5sYW5nLk1hdGguKjsKaW1wb3J0IHN0YXRpYyBqYXZhLnV0aWwuQXJyYXlzLio7CmltcG9ydCBzdGF0aWMgamF2YS51dGlsLkNvbGxlY3Rpb25zLio7CgpwdWJsaWMgY2xhc3MgQXsKCVNjYW5uZXIgc2M9bmV3IFNjYW5uZXIoU3lzdGVtLmluKTsKCglpbnQgSU5GPTE8PDI4OwoKCS8vIGlucHV0CglpbnQgd2lkdGgsIGhlaWdodCwgbjsKCWludFtdIHdzMCwgaHMwOwoKCS8vIHRyaWFsCglpbnRbXSB4cywgeXM7CglpbnRbXSB3cywgaHM7CglpbnRbXSB0cywgc3M7CglpbnRbXSBfOwoJYm9vbGVhbltdIHVzOwoKCWludCB0YXJnZXQ7CgoJLy8gYmVzdAoJaW50W10gYmVzdFhzLCBiZXN0WXM7CglpbnRbXSBiZXN0V3MsIGJlc3RIczsKCWJvb2xlYW5bXSBiZXN0VXM7CgoJLy8gcGFyYW1ldGVycwoJaW50IG1hcmdpblgsIG1hcmdpblk7CglpbnQgbWF4QXJlYTsKCWZpbmFsIGRvdWJsZSBhbHBoYT0yLjI7CgoJaW50W10gc2NhbGVzOwoJaW50IG5TY2FsZXM7CglpbnQgc2NhbGVzT3JkZXI7CglmaW5hbCBpbnQgYXNjZW5kaW5nPTEsIGRlc2NlbmRpbmc9LTE7CgoJaW50W10gZHgxLCBkeTE7CglpbnRbXSBkeDIsIGR5MjsKCglYb3JzaGlmdCB4b3JTaGlmdDsKCglmaW5hbCBsb25nIHRpbWVMaW1pdD00ODAwOwoKCS8vIGRlYnVnCglib29sZWFuIGRlYnVnPWZhbHNlLCBsb2NrPWZhbHNlLCBkcmF3PWZhbHNlOwoKCWxvbmcgc3RhcnQ7CgoJdm9pZCBydW4oKXsKCQlzdGFydD1TeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCgkJd2lkdGg9c2MubmV4dEludCgpOwoJCWhlaWdodD1zYy5uZXh0SW50KCk7CgkJbj1zYy5uZXh0SW50KCk7CgkJd3MwPW5ldyBpbnRbbl07CgkJaHMwPW5ldyBpbnRbbl07CgkJZm9yKGludCBpPTA7IGk8bjsgaSsrKXsKCQkJd3MwW2ldPXNjLm5leHRJbnQoKTsKCQkJaHMwW2ldPXNjLm5leHRJbnQoKTsKCQl9CgkJQW5zd2VyIGE9c29sdmUoKTsKCQlTdHJpbmdCdWlsZGVyIHNiPW5ldyBTdHJpbmdCdWlsZGVyKCk7CgkJZm9yKGludCBpPTA7IGk8bjsgaSsrKXsKCQkJLy8gaWYgeDE9eTE9eDI9eTI9LTEwCgkJCS8vIG91dHB1dCAiLTEuMCAtMS4wIC0xLjAgLTEuMCIKCQkJc2IuYXBwZW5kKGEueDFbaV0vMTApOwoJCQlzYi5hcHBlbmQoJy4nKTsKCQkJc2IuYXBwZW5kKGEueDFbaV0lMTApOwoJCQlzYi5hcHBlbmQoJyAnKTsKCQkJc2IuYXBwZW5kKGEueTFbaV0vMTApOwoJCQlzYi5hcHBlbmQoJy4nKTsKCQkJc2IuYXBwZW5kKGEueTFbaV0lMTApOwoJCQlzYi5hcHBlbmQoJyAnKTsKCQkJc2IuYXBwZW5kKGEueDJbaV0vMTApOwoJCQlzYi5hcHBlbmQoJy4nKTsKCQkJc2IuYXBwZW5kKGEueDJbaV0lMTApOwoJCQlzYi5hcHBlbmQoJyAnKTsKCQkJc2IuYXBwZW5kKGEueTJbaV0vMTApOwoJCQlzYi5hcHBlbmQoJy4nKTsKCQkJc2IuYXBwZW5kKGEueTJbaV0lMTApOwoJCQlzYi5hcHBlbmQoJ1xuJyk7CgkJfQoJCXByaW50bG4oc2IudG9TdHJpbmcoKSk7Cgl9CgoJdm9pZCBsb2FkKFBhcmFtIHBhcmFtKXsKCQlzdGFydD1TeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCgkJd2lkdGg9cGFyYW0udzsKCQloZWlnaHQ9cGFyYW0uaDsKCQluPXBhcmFtLm47CgkJd3MwPXBhcmFtLndzLmNsb25lKCk7CgkJaHMwPXBhcmFtLmhzLmNsb25lKCk7Cgl9CgoJdm9pZCBpbml0KCl7CgkJd2lkdGgqPTEwOwoJCWhlaWdodCo9MTA7CgoJCWZvcihpbnQgaT0wOyBpPG47IGkrKyl7CgkJCXdzMFtpXSo9MTA7CgkJCWhzMFtpXSo9MTA7CgkJfQoKCQl4cz1uZXcgaW50W25dOwoJCXlzPW5ldyBpbnRbbl07CgkJd3M9bmV3IGludFtuXTsKCQlocz1uZXcgaW50W25dOwoJCXRzPW5ldyBpbnRbbl07CgkJc3M9bmV3IGludFtuXTsKCQlfPW5ldyBpbnRbbl07CgkJdXM9bmV3IGJvb2xlYW5bbl07CgoJCWJlc3RYcz1uZXcgaW50W25dOwoJCWJlc3RZcz1uZXcgaW50W25dOwoJCWJlc3RXcz1uZXcgaW50W25dOwoJCWJlc3RIcz1uZXcgaW50W25dOwoJCWJlc3RVcz1uZXcgYm9vbGVhbltuXTsKCgkJeG9yU2hpZnQ9bmV3IFhvcnNoaWZ0KCk7Cgl9CgoJQW5zd2VyIHNvbHZlKCl7CgkJaW5pdCgpOwoJCWRyYXc9dHJ1ZTsKCQlpZihuPD0xNSl7CgkJCXNvbHZlU21hbGwoKTsKCQl9ZWxzZXsKCQkJc29sdmVMYXJnZSgpOwoJCX0KCQlyZXR1cm4gb3V0cHV0KCk7Cgl9CgoJdm9pZCBzb2x2ZVNtYWxsKCl7CgkJaW50W11bXSBzY2FsZXNzPW5ldyBpbnRbMl1bXTsKCQlzY2FsZXNzWzBdPW5ldyBpbnRbXXsyMCwgMTksIDE4LCAxNywgMTYsIDE1LCAxNCwgMTMsIDEyLCAxMSwgMTAsIDksIDgsCgkJCQk3LCA2LCA1LCA0LCAzLCAyLCAxfTsKCQlzY2FsZXNzWzFdPW5ldyBpbnRbXXsxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LAoJCQkJMTYsIDE3LCAxOCwgMTksIDIwfTsKCQlpbnRbXSBzY2FsZXNPcmRlcnM9e2Rlc2NlbmRpbmcsIGFzY2VuZGluZ307CgkJaW50IG5TY2FsZXNzPXNjYWxlc3MubGVuZ3RoOwoKCQlkeDE9bmV3IGludFtdezB9OwoJCWR5MT1uZXcgaW50W117MH07CgkJZHgyPW5ldyBpbnRbXXswLCAtMSwgMCwgLTF9OwoJCWR5Mj1uZXcgaW50W117MCwgMCwgLTEsIC0xfTsKCgkJaW50W10gbWF4QXJlYXM9e3dpZHRoKmhlaWdodC8xLCB3aWR0aCpoZWlnaHQvMywgd2lkdGgqaGVpZ2h0LzUsCgkJCQl3aWR0aCpoZWlnaHQvNywgd2lkdGgqaGVpZ2h0Lzl9OwoJCWludCBuTWF4QXJlYXM9bWF4QXJlYXMubGVuZ3RoOwoKCQlmb3IoaW50IGk9MDsgaTxuOyBpKyspewoJCQlfW2ldPWk7CgkJfQoKCQlpbnQgYmVzdFN1bVNjb3JlPS1JTkY7CgkJZm9yKGludCB0cmlhbD0wOzsgdHJpYWwrKyl7CgkJCW1heEFyZWE9bWF4QXJlYXNbdHJpYWwlbk1heEFyZWFzXTsKCQkJc2NhbGVzPXNjYWxlc3NbKHRyaWFsL25NYXhBcmVhcyklblNjYWxlc3NdOwoJCQlzY2FsZXNPcmRlcj1zY2FsZXNPcmRlcnNbKHRyaWFsL25NYXhBcmVhcyklblNjYWxlc3NdOwoJCQluU2NhbGVzPXNjYWxlcy5sZW5ndGg7CgoJCQlmaWxsKHVzLCBmYWxzZSk7CgoJCQlpbnQgc3VtU2NvcmU9MDsKCQkJZm9yKGludCBpPTA7IGk8bjsgaSsrKXsKCQkJCXRhcmdldD1pOwoJCQkJc3VtU2NvcmUrPXN0ZXAyKCk7CgkJCX0KCgkJCWlmKHN1bVNjb3JlPmJlc3RTdW1TY29yZSl7CgkJCQliZXN0U3VtU2NvcmU9c3VtU2NvcmU7CgkJCQl1cGRhdGVCZXN0KCk7CgkJCX0KCgkJCXNodWZmbGVTbWFsbChfKTsKCgkJCWxvbmcgZW5kPVN5c3RlbS5jdXJyZW50VGltZU1pbGxpcygpOwoJCQlpZihlbmQtc3RhcnQ+dGltZUxpbWl0KXsKCQkJCWJyZWFrOwoJCQl9CgkJfQoJfQoKCXZvaWQgc29sdmVMYXJnZSgpewoJCXNjYWxlcz1uZXcgaW50W117MSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTB9OwoJCXNjYWxlc09yZGVyPWFzY2VuZGluZzsKCQluU2NhbGVzPXNjYWxlcy5sZW5ndGg7CgoJCWR4MT1uZXcgaW50W117MCwgMCwgMCwgLTEsIDF9OwoJCWR5MT1uZXcgaW50W117MCwgLTEsIDEsIDAsIDB9OwoJCWR4Mj1uZXcgaW50W117MCwgLTEsIDAsIC0xfTsKCQlkeTI9bmV3IGludFtdezAsIDAsIC0xLCAtMX07CgoJCWludCBtaW49bWluKHdpZHRoLCBoZWlnaHQpOwoJCWludFtdIG1hcmdpblhzPXttaW4vNCwgbWluLzUsIG1pbi82LCB3aWR0aC80LCB3aWR0aC81LCB3aWR0aC82fTsKCQlpbnRbXSBtYXJnaW5Zcz17bWluLzQsIG1pbi81LCBtaW4vNiwgaGVpZ2h0LzQsIGhlaWdodC81LCBoZWlnaHQvNn07CgkJaW50IG5NYXJnaW49bWFyZ2luWHMubGVuZ3RoOwoKCQltYXhBcmVhPShpbnQpKGFscGhhKndpZHRoKmhlaWdodC9uKTsKCgkJaW50IGJlc3RTdW1TY29yZT0tSU5GOwoJCWZvcihpbnQgdHJpYWw9MDs7IHRyaWFsKyspewoJCQlmb3IoaW50IGs9MDsgazxuTWFyZ2luOyBrKyspewoJCQkJbWFyZ2luWD1tYXJnaW5Yc1trXTsKCQkJCW1hcmdpblk9bWFyZ2luWXNba107CgoJCQkJUGFpcltdIHBhaXJzPW5ldyBQYWlyW25dOwoJCQkJZm9yKGludCBpPTA7IGk8bjsgaSsrKXsKCQkJCQlkb3VibGUgdz13czBbaV07CgkJCQkJZG91YmxlIGg9aHMwW2ldOwoJCQkJCS8vIG4+MjUKCQkJCQlpZih0cmlhbD4wJiZuPjI1KXsKCQkJCQkJdys9eG9yU2hpZnQubmV4dERvdWJsZSgpKndpZHRoLzEwOwoJCQkJCQloKz14b3JTaGlmdC5uZXh0RG91YmxlKCkqaGVpZ2h0LzEwOwoJCQkJCX0KCQkJCQlwYWlyc1tpXT1uZXcgUGFpcihpLCB3L2gpOwoJCQkJfQoJCQkJc29ydChwYWlycyk7CgkJCQlpbnQgaW5kZXg9MDsKCQkJCWZvcihpbnQgaT0wOyBpPG4vMjsgaSsrKXsKCQkJCQlfW2luZGV4KytdPXBhaXJzW2ldLmtleTsKCQkJCQlfW2luZGV4KytdPXBhaXJzW24tMS1pXS5rZXk7CgkJCQl9CgkJCQlpZihuJTI9PTEpewoJCQkJCV9baW5kZXgrK109cGFpcnNbbi8yXS5rZXk7CgkJCQl9CgoJCQkJLy8gbjw9MjUKCQkJCWlmKHRyaWFsPjAmJm48PTI1KXsKCQkJCQlmb3IoaW50IHM9MDsgczwyOyBzKyspewoJCQkJCQlpbnQgaT14b3JTaGlmdC5uZXh0SW50KG4pOwoJCQkJCQlpbnQgaj14b3JTaGlmdC5uZXh0SW50KG4pOwoJCQkJCQlpbnQgdD1fW2ldOwoJCQkJCQlfW2ldPV9bal07CgkJCQkJCV9bal09dDsKCQkJCQl9CgkJCQl9CgoJCQkJZmlsbCh1cywgZmFsc2UpOwoJCQkJdGFyZ2V0PTA7CgoJCQkJaW50IHN1bVNjb3JlOwoJCQkJaWYod2lkdGg+aGVpZ2h0KXsKCQkJCQlzdW1TY29yZT1zdGVwMXgoKTsKCQkJCX1lbHNlewoJCQkJCXN1bVNjb3JlPXN0ZXAxeSgpOwoJCQkJfQoJCQkJaW50IGZyb209dGFyZ2V0OwoKCQkJCWZvcihpbnQgaT1mcm9tOyBpPG47IGkrKyl7CgkJCQkJdXNbX1tpXV09ZmFsc2U7CgkJCQl9CgoJCQkJZm9yKGludCBpPWZyb207IGk8bjsgaSsrKXsKCQkJCQl0YXJnZXQ9aTsKCQkJCQlzdW1TY29yZSs9c3RlcDIoKTsKCQkJCQlsb25nIGVuZD1TeXN0ZW0uY3VycmVudFRpbWVNaWxsaXMoKTsKCQkJCQlpZihlbmQtc3RhcnQ+dGltZUxpbWl0KXsKCQkJCQkJcmV0dXJuOwoJCQkJCX0KCQkJCX0KCgkJCQlpZihzdW1TY29yZT5iZXN0U3VtU2NvcmUpewoJCQkJCWJlc3RTdW1TY29yZT1zdW1TY29yZTsKCQkJCQl1cGRhdGVCZXN0KCk7CgkJCQl9CgkJCX0KCQl9Cgl9CgoJdm9pZCB1cGRhdGVCZXN0KCl7CgkJU3lzdGVtLmFycmF5Y29weSh4cywgMCwgYmVzdFhzLCAwLCBuKTsKCQlTeXN0ZW0uYXJyYXljb3B5KHlzLCAwLCBiZXN0WXMsIDAsIG4pOwoJCVN5c3RlbS5hcnJheWNvcHkod3MsIDAsIGJlc3RXcywgMCwgbik7CgkJU3lzdGVtLmFycmF5Y29weShocywgMCwgYmVzdEhzLCAwLCBuKTsKCQlTeXN0ZW0uYXJyYXljb3B5KHVzLCAwLCBiZXN0VXMsIDAsIG4pOwoJfQoKCUFuc3dlciBvdXRwdXQoKXsKCQlpbnRbXSB4MT1uZXcgaW50W25dOwoJCWludFtdIHkxPW5ldyBpbnRbbl07CgkJaW50W10geDI9bmV3IGludFtuXTsKCQlpbnRbXSB5Mj1uZXcgaW50W25dOwoKCQkvLyBhbnN3ZXIuKltpXT0qW2ldKjEwCgkJZm9yKGludCBpPTA7IGk8bjsgaSsrKXsKCQkJaWYoYmVzdFVzW2ldKXsKCQkJCXgxW2ldPWJlc3RYc1tpXTsKCQkJCXkxW2ldPWJlc3RZc1tpXTsKCQkJCXgyW2ldPWJlc3RYc1tpXStiZXN0V3NbaV07CgkJCQl5MltpXT1iZXN0WXNbaV0rYmVzdEhzW2ldOwoJCQl9ZWxzZXsKCQkJCXgxW2ldPXkxW2ldPXgyW2ldPXkyW2ldPS0xMDsKCQkJfQoJCX0KCQlyZXR1cm4gbmV3IEFuc3dlcih4MSwgeTEsIHgyLCB5Mik7Cgl9CgoJaW50IHN0ZXAxeCgpewoJCWludCBzdW1TY29yZT0wOwoJCWludCB4PW1hcmdpblg7CgkJaW50IGg9aGVpZ2h0LTIqbWFyZ2luWTsKCQlmb3IoaW50IGk9MDsgaTxuOyBpKyspewoJCQl0YXJnZXQ9aTsKCQkJaW50IHM7CgkJCWlmKGklMj09MCl7CgkJCQlzPTEwKmgvaHMwW19baV1dOwoJCQl9ZWxzZXsKCQkJCXM9MTAqaC93czBbX1tpXV07CgkJCX0KCQkJcz1taW4ocywgMjApOwoJCQlzPW1heChzLCAxKTsKCQkJaWYoaSUyPT0wKXsKCQkJCXdzW19baV1dPXdzMFtfW2ldXSpzLzEwOwoJCQkJaHNbX1tpXV09aHMwW19baV1dKnMvMTA7CgkJCX1lbHNlewoJCQkJd3NbX1tpXV09aHMwW19baV1dKnMvMTA7CgkJCQloc1tfW2ldXT13czBbX1tpXV0qcy8xMDsKCQkJfQoJCQl4c1tfW2ldXT14OwoJCQl5c1tfW2ldXT1tYXJnaW5ZOwoJCQl0c1tfW2ldXT1pJTI7CgkJCXNzW19baV1dPXM7CgkJCXVzW19baV1dPXRydWU7CgkJCWlmKHlzW19baV1dK2hzW19baV1dPmhlaWdodCl7CgkJCQl5c1tfW2ldXT0wOwoJCQkJaWYoeXNbX1tpXV0raHNbX1tpXV0+aGVpZ2h0KXsKCQkJCQl1c1tfW2ldXT1mYWxzZTsKCQkJCX0KCQkJfQoJCQlpZih4c1tfW2ldXSt3c1tfW2ldXT53aWR0aC1tYXJnaW5YKXsKCQkJCXVzW19baV1dPWZhbHNlOwoJCQkJYnJlYWs7CgkJCX0KCQkJeCs9d3NbX1tpXV07CgkJCWlmKHVzW19baV1dKXsKCQkJCXN1bVNjb3JlKz1jYWxjU2NvcmUoKTsKCQkJfQoJCX0KCQlyZXR1cm4gc3VtU2NvcmU7Cgl9CgoJaW50IHN0ZXAxeSgpewoJCWludCBzdW1TY29yZT0wOwoJCWludCB5PW1hcmdpblk7CgkJaW50IHc9d2lkdGgtMiptYXJnaW5YOwoJCWZvcihpbnQgaT0wOyBpPG47IGkrKyl7CgkJCXRhcmdldD1pOwoJCQlpbnQgczsKCQkJaWYoaSUyPT0wKXsKCQkJCXM9MTAqdy9oczBbX1tpXV07CgkJCX1lbHNlewoJCQkJcz0xMCp3L3dzMFtfW2ldXTsKCQkJfQoJCQlzPW1pbihzLCAyMCk7CgkJCXM9bWF4KHMsIDEpOwoJCQlpZihpJTI9PTApewoJCQkJd3NbX1tpXV09aHMwW19baV1dKnMvMTA7CgkJCQloc1tfW2ldXT13czBbX1tpXV0qcy8xMDsKCQkJfWVsc2V7CgkJCQl3c1tfW2ldXT13czBbX1tpXV0qcy8xMDsKCQkJCWhzW19baV1dPWhzMFtfW2ldXSpzLzEwOwoJCQl9CgkJCXhzW19baV1dPW1hcmdpblg7CgkJCXlzW19baV1dPXk7CgkJCXRzW19baV1dPShpKzEpJTI7CgkJCXNzW19baV1dPXM7CgkJCXVzW19baV1dPXRydWU7CgkJCWlmKHhzW19baV1dK3dzW19baV1dPndpZHRoKXsKCQkJCXhzW19baV1dPTA7CgkJCQlpZih4c1tfW2ldXSt3c1tfW2ldXT53aWR0aCl7CgkJCQkJdXNbX1tpXV09ZmFsc2U7CgkJCQl9CgkJCX0KCQkJaWYoeXNbX1tpXV0raHNbX1tpXV0rbWFyZ2luWT5oZWlnaHQpewoJCQkJdXNbX1tpXV09ZmFsc2U7CgkJCQlicmVhazsKCQkJfQoJCQl5Kz1oc1tfW2ldXTsKCQkJaWYodXNbX1tpXV0pewoJCQkJc3VtU2NvcmUrPWNhbGNTY29yZSgpOwoJCQl9CgkJfQoJCXJldHVybiBzdW1TY29yZTsKCX0KCglpbnQgc3RlcDIoKXsKCQlmaW5hbCBpbnQgZTQ9MTAwMDAsIGU4PTEwMDAwMDAwMDsKCgkJSGFzaFNldDxJbnRlZ2VyPiBzZXQ9bmV3IEhhc2hTZXQ8SW50ZWdlcj4oKTsKCQlzZXQuYWRkKDApOwoJCXNldC5hZGQod2lkdGgpOwoJCXNldC5hZGQoaGVpZ2h0KmU0KTsKCQlzZXQuYWRkKHdpZHRoK2hlaWdodCplNCk7CgkJZm9yKGludCBpPTA7IGk8dGFyZ2V0OyBpKyspewoJCQlpZighdXNbX1tpXV0pewoJCQkJY29udGludWU7CgkJCX0KCQkJaW50IHg9eHNbX1tpXV07CgkJCWludCB5PXlzW19baV1dOwoJCQlpbnQgdz13c1tfW2ldXTsKCQkJaW50IGg9aHNbX1tpXV07CgkJCWZvcihpbnQgaz0wOyBrPGR4MS5sZW5ndGg7IGsrKyl7CgkJCQlzZXQuYWRkKCh4K2R4MVtrXSkrKHkrZHkxW2tdKSplNCk7CgkJCQlzZXQuYWRkKCh4K3crZHgxW2tdKSsoeStkeTFba10pKmU0KTsKCQkJCXNldC5hZGQoKHgrZHgxW2tdKSsoeStoK2R5MVtrXSkqZTQpOwoJCQkJc2V0LmFkZCgoeCt3K2R4MVtrXSkrKHkraCtkeTFba10pKmU0KTsKCQkJfQoJCX0KCgkJaW50IGluZGV4PV9bdGFyZ2V0XTsKCQl1c1tpbmRleF09ZmFsc2U7CgoJCXdzW2luZGV4XT1taW4od3MwW2luZGV4XSwgaHMwW2luZGV4XSkvMTA7CgkJaHNbaW5kZXhdPW1pbih3czBbaW5kZXhdLCBoczBbaW5kZXhdKS8xMDsKCgkJQXJyYXlMaXN0PEludGVnZXI+IGNhbmRpZGF0ZT1uZXcgQXJyYXlMaXN0PEludGVnZXI+KCk7CgkJZm9yKGludCBwIDogc2V0KXsKCQkJaW50IHg9cCVlNDsKCQkJaW50IHk9cC9lNDsKCQkJaW50IGJpdD0wOwoJCQlmb3IoaW50IGk9MDsgaTxkeDIubGVuZ3RoOyBpKyspewoJCQkJeHNbaW5kZXhdPXgrZHgyW2ldKndzW2luZGV4XTsKCQkJCXlzW2luZGV4XT15K2R5MltpXSpoc1tpbmRleF07CgkJCQlpZihjaGVjaygpKXsKCQkJCQliaXR8PTE8PGk7CgkJCQl9CgkJCX0KCQkJaWYoYml0IT0wKXsKCQkJCWNhbmRpZGF0ZS5hZGQocCtiaXQqZTgpOwoJCQl9CgkJfQoKCQlib29sZWFuIG9rPWZhbHNlOwoJCWludCBiZXN0U2NvcmU9LUlORjsKCQlpbnQgYmVzdFg9LTEsIGJlc3RZPS0xLCBiZXN0Vz0tMSwgYmVzdEg9LTEsIGJlc3RUPS0xLCBiZXN0Uz0tMTsKCgkJZm9yKGludCBwIDogY2FuZGlkYXRlKXsKCQkJaW50IHg9cCVlNDsKCQkJaW50IHk9cC9lNCVlNDsKCQkJaW50IGJpdD1wL2U4OwoJCQlmb3IoaW50IGs9MDsgazwyOyBrKyspewoJCQkJZm9yKGludCBqPTA7IGo8ZHgyLmxlbmd0aDsgaisrKXsKCQkJCQlpZigoYml0Pj5qJjEpPT0wKXsKCQkJCQkJY29udGludWU7CgkJCQkJfQoJCQkJCWZvcihpbnQgaT0wOyBpPG5TY2FsZXM7IGkrKyl7CgkJCQkJCWlmKGs9PTApewoJCQkJCQkJd3NbaW5kZXhdPXdzMFtpbmRleF0qc2NhbGVzW2ldLzEwOwoJCQkJCQkJaHNbaW5kZXhdPWhzMFtpbmRleF0qc2NhbGVzW2ldLzEwOwoJCQkJCQl9ZWxzZXsKCQkJCQkJCXdzW2luZGV4XT1oczBbaW5kZXhdKnNjYWxlc1tpXS8xMDsKCQkJCQkJCWhzW2luZGV4XT13czBbaW5kZXhdKnNjYWxlc1tpXS8xMDsKCQkJCQkJfQoJCQkJCQlpZih3c1tpbmRleF0qaHNbaW5kZXhdPm1heEFyZWEpewoJCQkJCQkJaWYoc2NhbGVzT3JkZXI9PWFzY2VuZGluZyl7CgkJCQkJCQkJYnJlYWs7CgkJCQkJCQl9ZWxzZXsKCQkJCQkJCQljb250aW51ZTsKCQkJCQkJCX0KCQkJCQkJfQoKCQkJCQkJeHNbaW5kZXhdPXgrZHgyW2pdKndzW2luZGV4XTsKCQkJCQkJeXNbaW5kZXhdPXkrZHkyW2pdKmhzW2luZGV4XTsKCQkJCQkJdHNbaW5kZXhdPWs7CgkJCQkJCXNzW2luZGV4XT1zY2FsZXNbaV07CgoJCQkJCQlpZihjaGVjaygpKXsKCQkJCQkJCWludCBzY29yZT1jYWxjU2NvcmUoKTsKCQkJCQkJCW9rPXRydWU7CgkJCQkJCQlpZihzY29yZT5iZXN0U2NvcmUpewoJCQkJCQkJCWJlc3RTY29yZT1zY29yZTsKCQkJCQkJCQliZXN0WD14c1tpbmRleF07CgkJCQkJCQkJYmVzdFk9eXNbaW5kZXhdOwoJCQkJCQkJCWJlc3RXPXdzW2luZGV4XTsKCQkJCQkJCQliZXN0SD1oc1tpbmRleF07CgkJCQkJCQkJYmVzdFQ9dHNbaW5kZXhdOwoJCQkJCQkJCWJlc3RTPXNzW2luZGV4XTsKCQkJCQkJCX0KCQkJCQkJfWVsc2UgaWYoc2NhbGVzT3JkZXI9PWFzY2VuZGluZyl7CgkJCQkJCQlicmVhazsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCgkJdXNbaW5kZXhdPWZhbHNlOwoJCWlmKG9rJiYodGFyZ2V0PT0wfHxiZXN0U2NvcmU+MCkpewoJCQl4c1tpbmRleF09YmVzdFg7CgkJCXlzW2luZGV4XT1iZXN0WTsKCQkJd3NbaW5kZXhdPWJlc3RXOwoJCQloc1tpbmRleF09YmVzdEg7CgkJCXRzW2luZGV4XT1iZXN0VDsKCQkJc3NbaW5kZXhdPWJlc3RTOwoJCQl1c1tpbmRleF09dHJ1ZTsKCQl9CgoJCXJldHVybiB1c1tpbmRleF0/YmVzdFNjb3JlOjA7Cgl9CgoJYm9vbGVhbiBjaGVjaygpewoJCS8vIGRldGVybWluZSB3aGV0aGVyIHRhcmdldCdzIHBvc2l0aW9uIGlzIHZhbGlkIG9yIG5vdAoJCWludCB4PXhzW19bdGFyZ2V0XV07CgkJaW50IHk9eXNbX1t0YXJnZXRdXTsKCQlpbnQgdz13c1tfW3RhcmdldF1dOwoJCWludCBoPWhzW19bdGFyZ2V0XV07CgkJaWYoeDwwfHx4K3c+d2lkdGh8fHk8MHx8eStoPmhlaWdodCl7CgkJCXJldHVybiBmYWxzZTsKCQl9CgkJZm9yKGludCBpPTA7IGk8dGFyZ2V0OyBpKyspewoJCQlpZih1c1tfW2ldXSYmb3ZlcmxhcFN0cmljdCh4c1tfW2ldXSwgd3NbX1tpXV0sIHgsIHcpCgkJCQkJJiZvdmVybGFwU3RyaWN0KHlzW19baV1dLCBoc1tfW2ldXSwgeSwgaCkpewoJCQkJcmV0dXJuIGZhbHNlOwoJCQl9CgkJfQoJCXJldHVybiB0cnVlOwoJfQoKCWludCBjYWxjU2NvcmUoKXsKCQkvLyBhc3N1bWUgbm8gcmVjdHMgb3ZlcmxhcAoJCWludCBzY29yZT0wOwoJCWludCB4PXhzW19bdGFyZ2V0XV07CgkJaW50IHk9eXNbX1t0YXJnZXRdXTsKCQlpbnQgdz13c1tfW3RhcmdldF1dOwoJCWludCBoPWhzW19bdGFyZ2V0XV07CgkJaW50IHQ9dHNbX1t0YXJnZXRdXTsKCQlmb3IoaW50IGk9MDsgaTx0YXJnZXQ7IGkrKyl7CgkJCWlmKCF1c1tfW2ldXSl7CgkJCQljb250aW51ZTsKCQkJfQoJCQlpbnQgeDE9bWF4KHhzW19baV1dLCB4KTsKCQkJaW50IHgyPW1pbih4c1tfW2ldXSt3c1tfW2ldXSwgeCt3KTsKCgkJCWludCB5MT1tYXgoeXNbX1tpXV0sIHkpOwoJCQlpbnQgeTI9bWluKHlzW19baV1dK2hzW19baV1dLCB5K2gpOwoKCQkJaWYoeDE8eDImJnkxPT15Mil7CgkJCQlzY29yZSs9KHRzW19baV1dPT10Py0xOjEpKih4Mi14MSk7CgkJCX0KCQkJaWYoeTE8eTImJngxPT14Mil7CgkJCQlzY29yZSs9KHRzW19baV1dPT10Py0xOjEpKih5Mi15MSk7CgkJCX0KCQl9CgkJcmV0dXJuIHNjb3JlOwoJfQoKCWludCBjYWxjU2NvcmVBbGwoKXsKCQkvLyBhc3N1bWUgbm8gcmVjdHMgb3ZlcmxhcAoJCWludCBzY29yZT0wOwoJCWZvcihpbnQgaT0wOyBpPG47IGkrKyl7CgkJCWlmKCF1c1tpXSl7CgkJCQljb250aW51ZTsKCQkJfQoJCQlmb3IoaW50IGo9aSsxOyBqPG47IGorKyl7CgkJCQlpZighdXNbal0pewoJCQkJCWNvbnRpbnVlOwoJCQkJfQoJCQkJaW50IHgxPW1heCh4c1tpXSwgeHNbal0pOwoJCQkJaW50IHgyPW1pbih4c1tpXSt3c1tpXSwgeHNbal0rd3Nbal0pOwoKCQkJCWludCB5MT1tYXgoeXNbaV0sIHlzW2pdKTsKCQkJCWludCB5Mj1taW4oeXNbaV0raHNbaV0sIHlzW2pdK2hzW2pdKTsKCgkJCQlpZih4MTx4MiYmeTE9PXkyKXsKCQkJCQlzY29yZSs9KHRzW2ldPT10c1tqXT8tMToxKSooeDIteDEpOwoJCQkJfQoJCQkJaWYoeTE8eTImJngxPT14Mil7CgkJCQkJc2NvcmUrPSh0c1tpXT09dHNbal0/LTE6MSkqKHkyLXkxKTsKCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gc2NvcmU7Cgl9CgoJYm9vbGVhbiBvdmVybGFwKGludCB4MSwgaW50IHcxLCBpbnQgeDIsIGludCB3Mil7CgkJcmV0dXJuIHgxPD14Mit3MiYmeDI8PXgxK3cxOwoJfQoKCWJvb2xlYW4gb3ZlcmxhcFN0cmljdChpbnQgeDEsIGludCB3MSwgaW50IHgyLCBpbnQgdzIpewoJCXJldHVybiB4MTx4Mit3MiYmeDI8eDErdzE7Cgl9CgoJdm9pZCBzaHVmZmxlU21hbGwoaW50W10gaXMpewoJCWZvcihpbnQgaT1pcy5sZW5ndGgtMTsgaT49MTsgaS0tKXsKCQkJaW50IGo9eG9yU2hpZnQubmV4dEludChpKzEpOwoJCQlpbnQgdD1pc1tpXTsKCQkJaXNbaV09aXNbal07CgkJCWlzW2pdPXQ7CgkJfQoJfQoKCXZvaWQgc2h1ZmZsZUxhcmdlKGludFtdIGlzLCBpbnQgZnJvbSl7CgkJZm9yKGludCBpPWlzLmxlbmd0aC0xOyBpPj1mcm9tKzE7IGktLSl7CgkJCWludCBqPXhvclNoaWZ0Lm5leHRJbnQoaS1mcm9tKzEpK2Zyb207CgkJCWludCB0PWlzW2ldOwoJCQlpc1tpXT1pc1tqXTsKCQkJaXNbal09dDsKCQl9Cgl9CgoJdm9pZCBsb2NrKCl7CgkJaWYoZGVidWcpewoJCQlmb3IoOyBsb2NrOyl7CgkJCQl0cnl7CgkJCQkJVGhyZWFkLnNsZWVwKDIpOwoJCQkJfWNhdGNoKEludGVycnVwdGVkRXhjZXB0aW9uIGUpewoJCQkJCWUucHJpbnRTdGFja1RyYWNlKCk7CgkJCQl9CgkJCX0KCQkJbG9jaz10cnVlOwoJCX0KCX0KCgl2b2lkIHByaW50bG4oU3RyaW5nIHMpewoJCVN5c3RlbS5vdXQucHJpbnRsbihzKTsKCX0KCgl2b2lkIHByaW50KFN0cmluZyBzKXsKCQlTeXN0ZW0ub3V0LnByaW50KHMpOwoJfQoKCXZvaWQgZGVidWcoT2JqZWN0Li4uIG9zKXsKCQlTeXN0ZW0uZXJyLnByaW50bG4oQXJyYXlzLmRlZXBUb1N0cmluZyhvcykpOwoJfQoKCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpewoJCW5ldyBBKCkucnVuKCk7Cgl9Cgp9CgpjbGFzcyBYb3JzaGlmdHsKCglpbnQgeCwgeSwgeiwgdzsKCglwdWJsaWMgWG9yc2hpZnQoKXsKCQl4PTEyMzQ1Njc4OTsKCQl5PTM2MjQzNjA2OTsKCQl6PTUyMTI4ODYyOTsKCQl3PTg4Njc1MTIzOwoJfQoKCXB1YmxpYyBYb3JzaGlmdChpbnQgc2VlZCl7CgkJeD1fKHNlZWQsIDApOwoJCXk9Xyh4LCAxKTsKCQl6PV8oeSwgMik7CgkJdz1fKHosIDMpOwoJfQoKCWludCBfKGludCBzLCBpbnQgaSl7CgkJcmV0dXJuIDE4MTI0MzMyNTMqKHNeKHM+Pj4zMCkpK2krMTsKCX0KCgkvLyAzMmJpdCBzaWduZWQKCXB1YmxpYyBpbnQgbmV4dEludCgpewoJCWludCB0PXheKHg8PDExKTsKCQl4PXk7CgkJeT16OwoJCXo9dzsKCQlyZXR1cm4gdz13Xih3Pj4+MTkpXnReKHQ+Pj44KTsKCX0KCgkvLyBlcnJvciA9IE8obioyXi0zMikKCXB1YmxpYyBpbnQgbmV4dEludChpbnQgbil7CgkJcmV0dXJuIChpbnQpKG4qbmV4dERvdWJsZSgpKTsKCX0KCgkvLyBbMCwgMSkgKDUzYml0KQoJcHVibGljIGRvdWJsZSBuZXh0RG91YmxlKCl7CgkJaW50IGE9bmV4dEludCgpPj4+NSwgYj1uZXh0SW50KCk+Pj42OwoJCXJldHVybiAoYSo2NzEwODg2NC4wK2IpKigxLjAvKDFMPDw1MykpOwoJfQoKfQoKY2xhc3MgUGFpciBpbXBsZW1lbnRzIENvbXBhcmFibGU8UGFpcj57CglpbnQga2V5OwoJZG91YmxlIHZhbHVlOwoKCVBhaXIoaW50IGtleSwgZG91YmxlIHZhbHVlKXsKCQl0aGlzLmtleT1rZXk7CgkJdGhpcy52YWx1ZT12YWx1ZTsKCX0KCglAT3ZlcnJpZGUKCXB1YmxpYyBpbnQgY29tcGFyZVRvKFBhaXIgcCl7CgkJcmV0dXJuIERvdWJsZS5jb21wYXJlKHZhbHVlLCBwLnZhbHVlKTsKCX0KfQoKY2xhc3MgUGFyYW17CglpbnQgdywgaCwgbjsKCWludFtdIHdzLCBoczsKCglQYXJhbShpbnQgdywgaW50IGgsIGludCBuLCBpbnRbXSB3cywgaW50W10gaHMpewoJCXRoaXMudz13OwoJCXRoaXMuaD1oOwoJCXRoaXMubj1uOwoJCXRoaXMud3M9d3MuY2xvbmUoKTsKCQl0aGlzLmhzPWhzLmNsb25lKCk7Cgl9Cn0KCmNsYXNzIEFuc3dlcnsKCWludFtdIHgxLCB5MSwgeDIsIHkyOwoJaW50IG47CgoJQW5zd2VyKGludFtdIHgxLCBpbnRbXSB5MSwgaW50W10geDIsIGludFtdIHkyKXsKCQl0aGlzLngxPXgxLmNsb25lKCk7CgkJdGhpcy55MT15MS5jbG9uZSgpOwoJCXRoaXMueDI9eDIuY2xvbmUoKTsKCQl0aGlzLnkyPXkyLmNsb25lKCk7CgkJbj14MS5sZW5ndGg7Cgl9Cn0KCmNsYXNzIFNjYW5uZXJ7CglCdWZmZXJlZFJlYWRlciBicjsKCVN0cmluZ1Rva2VuaXplciBzdDsKCglTY2FubmVyKElucHV0U3RyZWFtIGluKXsKCQlicj1uZXcgQnVmZmVyZWRSZWFkZXIobmV3IElucHV0U3RyZWFtUmVhZGVyKGluKSk7CgkJZWF0KCIiKTsKCX0KCgl2b2lkIGVhdChTdHJpbmcgcyl7CgkJc3Q9bmV3IFN0cmluZ1Rva2VuaXplcihzKTsKCX0KCglTdHJpbmcgbmV4dExpbmUoKXsKCQl0cnl7CgkJCXJldHVybiBici5yZWFkTGluZSgpOwoJCX1jYXRjaChJT0V4Y2VwdGlvbiBlKXsKCQkJdGhyb3cgbmV3IElPRXJyb3IoZSk7CgkJfQoJfQoKCWJvb2xlYW4gaGFzTmV4dCgpewoJCXdoaWxlKCFzdC5oYXNNb3JlVG9rZW5zKCkpewoJCQlTdHJpbmcgcz1uZXh0TGluZSgpOwoJCQlpZihzPT1udWxsKQoJCQkJcmV0dXJuIGZhbHNlOwoJCQllYXQocyk7CgkJfQoJCXJldHVybiB0cnVlOwoJfQoKCVN0cmluZyBuZXh0KCl7CgkJaGFzTmV4dCgpOwoJCXJldHVybiBzdC5uZXh0VG9rZW4oKTsKCX0KCglpbnQgbmV4dEludCgpewoJCXJldHVybiBJbnRlZ2VyLnBhcnNlSW50KG5leHQoKSk7Cgl9Cn0=