Skip to content

Instantly share code, notes, and snippets.

@kuuso
Created September 24, 2014 14:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kuuso/6754d9321b5e1fe1d408 to your computer and use it in GitHub Desktop.
Save kuuso/6754d9321b5e1fe1d408 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
class TEST{
static void Main(){
String InputFile="./data.utf8.txt";
StreamReader SR=new StreamReader(InputFile);
//Stream stdin=Console.OpenStandardInput();
//StreamReader SR=new StreamReader(stdin);
String s="";
List<String> L=new List<String>();
while(!String.IsNullOrEmpty(s=SR.ReadLine())){
var ss=s.Split('\t');
Sol mySol =new Sol(ss);
bool chk=mySol.Solve();
if(!chk)L.Add(ss[0]);
}
Console.WriteLine("");
Console.WriteLine("Answer--result does not match with expectation -Total {0}",L.Count);
for(int i=0;i<L.Count;i++){
Console.Write(i==0?"{0}":",{0}",L[i]);
}
Console.WriteLine("");
}
}
class Sol{
public bool Solve(){
MakeUnitTable();
/* if(Ans(eq1)!=Ans(eq2)){
Console.WriteLine("Case:{0}",idx);
Console.WriteLine("\teq1: {0} \n\t\tans={1}",eq1,Ans(eq1));
Console.WriteLine("\teq2: {0} \n\t\tans={1}",eq2,Ans(eq2));
}
*/
return Ans(eq1)==Ans(eq2);
}
Dictionary<String,long> unit;
void MakeUnitTable(){
unit=new Dictionary<String,long>();
//長さ:mm基準
unit["mm"]=1;
unit["cm"]=10;
unit["m"]=1000;
unit["km"]=1000*1000;
//重さ:mg基準
unit["mg"]=1;
unit["g"]=1000;
unit["kg"]=1000*1000;
//時間:秒基準
unit["秒"]=1;
unit["分"]=60;
unit["時間"]=60*60;
unit["日"]=24*unit["時間"];
}
long Ans(String equ){
//□のある辺を左辺に
var s=equ.Split('=');
if(s[0].IndexOf('□')==-1){
String tmp=s[0];s[0]=s[1];s[1]=tmp;
}
String left=s[0];
String right=s[1];
//□とその単位の位置を調べる。符号(あれば)を含める。
int strt=left.IndexOf('□');
int len=0;
while(strt+len<left.Length && left[strt+len]>'9')len++;
if(strt>0 && (left[strt-1]=='-'||left[strt-1]=='+')){
strt--;
len++;
}
//Console.WriteLine("left:\t{0}",left);
//Console.WriteLine(" :\t{0},Eval={1}",left.Substring(0,strt),Eval(left.Substring(0,strt)));
//Console.WriteLine(" :\t{0}",left.Substring(strt,len));
//Console.WriteLine(" :\t{0},Eval={1}",left.Substring(strt+len),Eval(left.Substring(strt+len)));
//Console.WriteLine("right:\t{0},Eval={1}",right,Eval(right));
//□の項以外を右辺に移項し計算後、□の単位・符号で割り算
long ret=Eval(right)-Eval(left.Substring(0,strt))-Eval(left.Substring(strt+len));
left=left.Substring(strt,len);
if(left[0]=='-')ret/=-1;
ret/=unit[left.Substring(left.IndexOf('□')+1)];
return ret;
}
long Eval(String expr){
if(expr=="")return 0;
long ret=0;
String s=expr;
// -xx時間yy分zz秒 のようなケースのパースのため、符号をsigで覚えておく。
long sig=1;
while(s!=""){
//各項ごとに値を計算。('+'と'-'のasciiコードは数字より若い)
bool flg=false;
for(int i=0;i<s.Length;i++){
if(i==0){
if(s[0]=='-')sig=-1;
if(s[0]=='+')sig=1;
}
if(!flg && s[i]<='9'){
continue;
}
if(s[i]>'9'){
flg=true;
if(i!=s.Length-1)continue;
}
if((flg && (s[i]<='9')) || i==s.Length-1){
if(i==s.Length-1)i++;
var t=s.Substring(0,i);
long val=ParseWithUnit(t);
if(t[0]!='-'&&t[0]!='+'){
val*=sig;
}
s=s.Substring(i);
ret+=val;
break;
}
}
}
return ret;
}
long ParseWithUnit(String expr){
int cnt=0;
while(expr[cnt]<='9')cnt++;
long val=long.Parse(expr.Substring(0,cnt));
val*=unit[expr.Substring(cnt)];
return val;
}
String idx;
String eq1;
String eq2;
public Sol(String[] ss_){
//コンストラクタ:入力データはフィールドで保持。
idx=ss_[0];
eq1=ss_[1];
eq2=ss_[2];
}
}
【解答】
111,112,222,223,333,334,444,445,555,556,666,667,777,778,888,889,999
【コード概要】
・まず与えられた式を
 expr1+□+expr2=expr3 の形に変形し、expr1,expr2,expr3を評価して□を計算します。
・各exprの評価は、例えば
 3m20cm-3m10cm-□mm=5mm なら
 +3m +20cm -3m -10cm -□mm = +5mm と読み替え。
   ⇒ expr1="+3m +20cm -3m -10cm"
     expr2=""
     expr3="+5mm"
こういう単位で分けます。符号については、文字列に加えるのではなくてparseの際に前後の文脈で判断します。
・単位は基準単位の何倍か、という数値を事前にテーブル化しておいてparseします。
 今回は整数演算になるよう、最小単位を1にそろえています。
・詰め切れず、こういう問題が解けない実装になっています。。
  2500g-1kg□g80mg=1300g20mg ←これは不正解する
  2500g+1kg□g20mg=4000g20mg ←これは正解する
 (こういうケースがないことは一応確認しましたが)
 あとかっこ算もないので、再帰のくだりも省略しています。
 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment