Last active
December 12, 2015 12:09
-
-
Save takawitter/4770094 to your computer and use it in GitHub Desktop.
姓名判断プログラム in Java8 lambda and stream interface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
あ、ファイルの読み込みとか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
与えられた名前の全組み合わせを求め、5運の吉凶を計算してスコアの高い順に表示するプログラム。
kakusuu.txtには、字と画数を1行ずつ列挙。kikkyou.txtには、画数と吉凶(大吉,吉,半吉,半凶,凶)を
列挙して下さい。画数の数え方や吉凶にいろいろ流派あるらしいので、実際に列挙する内容はお好みで。
実行結果: