質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

1回答

6155閲覧

覆面算をとくプログラムは?

katoy

総合スコア22324

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

3クリップ

投稿2014/12/13 14:07

覆面算をプログラムで解くとした場合、皆さんなら風にふうにしますか?
(利用言語は問いません。)

覆面算とは: http://ja.wikipedia.org/wiki/%E8%A6%86%E9%9D%A2%E7%AE%97

こんな例があります。
SEND + MORE == MONEY
twelve + twenty == answer
みず * みず = 飲みみず
ぴよ * ぴよ = ひよこ

私は、こんなふうにしました。
https://gist.github.com/katoy/2dfd7d41b342ddb70aaf

これを書くのに参考にしたのは次のページ。
Dive Into Python 3の覆面算をRubyで書いてみた http://web-salad.hateblo.jp/entry/2014/04/06/164312

筆算型の覆面算をとけるようにもしたいです。
さらには虫食い算もとけるようにしたいです。

googleでの虫食い算画像の検索

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

Javaで書いてみました。
evalpermutationが標準で使えないので、いろいろと苦しいですが...

演算子は+,-,*限定で。
permutationは、Uncommons Mathsというライブラリーを使いました。10文字中n文字みたいに使えないのが難点です。
Uncommons Maths - Random number generators, probability distributions, combinatorics and statistics for Java

lang

1 2// --- JUnitテスト --- 3// ※Alphametics.solveをstatic-import 4// assertEquals("9567 + 1085 = 10652", solve("SEND + MORE = MONEY")); 5// assertEquals("87 + 12 = 99", solve("AB + 12 = 99")); 6// assertEquals("407927 + 407146 = 815073", solve("twelve + twenty = answer")); 7// assertEquals("142857 * 2 = 285714", solve("ABCDEF * C = CDEFAB")); 8// assertEquals("5943 * 143 = 849849", solve("kore * are = iroiro")); 9// // これはサポートしない assertEquals("1 + 3 + 9 = 13 && 3 + 3 + 3 = 9", solve("a + b + c = ab && b + b + b = c")); 10// assertEquals("76 * 76 = 5776", solve("みず * みず = 飲みみず")); 11 12 13// --- メイン --- 14 15import java.util.*; 16import java.util.regex.*; 17import java.util.stream.*; 18import org.uncommons.maths.combinatorics.PermutationGenerator; 19 20final class Alphametics { 21 22 static Pattern p = Pattern.compile("([^\+\-\*]+)([\+\-\*])([^\+\-\*]+?)={1,2}([^\+\-\*=]+)"); 23 24 static String solve(String expr) { 25 char[] uniqueChars = uniqueChars(expr); 26 if (uniqueChars.length > 10) 27 throw new IllegalArgumentException("chars > 10"); 28 PermutationGenerator<Character> gen 29 = new PermutationGenerator<>(Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')); 30 Character[] numbers = new Character[10]; 31 while (gen.hasMore()) { 32 gen.nextPermutationAsArray(numbers); 33 String replaced = replaceCharsToNumbers(expr, uniqueChars, numbers); 34 if (evaluate(replaced)) 35 return replaced; 36 } 37 return "(failed)"; 38 } 39 40 private static char[] uniqueChars(String expr) { 41 Matcher m = p.matcher(expr.replaceAll("\s", "")); 42 if (!m.matches()) 43 throw new IllegalArgumentException("bad format: " + expr); 44 String s = m.group(1) + m.group(3) + m.group(4); 45 Set<Character> set = s.replaceAll("\d+", "").chars().mapToObj(c -> (char)c).collect(Collectors.toSet()); 46 char[] chars = new char[set.size()]; 47 int i = 0; 48 for (Character c : set) 49 chars[i++] = c; 50 return chars; 51 } 52 53 private static String replaceCharsToNumbers(String expr, char[] uniqueChars, Character[] numbers) { 54 String s = expr; 55 for (int i = 0, n = uniqueChars.length; i < n; i++) 56 s = s.replace(uniqueChars[i], numbers[i]); 57 return s; 58 } 59 60 private static boolean evaluate(String expr) { 61 String s = expr.replaceAll("\s", ""); 62 Matcher m = p.matcher(s); 63 if (!m.matches()) 64 throw new IllegalArgumentException("bad format: " + expr); 65 String sa = m.group(1); 66 String sb = m.group(3); 67 String sc = m.group(4); 68 if (Stream.of(sa, sb, sc).anyMatch(x -> x.startsWith("0"))) 69 return false; 70 int a = Integer.parseInt(sa); 71 int b = Integer.parseInt(sb); 72 int c = Integer.parseInt(sc); 73 int d; 74 switch (m.group(2)) { 75 case "+": 76 d = a + b; 77 break; 78 case "-": 79 d = a - b; 80 break; 81 case "*": 82 d = a * b; 83 break; 84 default: 85 return false; 86 } 87 return c == d; 88 } 89 90}

追記: evalをScripting(JavaScript)で。これなら&&も使えます。
さすがに遅いですね。

lang

1// 上のコードの、uniqueCharsメソッドとevaluateメソッドを書き換える 2 3// import javax.script.*; // import追加 4 5 private static char[] uniqueChars(String expr) { 6 String s = expr.replaceAll("[\s\+\-\*=&\|\d]", ""); 7 Set<Character> set = s.chars().mapToObj(c -> (char)c).collect(Collectors.toSet()); 8 char[] chars = new char[set.size()]; 9 int i = 0; 10 for (Character c : set) 11 chars[i++] = c; 12 return chars; 13 } 14 15 private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); 16 17 private static boolean evaluate(String expr) { 18 for (String x : expr.split("\D")) 19 if (x.startsWith("0")) 20 return false; 21 try { 22 return (boolean)engine.eval(expr); 23 } catch (ScriptException e) { 24 throw new RuntimeException(e); 25 } 26 } 27

投稿2014/12/17 09:19

argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

katoy

2014/12/17 14:40

java での記述はなかなか苦しいですね。 javascript あどのスクリプト を java から呼び出す方法を使って、eval のようなことはできそうですが...
argius

2014/12/18 04:01

Scriptingでeval版を追加してみました。 パフォーマンスはかなり落ちますが...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問