Skip to content

Instantly share code, notes, and snippets.

@dha-lo-jd
Last active August 29, 2015 13:56
Show Gist options
  • Save dha-lo-jd/9343923 to your computer and use it in GitHub Desktop.
Save dha-lo-jd/9343923 to your computer and use it in GitHub Desktop.
ローカルで動かすビビオペヨソイゲーム
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Delegate;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import org.apache.commons.lang3.RandomStringUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
public class BBOP {
/**
* bbop構文実行者
*/
static class BBOPOracle {
Map<String, RuneGroup> groups = Maps.newHashMap();
List<Rune> runes = Lists.newArrayList();
public BBOPResult run() {
murmur();
String word = chant();
double rate = pray();
return new BBOPResult(rate, word);
};
String chant() {
StringBuilder sb = new StringBuilder();
for (Rune rune : runes) {
sb.append(rune.getWord());
}
return sb.toString();
};
void murmur() {
for (RuneGroup group : groups.values()) {
group.reset();
}
}
double pray() {
double size = 0;
double matches = 0;
for (RuneGroup group : groups.values()) {
size += group.size();
matches += group.matches();
}
if (size == 0) {
return 0;
}
double rate = matches / size;
return rate * 100;
}
}
/**
* bbop構文パーサー
*/
static class BBOPParser {
public static BBOPOracle parse(String src, String grouping, String... groupTypes) {
String[] words = src.split("/");
if (words.length != grouping.length()) {
throw new IllegalArgumentException(String.format("Src is %d. but grouping is %d.", words.length, grouping.length()));
}
BBOPOracle oracle = new BBOPOracle();
// タイプ定義のマッピング
Map<String, GroupType> types = Maps.newHashMap();
int groupTypesIndex = 0;
while (groupTypes.length > groupTypesIndex) {
String groupId = groupTypes[groupTypesIndex];
if (groupTypes.length <= groupTypesIndex + 1) {
throw new IllegalArgumentException(String.format("GroupId[%s(%d)] has no type name.", groupId, groupTypesIndex));
}
groupTypesIndex++;
String typeName = groupTypes[groupTypesIndex];
GroupType type = GroupType.of(typeName);
types.put(groupId, type);
groupTypesIndex++;
}
// グループ文字ごとにグループタイプでグループを生成
for (char c : grouping.toCharArray()) {
String groupId = String.valueOf(c);
if (oracle.groups.containsKey(groupId)) {
continue;
}
if (!types.containsKey(groupId)) {
throw new IllegalArgumentException(String.format("GroupId[%s] was missing type.", groupId));
}
GroupType type = types.get(groupId);
RuneGroupFactory factory = groupFactoryMap.get(type);
RuneGroup group = factory.create();
oracle.groups.put(groupId, group);
groupTypesIndex++;
}
int wordIndex = 0;
for (String word : words) {
String groupId = String.valueOf(grouping.charAt(wordIndex));
RuneGroup group = oracle.groups.get(groupId);
Rune rune = new Rune(wordIndex, group);
group.addRune(rune, word);
oracle.runes.add(rune);
wordIndex++;
}
return oracle;
}
}
/**
* bbop結果
*/
@AllArgsConstructor
static class BBOPResult {
@Getter
final double rate;
@Getter
final String word;
@Override
public String toString() {
return String.format("%s (%3.1f%%)", word, rate);
}
}
/**
* 固定文字グループ
*/
static class FixedRuneGroup implements RuneGroup {
private Map<Rune, String> words = Maps.newHashMap();
@Override
public void addRune(Rune rune, String word) {
words.put(rune, word);
}
@Override
public String getWord(Rune rune) {
return words.get(rune);
}
@Override
public int matches() {
return 0;
}
@Override
public void reset() {
}
@Override
public int size() {
return 0;
}
}
static class KanaFixRandomRuneGroup extends RandomRuneGroup {
private enum Type {
HIRA, KATA, OTHER,
}
protected Map<Integer, Type> runeKanas = Maps.newHashMap();
public KanaFixRandomRuneGroup(Random rnd) {
super(rnd);
}
@Override
public void addRune(Rune rune, String word) {
super.addRune(rune, word);
Type type = Type.OTHER;
if (word.length() > 0) {
if (isHiragana(word.charAt(0))) {
type = Type.HIRA;
} else if (isKatakana(word.charAt(0))) {
type = Type.KATA;
}
}
runeKanas.put(rune.getIndex(), type);
}
@Override
protected String processWord(Rune rune, String word) {
int index = rune.getIndex();
Type type = runeKanas.get(index);
switch (type) {
case HIRA:
word = KtoH(word);
break;
case KATA:
word = HtoK(word);
break;
case OTHER:
default:
break;
}
return word;
}
}
static class KanaFixUniqueRandomRuneGroup extends KanaFixRandomRuneGroup {
public KanaFixUniqueRandomRuneGroup(Random rnd) {
super(rnd);
}
@Override
protected String getWordInternal(Rune rune) {
Collections.shuffle(randomRunes, rnd);
String word = randomRunes.get(0);
randomRunes.remove(0);
return word;
}
}
@RequiredArgsConstructor
static class RandomRuneGroup implements RuneGroup {
private interface SizeDelegate {
public int size();
}
protected final Random rnd;
@Delegate(types = {
SizeDelegate.class
})
protected Map<Integer, String> runes = Maps.newHashMap();
protected List<String> randomRunes = Lists.newArrayList();
protected Set<Integer> matches = Sets.newHashSet();
@Override
public void addRune(Rune rune, String word) {
runes.put(rune.getIndex(), word);
randomRunes.add(word);
}
@Override
public String getWord(Rune rune) {
String word = getWordInternal(rune);
int index = rune.getIndex();
if (word.equals(runes.get(index))) {
matches.add(index);
} else {
matches.remove(index);
}
return processWord(rune, word);
}
@Override
public int matches() {
return matches.size();
}
@Override
public void reset() {
matches.clear();
randomRunes.clear();
randomRunes.addAll(runes.values());
}
protected String getWordInternal(Rune rune) {
Collections.shuffle(randomRunes);
String word = randomRunes.get(0);
return word;
}
protected String processWord(Rune rune, String word) {
return word;
}
}
/**
* bbop文字
*/
@Value
static class Rune {
private final int index;
private RuneGroup myGroup;
public String getWord() {
return myGroup.getWord(this);
}
}
/**
* bbop文字グループ
*/
interface RuneGroup {
int size();
int matches();
void addRune(Rune rune, String word);
String getWord(Rune rune);
void reset();
}
interface RuneGroupFactory {
RuneGroup create();
}
static class UniqueRandomRuneGroup extends RandomRuneGroup {
public UniqueRandomRuneGroup(Random rnd) {
super(rnd);
}
@Override
protected String getWordInternal(Rune rune) {
Collections.shuffle(randomRunes, rnd);
String word = randomRunes.get(0);
randomRunes.remove(0);
return word;
}
}
@AllArgsConstructor
private enum GroupType {
FIXED("fixed"), //
RANDOM("random"), //
UNIQUE_RANDOM("urandom"), //
KANAFIXED_RANDOM("knfrandom"), //
KANAFIXED_UNIQUE_RANDOM("knfurandom"), //
;
private final String name;
private static final Map<String, GroupType> map;
static {
Map<String, GroupType> m = Maps.newHashMap();
for (GroupType type : GroupType.values()) {
m.put(type.name, type);
}
map = m;
}
public static GroupType of(String name) {
String n = name.toLowerCase();
if (!map.containsKey(n)) {
return FIXED;
}
return map.get(n);
}
}
private static Random rnd;
private static final Map<GroupType, RuneGroupFactory> groupFactoryMap;
static {
Map<GroupType, RuneGroupFactory> map = Maps.newEnumMap(GroupType.class);
map.put(GroupType.FIXED, new RuneGroupFactory() {
@Override
public RuneGroup create() {
return new FixedRuneGroup();
}
});
map.put(GroupType.RANDOM, new RuneGroupFactory() {
@Override
public RuneGroup create() {
return new RandomRuneGroup(rnd);
}
});
map.put(GroupType.UNIQUE_RANDOM, new RuneGroupFactory() {
@Override
public RuneGroup create() {
return new UniqueRandomRuneGroup(rnd);
}
});
map.put(GroupType.KANAFIXED_RANDOM, new RuneGroupFactory() {
@Override
public RuneGroup create() {
return new KanaFixRandomRuneGroup(rnd);
}
});
map.put(GroupType.KANAFIXED_UNIQUE_RANDOM, new RuneGroupFactory() {
@Override
public RuneGroup create() {
return new KanaFixUniqueRandomRuneGroup(rnd);
}
});
groupFactoryMap = map;
}
private static final String[] SRC = new String[] {
"ビ/ビ/ッ/ド/レ/ッ/ド/・/オ/ペ/レ/ー/ショ/ン", //
"11211212111212",//
"1", GroupType.UNIQUE_RANDOM.name,//
"2", GroupType.FIXED.name,//
};
private static final String[] SRC_N = new String[] {
"シ/リ/コ/ン/バ/レ/ー/で/P/H/P", //
"12212211333",//
"1", GroupType.FIXED.name,//
"2", GroupType.RANDOM.name,//
"3", GroupType.RANDOM.name,//
};
private static final String[] SRC_SPPC = new String[] {
"す/っ/ぽ/ん/ぽ/ん/チェ/ッ/カ/ー", //
"1212121212",//
"1", GroupType.KANAFIXED_UNIQUE_RANDOM.name,//
"2", GroupType.FIXED.name,//
};
private static final String[] SRC_OT = new String[] {
"お/し/り/タ/ー/ボ", //
"111121",//
"1", GroupType.KANAFIXED_RANDOM.name,//
"2", GroupType.FIXED.name,//
};
public static String HtoK(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if (isHiragana(c)) {
sb.append((char) (c - 'ぁ' + 'ァ'));
} else {
sb.append(c);
}
}
return sb.toString();
}
public static boolean isHiragana(char c) {
return c >= 'ぁ' && c <= 'ん';
}
public static boolean isKatakana(char c) {
return c >= 'ァ' && c <= 'ヶ';
}
public static String KtoH(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if (isKatakana(c)) {
sb.append((char) (c + 'ぁ' - 'ァ'));
} else {
sb.append(c);
}
}
return sb.toString();
}
public static void main(String[] args) {
String seed = RandomStringUtils.random(10, "0123456789abcdefghijklmnopqrstuvwxyz");
System.out.println(seed);
rnd = new Random(seed.hashCode());
bbop();
nk9t();
sppc();
ot();
}
private static void bbop() {
String[] src = SRC;
BBOPOracle oracle = BBOPParser.parse(src[0], src[1], Arrays.copyOfRange(src, 2, src.length));
int i = 0;
double rate = -1;
while (i < 10000 && rate < 50) {
BBOPResult result = oracle.run();
rate = result.getRate();
System.out.println(result);
i++;
}
}
private static void nk9t() {
String[] src = SRC_N;
BBOPOracle oracle = BBOPParser.parse(src[0], src[1], Arrays.copyOfRange(src, 2, src.length));
int i = 0;
double rate = -1;
while (i < 1 && rate < 90) {
BBOPResult result = oracle.run();
rate = result.getRate();
System.out.println(result);
i++;
}
}
private static void ot() {
String[] src = SRC_OT;
BBOPOracle oracle = BBOPParser.parse(src[0], src[1], Arrays.copyOfRange(src, 2, src.length));
BBOPResult result = oracle.run();
System.out.println(result);
}
private static void sppc() {
String[] src = SRC_SPPC;
BBOPOracle oracle = BBOPParser.parse(src[0], src[1], Arrays.copyOfRange(src, 2, src.length));
BBOPResult result = oracle.run();
System.out.println(result);
}
}
import java.util.Map;
import java.util.Random;
import com.google.common.collect.Maps;
public class BBOP {
public static void main(String[] args) {
String[] src = new String[] {
"ビ", "ビ", "ド", "レ", "ド", "オ", "ペ", "レ", "ショ",
};
Map<Integer, String> map = Maps.newHashMap();
map.put(1, "ッ");
map.put(3, "ッ");
map.put(4, "・");
map.put(7, "ー");
map.put(8, "ン");
Random rnd = new Random();
int l = src.length;
String[] dest = new String[l];
int match = 0;
for (int i = 0; i < l; i++) {
int n = rnd.nextInt(src.length);
dest[i] = src[n];
if (dest[i].equals(src[i])) {
match++;
}
}
StringBuilder sb = new StringBuilder();
int i = 0;
for (String r : dest) {
sb.append(r);
if (map.containsKey(i)) {
sb.append(map.get(i));
}
i++;
}
double rate = ((double) match) / ((double) l);
System.out.println(String.format("%s [%d/%d(%.3f%%)]", sb, match, l, rate));
}
}
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
public class BBOP {
@Value
static class FixedRune implements Rune {
private String rune;
}
@RequiredArgsConstructor
static class RandomRune implements Rune {
private static Map<Integer, String> runes = Maps.newHashMap();
private static List<String> randomRunes = Lists.newArrayList();
private static Set<Integer> matches = Sets.newHashSet();
public static int counts() {
return runes.size();
}
public static int matches() {
return matches.size();
}
public static double rate() {
return (((double) matches()) / (counts())) * 100;
}
public static RandomRune registRune(String rune) {
RandomRune r = new RandomRune(runes.size());
runes.put(runes.size(), rune);
randomRunes.add(rune);
return r;
}
private final int index;
@Override
public String getRune() {
Collections.shuffle(randomRunes);
String rune = randomRunes.get(0);
if (rune.equals(runes.get(index))) {
matches.add(index);
} else {
matches.remove(index);
}
return rune;
}
}
static interface Rune {
String getRune();
}
private static final Rune[] SRC = new Rune[] {
RandomRune.registRune("ビ"),//
RandomRune.registRune("ビ"),//
new FixedRune("ッ"),//
RandomRune.registRune("ド"),//
RandomRune.registRune("レ"),//
new FixedRune("ッ"),//
RandomRune.registRune("ド"),//
new FixedRune("・"),//
RandomRune.registRune("オ"), //
RandomRune.registRune("ペ"),//
RandomRune.registRune("レ"),//
new FixedRune("ー"),//
RandomRune.registRune("ショ"),//
new FixedRune("ン"),//
};
public static void main(String[] args) {
int i = 0;
double rate = -1;
while (i < 10000 && rate < 50) {
rate = bbop();
}
}
private static double bbop() {
StringBuilder sb = new StringBuilder();
for (Rune rune : SRC) {
sb.append(rune.getRune());
}
System.out.println(String.format("%s [%d/%d(%3.3f%%)]", sb, RandomRune.matches(), RandomRune.counts(), RandomRune.rate()));
return RandomRune.rate();
}
}
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class BBOP {
public static void main(String[] args) {
String[] src = new String[] {
"ビ", "ビ", "ド", "レ", "ド", "オ", "ペ", "レ", "ショ",
};
Map<Integer, String> map = Maps.newHashMap();
map.put(1, "ッ");
map.put(3, "ッ");
map.put(4, "・");
map.put(7, "ー");
map.put(8, "ン");
List<String> srcList = Lists.newArrayList(src);
Random rnd = new Random();
int l = src.length;
String[] dest = new String[l];
int match = 0;
int i1 = 0;
while (!srcList.isEmpty()) {
Collections.shuffle(srcList);
// int n = rnd.nextInt(src.length);
dest[i1] = srcList.get(0);
srcList.remove(0);
if (dest[i1].equals(src[i1])) {
match++;
}
i1++;
}
StringBuilder sb = new StringBuilder();
int i = 0;
for (String r : dest) {
sb.append(r);
if (map.containsKey(i)) {
sb.append(map.get(i));
}
i++;
}
double rate = ((double) match) / ((double) l);
System.out.println(String.format("%s [%d/%d(%.3f%%)]", sb, match, l, rate));
}
}
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
public class BBOP {
@Value
static class FixedRune implements Rune {
private String rune;
}
@RequiredArgsConstructor
static class RandomRune implements Rune {
private static Map<Integer, String> runes = Maps.newHashMap();
private static List<String> randomRunes = Lists.newArrayList();
private static Set<Integer> matches = Sets.newHashSet();
public static int counts() {
return runes.size();
}
public static int matches() {
return matches.size();
}
public static double rate() {
return (((double) matches()) / (counts())) * 100;
}
public static RandomRune registRune(String rune) {
RandomRune r = new RandomRune(runes.size());
runes.put(runes.size(), rune);
randomRunes.add(rune);
return r;
}
public static void reset() {
matches.clear();
randomRunes.clear();
randomRunes.addAll(runes.values());
}
private final int index;
@Override
public String getRune() {
Collections.shuffle(randomRunes);
String rune = randomRunes.get(0);
randomRunes.remove(0);
if (rune.equals(runes.get(index))) {
matches.add(index);
} else {
matches.remove(index);
}
return rune;
}
}
static interface Rune {
String getRune();
}
private static final Rune[] SRC = new Rune[] {
RandomRune.registRune("ビ"),//
RandomRune.registRune("ビ"),//
new FixedRune("ッ"),//
RandomRune.registRune("ド"),//
RandomRune.registRune("レ"),//
new FixedRune("ッ"),//
RandomRune.registRune("ド"),//
new FixedRune("・"),//
RandomRune.registRune("オ"), //
RandomRune.registRune("ペ"),//
RandomRune.registRune("レ"),//
new FixedRune("ー"),//
RandomRune.registRune("ショ"),//
new FixedRune("ン"),//
};
public static void main(String[] args) {
int i = 0;
double rate = -1;
while (i < 10000 && rate < 50) {
RandomRune.reset();
rate = bbop();
}
}
private static double bbop() {
StringBuilder sb = new StringBuilder();
for (Rune rune : SRC) {
sb.append(rune.getRune());
}
System.out.println(String.format("%s [%d/%d(%3.3f%%)]", sb, RandomRune.matches(), RandomRune.counts(), RandomRune.rate()));
return RandomRune.rate();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment