Last active
August 29, 2015 13:56
-
-
Save dha-lo-jd/9343923 to your computer and use it in GitHub Desktop.
ローカルで動かすビビオペヨソイゲーム
This file contains hidden or 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
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); | |
} | |
} |
This file contains hidden or 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
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)); | |
} | |
} |
This file contains hidden or 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
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(); | |
} | |
} |
This file contains hidden or 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
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)); | |
} | |
} |
This file contains hidden or 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
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