Forty Two - A Java Solver

0 Conversations


import java.util.HashMap;

public class GFortyTwo
{
// Data

private HashMap results;
private static final Value impossible=new Value(false, "");

// Constructors

GFortyTwo()
{
results=new HashMap(1000000);
}

public static void main(String[] arguments)
{
GFortyTwo finder=new GFortyTwo();
double[] digits=new double[arguments.length];

for(int i=0; i!=arguments.length; i++)
{
digits[i]=Integer.parseInt(arguments[i]);
}

System.out.println(finder.make(new Key(digits, 42), true));
}

private Value attempt(double[] leftDigits, double leftTarget,
double[] rightDigits, double rightTarget,
boolean switchSides, String symbol)
{
if(switchSides)
{
Value rightResult=make(new Key(rightDigits, rightTarget), true);
if(rightResult.possible)
{
Value leftResult=make(new Key(leftDigits, leftTarget), true);
if(leftResult.possible)
{
return new Value(true, leftResult.toString()+symbol+rightResult.toString());
}
}
}
else
{
Value leftResult=make(new Key(leftDigits, leftTarget), true);
if(leftResult.possible)
{
Value rightResult=make(new Key(rightDigits, rightTarget), true);
if(rightResult.possible)
{
return new Value(true, leftResult.toString()+symbol+rightResult.toString());

}
}
}

return impossible;
}

private Value tryUnary(double from, double to)
{
if(from==to)
{
Value value=new Value(true,
Integer.toString((int)from));

return value;
}

if(((to==2)&&(from==4))||
((to==3)&&(from==9)))
{
Value value=new Value(true,
"q"+Integer.toString((int)from));
return value;
}

if((to==1)&&(from==0)||
(to==6)&&(from==3)||
(to==24)&&(from==4)||
(to==120)&&(from==5)||
(to==720)&&(from==6))
{
Value value=new Value(true,
Integer.toString((int)from)+"!");
return value;
}

if((to==45)&&(from==1))
{
Value value=new Value(true,
"ATN("+Integer.toString((int)from)+")");
return value;
}

if((to==90)&&(from==0))
{
Value value=new Value(true,
"ACOS("+Integer.toString((int)from)+")");
return value;
}

if((to==90)&&(from==1))
{
Value value=new Value(true,
"ASIN("+Integer.toString((int)from)+")");
return value;
}

if((to==0)&&(from==1))
{
Value value=new Value(true,
"ACOS("+Integer.toString((int)from)+")");
return value;
}

return impossible;
}


private Value make(Key key, boolean allowUnary)
{
if(key.digits.length==1)
{
return(tryUnary(key.digits[0], key.target));
}
else
{

Value value=(Value)results.get(key);
if(value!=null)
{
// System.out.println("Old: "+key+" "+value);
// System.out.print("?");
return value;
}
else
{
value=new Value(false, "");
}

try
{
// Digit concatenation

double concatenated=concatenate(key.digits);

if(concatenated==key.target)
{
value.possible=true;
value.formula=Integer.toString((int)key.target);
return value;
}

if((key.target>0)&&(key.target*key.target==concatenated))
{
value.possible=true;
value.formula="q"+Integer.toString((int)concatenated);
return value;
}

// Cycle over split points

int middle=key.digits.length/2;

for(int o=1; o!=key.digits.length; o++)
{
int d=0;

if((o&1)==0)
{
d=middle+o/2;
}
else
{
d=middle-o/2;
}


double[] leftDigits=new double[d];
double[] rightDigits=new double[key.digits.length-d];

double leftTarget=0;
double rightTarget=0;
Value leftResult;
Value rightResult;
boolean switchSides=d>(key.digits.length/2);

for(int i=0; i!=key.digits.length; i++)
{
if(i<d) leftDigits[i]=key.digits[i];
else rightDigits[i-d]=key.digits[i];
}

for(int index=0; index!=key.target*2; index=index<0?-index:-index-1)
{
// Addition

leftTarget=index;
rightTarget=key.target-leftTarget;

value=attempt(leftDigits, leftTarget, rightDigits, rightTarget,
switchSides, "+");
if(value.possible) return value;

// Subtraction

leftTarget=index;
rightTarget=leftTarget-key.target;

value=attempt(leftDigits, leftTarget, rightDigits, rightTarget,
switchSides, "-");
if(value.possible) return value;

// Multiplication

if((index!=0)||(key.target==0))
{
leftTarget=index;
if(key.target!=0) rightTarget=key.target/leftTarget;
else rightTarget=0;

if(rightTarget==(int)rightTarget)
{
value=attempt(leftDigits, leftTarget, rightDigits, rightTarget,
switchSides, "*");
if(value.possible) return value;
}

if(key.target==0)
{
value=attempt(leftDigits, rightTarget, rightDigits, leftTarget,
switchSides, "*");
if(value.possible) return value;
}
}

// Division

if((index!=0)||(key.target==0))
{
leftTarget=index;
rightTarget=leftTarget/key.target;

if(rightTarget==(int)rightTarget)
{
value=attempt(leftDigits, leftTarget, rightDigits, rightTarget,
switchSides, "/");
if(value.possible) return value;
}
}

// Zeroth power

leftTarget=index;

if((key.target==1)&&(leftTarget>0))
{
value=attempt(leftDigits, leftTarget, rightDigits, 0,
switchSides, "^");
if(value.possible) return value;
}

if((key.target==-1)&&(rightTarget<0))
{
value=attempt(leftDigits, leftTarget, rightDigits, 0,
switchSides, "^");
if(value.possible) return value;
}
}
}

return value;
}
finally
{
results.put(key, value);

if(value.possible) System.out.println("New: "+key+" "+value);
}
}
}

private double concatenate(double[] digits)
{
double result=0;

for(int i=0; i!=digits.length; i++)
{
result=result*10+digits[i];
}

return result;
}

private static class Key
{
public double[] digits;
public double target;

Key(double[] digits, double target)
{
this.digits=digits;
this.target=target;
}

public String toString()
{
String result="";

for(int i=0; i!=digits.length; i++)
{
result+=(int)digits[i];
}
result+="=>";
result+=target;

return result;
}

public int hashCode()
{
int result=(int)target;

for(int i=0; i!=digits.length; i++)
{
result=result*13+(int)digits[i];
}

return result;
}

public boolean equals(Object object)
{
if(!(object instanceof Key)) return false;

if(((Key)object).target!=target) return false;
if(((Key)object).digits.length!=digits.length) return false;

for(int i=0; i!=digits.length; i++)
{
if(((Key)object).digits[i]!=digits[i]) return false;
}

return true;
}
}

private static class Value
{
public boolean possible;
public String formula;

Value(boolean possible, String formula)
{
this.possible=possible;
this.formula=formula;
}

public String toString()
{
if(!possible) return "not possible";
else if(formula.length()<3) return formula; else return "("+formula+")";
}
}
}


Bookmark on your Personal Space


Conversations About This Entry

There are no Conversations for this Entry

Entry

A855029

Infinite Improbability Drive

Infinite Improbability Drive

Read a random Edited Entry


Written and Edited by

Disclaimer

h2g2 is created by h2g2's users, who are members of the public. The views expressed are theirs and unless specifically stated are not those of the Not Panicking Ltd. Unlike Edited Entries, Entries have not been checked by an Editor. If you consider any Entry to be in breach of the site's House Rules, please register a complaint. For any other comments, please visit the Feedback page.

Write an Entry

"The Hitchhiker's Guide to the Galaxy is a wholly remarkable book. It has been compiled and recompiled many times and under many different editorships. It contains contributions from countless numbers of travellers and researchers."

Write an entry
Read more