トップページに戻る
次のC#のサンプルへ
前のC#のサンプルへ
Cマガ電脳クラブ(第086回) 掛けても足しても
問題
2*42*8 = 24*28 (1)
73*9*42 = 7*3942 (2)
1803*60*6 =180*3606 (3)
この式をよく見ると、おもしろいことに、
どれも「数字の並び」が右辺と左辺で同じになっていることがわかる。
このようなものは、ほかにもまだたくさんある。ここで、'*'を'+'に置き換えてみると、
(1)だけがまだ成立している。
2+42+8=24+28 (1')
このように'*'と'+'の置き換えに対応するものは、両辺がそれぞれ4個の数字で構成される場合、
ほかにもう1解存在する(3*74*8=37*48)。
では、(2)や(3)のように両辺それぞれ5個以上の数字で構成されるものではどうだろうか。
5個から初めて、最初に成立する数字の個数と、その個数で作れる解をすべてあげていただきたい。
なお、例のように左辺は3数の掛け算(足し算)、右辺は2数の掛け算(足し算)という形に限定する。
また、0は式のなかの各数の左端には置けないものとする。
ソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
const int Jyougen = 9999999;
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int I = 100; I <= Jyougen; I++) {
List<int[]> Num2ArrList = DeriveNum2ArrList(I.ToString());
var CalcedArr = Num2ArrList.Select(
X => new { SumVal = X.Sum(), ProdVal = DeriveProd(X) }).ToArray();
List<int[]> Num3ArrList = DeriveNum3ArrList(I.ToString());
foreach (int[] EachNum3Arr in Num3ArrList) {
int wkSumVal = EachNum3Arr.Sum();
int wkProdVal = DeriveProd(EachNum3Arr);
int wkInd = Array.FindIndex(
CalcedArr, X => X.SumVal == wkSumVal && X.ProdVal == wkProdVal);
if (wkInd >= 0) {
Console.WriteLine("{0}で解を発見。経過時間={1}", I, sw.Elapsed);
Action<int[]> wkAct = pArr =>
{
for (int J = 0; J <= pArr.GetUpperBound(0); J++) {
Console.Write(pArr[J]);
if (J < pArr.GetUpperBound(0))
Console.Write("+(*)");
}
};
wkAct(EachNum3Arr); Console.Write(" = ");
wkAct(Num2ArrList[wkInd]); Console.WriteLine();
}
}
}
Console.WriteLine("終了しました。経過時間={0}", sw.Elapsed);
}
//数値を2つの数値に分割する
static List<int[]> DeriveNum2ArrList(string pTargetNumStr)
{
var WillReturn = new List<int[]>();
int UB = pTargetNumStr.Length - 1;
for (int I = 1; I <= UB; I++) {
string wkNumStr1 = pTargetNumStr.Substring(0, I);
string wkNumStr2 = pTargetNumStr.Substring(I);
//左端のゼロは不許可
if (wkNumStr1.StartsWith("0")) continue;
if (wkNumStr2.StartsWith("0")) continue;
WillReturn.Add(new int[] { int.Parse(wkNumStr1), int.Parse(wkNumStr2) });
}
return WillReturn;
}
//数値を3つの数値に分割する
static List<int[]> DeriveNum3ArrList(string pTargetNumStr)
{
var WillReturn = new List<int[]>();
int UB = pTargetNumStr.Length - 1;
for (int I = 1; I <= UB - 2; I++) {
for (int J = I + 1; J <= UB - 1; J++) {
string wkNumStr1 = pTargetNumStr.Substring(0, I);
string wkNumStr2 = pTargetNumStr.Substring(I, J - I + 1);
string wkNumStr3 = pTargetNumStr.Substring(J + 1);
//左端のゼロは不許可
if (wkNumStr1.StartsWith("0")) continue;
if (wkNumStr2.StartsWith("0")) continue;
if (wkNumStr3.StartsWith("0")) continue;
WillReturn.Add(
new int[] { int.Parse(wkNumStr1), int.Parse(wkNumStr2), int.Parse(wkNumStr3) });
}
}
return WillReturn;
}
//配列の総積を求める
static int DeriveProd(int[] pTargetArr)
{
int WillReturn = 1;
Array.ForEach(pTargetArr, X => WillReturn *= X);
return WillReturn;
}
}
実行結果
2428で解を発見。経過時間=00:00:00.0460849
2+(*)42+(*)8 = 24+(*)28
3748で解を発見。経過時間=00:00:00.0714381
3+(*)74+(*)8 = 37+(*)48
8322480で解を発見。経過時間=00:06:33.7583058
8+(*)3224+(*)80 = 832+(*)2480
終了しました。経過時間=00:07:58.7727091
解説
数値をループさせつつ、数値の分割の仕方を列挙して検証してます。