Skip to content

Instantly share code, notes, and snippets.

@takawitter
Last active December 12, 2015 12:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takawitter/4770094 to your computer and use it in GitHub Desktop.
Save takawitter/4770094 to your computer and use it in GitHub Desktop.
姓名判断プログラム in Java8 lambda and stream interface
package seimei;
import jp.go.nict.langrid.commons.util.Pair;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.Streams;
public class Seimei {
public static void main(String[] args) throws Exception{
System.out.println("名前, 天運, 人運, 地運, 外運, 総運");
new Seimei().handan(
"鈴木",
new String[][]{
{"一壱", "郎朗"},
{"剣権堅健謙賢拳", "汰太大", "朗郎"}
}
).forEach(v -> System.out.println(v.getFirst() + ": " + v.getSecond()));
}
public Stream<Pair<Integer, String>> handan(String familyName, String[][] candidates){
int[] fnPoints = familyName.codePoints().map(c -> kakusuu.get(c)).toArray();
int fnPointsSum = Arrays.stream(fnPoints).sum();
return Arrays.stream(candidates)
.flatMap(this::combination)
.map(givens -> calc(familyName, fnPointsSum, fnPoints, givens))
.sorted((l, r) -> r.getFirst() - l.getFirst());
}
private Stream<int[]> combination(String[] elements){
int n = elements.length;
int[] divide = new int[n];
int[] surplus = new int[n];
int r = Streams.intRange(0, n).reduce(1, (ret, i) -> {
i = n - i - 1;
int len = elements[i].codePointCount(0, elements[i].length());
divide[i] = ret;
surplus[i] = len;
return ret *= len;
});
return Streams.intRange(0, r).mapToObj(
i -> Streams.intRange(0, n).map(
j -> elements[j].codePointAt((i / divide[j]) % surplus[j])
).toArray()
);
}
private Pair<Integer, String> calc(String familyName, int fnPointsSum, int[] fnPoints, int[] givens){
int[] givenPoints = Arrays.stream(givens).map(v -> kakusuu.get(v)).toArray();
int givenPointsSum = Arrays.stream(givenPoints).sum();
int all = fnPointsSum + givenPointsSum;
int inner = fnPoints[fnPoints.length - 1] + givenPoints[0];
List<Pair<Integer, Kikkyou>> kikkyous = Arrays.stream(new int[]{
fnPointsSum, inner, givenPointsSum,
all - inner + (fnPoints.length == 1 ? 1 : 0) + (givenPoints.length == 1 ? 1 : 0),
all
}).mapToObj(v -> Pair.create(v, kikkyou.get(v))).collect(Collectors.toCollection(ArrayList::new));
StringBuilder name = new StringBuilder();
name.append(
kikkyous.stream().anyMatch(v -> bad.contains(v.getSecond())) ? "☓" :
kikkyous.stream().anyMatch(v -> nogood.contains(v.getSecond())) ? "△" : "◯"
)
.append(" ")
.append(familyName);
Arrays.stream(givens).forEach(name::appendCodePoint);
name.append(kikkyous.stream().map(v -> String.format(", %s(%d)", v.getSecond(), v.getFirst()))
.collect(Collectors.toStringJoiner("")));
return Pair.create(
kikkyous.stream().mapToInt(v -> v.getSecond().getScore()).sum(),
name.toString()
);
}
enum Kikkyou{
DAIKICHI("大吉", 2),
KICHI("吉", 1),
HANKICHI("半吉", 0),
HANKYO("半凶", -1),
KYO("凶", -2);
Kikkyou(String name, int score){
this.name = name;
this.score = score;
}
public String toString(){
return name;
}
public int getScore(){
return score;
}
static Kikkyou valueOfName(String v){
switch (v){
case "大吉": return DAIKICHI;
case "吉": return KICHI;
case "半吉": return HANKICHI;
case "半凶": return HANKYO;
case "凶": return KYO;
default: throw new RuntimeException();
}
}
private String name;
private int score;
}
private static Map<Integer, Integer> kakusuu = new HashMap<>();
private static Map<Integer, Kikkyou> kikkyou = new HashMap<>();
private static Set<Kikkyou> nogood = new HashSet<>();
private static Set<Kikkyou> bad = new HashSet<>();
static{
nogood.add(Kikkyou.HANKICHI);
bad.add(Kikkyou.HANKYO);
bad.add(Kikkyou.KYO);
try{
Function<Stream<String>, Stream<String[]>> toTokens = lines ->
lines.map(line -> line.trim())
.filter(line -> line.length() > 0)
.filter(line -> !line.startsWith("#"))
.map(line -> line.split(" |\t|,"));
try(InputStream is = Seimei.class.getResourceAsStream("/kakusuu.txt")){
toTokens.apply(new BufferedReader(new InputStreamReader(is, "UTF-8")).lines())
.filter(tokens -> tokens.length >= 2)
.forEach(tokens -> kakusuu.put(tokens[0].codePointAt(0), Integer.parseInt(tokens[1])));
}
try(InputStream is = Seimei.class.getResourceAsStream("/kikkyou.txt")){
toTokens.apply(new BufferedReader(new InputStreamReader(is, "UTF-8")).lines())
.filter(tokens -> tokens.length >= 2)
.forEach(tokens -> kikkyou.put(Integer.parseInt(tokens[0]), Kikkyou.valueOfName(tokens[1])));
}
} catch(IOException e){
throw new RuntimeException(e);
}
}
}
@takawitter
Copy link
Author

与えられた名前の全組み合わせを求め、5運の吉凶を計算してスコアの高い順に表示するプログラム。
kakusuu.txtには、字と画数を1行ずつ列挙。kikkyou.txtには、画数と吉凶(大吉,吉,半吉,半凶,凶)を
列挙して下さい。画数の数え方や吉凶にいろいろ流派あるらしいので、実際に列挙する内容はお好みで。

実行結果:

名前, 天運, 人運, 地運, 外運, 総運
7: ◯ 鈴木謙汰郎, 吉(17), 大吉(21), 吉(35), 大吉(31), 吉(52)
6: ☓ 鈴木壱朗, 吉(17), 大吉(16), 大吉(23), 大吉(24), 半凶(40)
6: △ 鈴木謙太郎, 吉(17), 大吉(21), 大吉(31), 半吉(27), 吉(48)
6: △ 鈴木謙大朗, 吉(17), 大吉(21), 大吉(31), 半吉(27), 吉(48)
5: ☓ 鈴木壱郎, 吉(17), 大吉(16), 凶(22), 大吉(23), 大吉(39)
5: ☓ 鈴木権汰朗, 吉(17), 半凶(26), 大吉(41), 大吉(32), 吉(58)
5: ☓ 鈴木堅汰朗, 吉(17), 吉(15), 半凶(30), 大吉(32), 大吉(47)
5: ☓ 鈴木堅大郎, 吉(17), 吉(15), 大吉(24), 半凶(26), 大吉(41)
5: ☓ 鈴木健汰朗, 吉(17), 吉(15), 半凶(30), 大吉(32), 大吉(47)
5: ☓ 鈴木健大郎, 吉(17), 吉(15), 大吉(24), 半凶(26), 大吉(41)
5: △ 鈴木謙汰朗, 吉(17), 大吉(21), 半吉(36), 大吉(32), 半吉(53)
3: ☓ 鈴木一郎, 吉(17), 吉(5), 吉(11), 大吉(23), 凶(28)
3: ☓ 鈴木一朗, 吉(17), 吉(5), 凶(12), 大吉(24), 吉(29)
3: ☓ 鈴木堅汰郎, 吉(17), 吉(15), 吉(29), 大吉(31), 凶(46)
3: △ 鈴木堅太郎, 吉(17), 吉(15), 吉(25), 半吉(27), 半吉(42)
...

@takawitter
Copy link
Author

あ、ファイルの読み込みとかPairクラスにサービスグリッドのユーティリティライブラリ http://servicegrid.svn.sourceforge.net/viewvc/servicegrid/service-grid-server/trunk/jp.go.nict.langrid.commons/ 使ってます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment