儿童黑话(Pig Latin)语言加密算法

Pig Latin(儿童黑话)

我是怎么接触到Pig Latin的?

实际上我是在C++ Program Algorithm(中译版)黑皮书上接触到的,当时看到这个短语还以为是跟猪相关,真是贻笑大方了。实际上这是个语言游戏,只不过也可以用来进行简单的语言加密。

后来在查阅资料的时候,发现了一个很有趣的一段话:”Ix-nay on the upid-stay.”。这段话出现在狮子王1中dodo鸟Zazu(沙祖)在大象墓地说的话,大概意思就是愚蠢的nalx。upid-stay实际上就是stupid,是一种非常地道的英语表达。

什么是Pig Latin?

儿童黑话(Pig Latin)是一种英语语言游戏,形式是在英语加上一点规则使发音改变。据说是由在德国的英国战俘发明来瞒混德军守卫的。儿童黑话于50年代和60年代在英国利物浦达到颠峰,各种年纪和职业的人都有使用。儿童黑话多半被儿童用来瞒著大人秘密沟通,有时则只是说著好玩。虽然是起源于英语的游戏,但是规则适用很多其他语言。

Pig Latin规则?

  • 假设单词以辅音字母开始,将词首的辅音字母字符串(第一个元音字母前的全部字母)从单词的开头移动到末尾,然后加上后缀ay,这样就形成了它的pig latin。
  1. 比如说ball,它的第一个元音是a,那么它的Pig Latin就是all-bay.
  2. three,元音是e,变成ee-thray.

怎么样?是不是很容易理解?

  • 那么对于元音字母开头的单词,该怎么描述它的黑话?仅仅加入后缀ay就可以,也可以是way,yay,hay。为了方便统一,在本文一律用way后缀。
  • 让我们看看一个示例

One-way o-whay as-hay een-say e-thay ocean-way inks-thay othing-nay of-way ere-may ivers-ray.

(中译:曾经沧海难为水)

(英语:One who has seen the ocean thinks nothing of mere rivers.)

如何用代码实现Pig Latin语言加密?(以JAVA为例,实现单词Pig Latin加密,语句加密在本篇暂不实现,期待后续实现)

  1. 首先第一步,当然是要找出第一个元音字母的位置。(已知元音字母有a,e,i,o,u,其他的都是辅音字母)
  2. 第二步,判断元音字母出现的位置,如果是一个位置,则把备用后缀设为way,否则是ay
  3. 第三步,在第一个元音字母位置分离,把单词分离为两个部分。比如ball,分离为b和all.
  4. 第四步,将分离后的第二个部分放在首部,第一个部分放在尾部。
  5. 第五步,在第四部拼合的结果上,在尾部加入后缀。

那么整个编程的思路就很明了了,接下来开始撸代码。

全部代码我就放在结尾了,因为,你知道的,很影响阅读效率。

判断是否是元音字母
1
2
3
4
5
6
7
8
9
10
11
12
private static boolean isVowel(char ch) {
switch(ch) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return true;
default :
return false;
}
}

这个代码也很简单就是swith-case判断,但是有一个致命问题,就是没有办法分辨大写字母情况,实际上行首的字母通常是大写的,而且大写的元音字母也是元音。so,我们应该加上所有的大写字母吗?加上所有的元音大写字母的话,整个方法会显得很臃肿。实际上java里面String类有一个方法equalsIgnoreCase判断字母是否为指定字符而忽略大小写。

修改后的判断是否是元音字母代码
1
2
3
4
5
6
7
8
9
10
11
private static boolean isVowel(char ch) {
String str = String.valueOf(ch);
if(str.equalsIgnoreCase("a")|
str.equalsIgnoreCase("e")|
str.equalsIgnoreCase("i")|
str.equalsIgnoreCase("o")|
str.equalsIgnoreCase("u")) {
return true;
}
return false;
}
还有一个问题,在找到元音字母后如何进行字符串倒置,我的实现代码是这样的
1
2
3
4
5
6
//beforeWord:倒置前字符串,index:元音字母所在位置
private static String reversalWord(String beforeWord,int index) {
String frontWord = beforeWord.substring(0,index);
String breakWord = beforeWord.substring(index);
return breakWord.concat(frontWord);
}
结果输出

One -> Oneway

剩下的都是没什么了,有兴趣的话可以看看结尾的全部代码

缺陷

  1. 还可以进一步优化思路,提高程序健壮程度,降低时间复杂度。
  2. 只是实现了单个单词的Pig Latin加密,句子的Pig Latin加密没有实现,因为句子的情况更为复杂。

全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package exercise1;

import java.util.Scanner;
import java.util.StringTokenizer;

public class test2 {

public static void main(String[] args) {
// TODO Auto-generated method stub

Scanner scanner = new Scanner(System.in);//从键盘输入
String word=scanner.nextLine();
System.out.println(translateWord(word));
}

private static String translateWord(String inputWord) {
String breakWord = "";
String afterWord = "";
StringBuilder endWord = new StringBuilder();
int i = indexOfVowel(inputWord);

if(i >= 0) {
if(i == 0) {
breakWord = "way";
endWord.append(inputWord);
endWord.append(breakWord);
}else {
breakWord = "ay";
endWord.append(reversalWord(inputWord,i));
endWord.append(breakWord);
}
return endWord.toString();

}else {
return inputWord;
}
}

private static String reversalWord(String beforeWord,int index) {
String frontWord = beforeWord.substring(0,index);
String breakWord = beforeWord.substring(index);
return breakWord.concat(frontWord);
}

private static int indexOfVowel(String inputWord) {
for(int i = 0;i < inputWord.length();i++) {
if(isVowel(inputWord.charAt(i))) {
return i;
}
}
return -1;
}

private static boolean isVowel(char ch) {
String str = String.valueOf(ch);
if(str.equalsIgnoreCase("a")|
str.equalsIgnoreCase("e")|
str.equalsIgnoreCase("i")|
str.equalsIgnoreCase("o")|
str.equalsIgnoreCase("u")) {
return true;
}
return false;
}

}

参考资料:

char转化为String
儿童黑话介绍
相关代码参考


儿童黑话(Pig Latin)语言加密算法
https://llc-zh.github.io/2021/11/09/儿童黑话-Pig-Latin/
作者
野风掠原
发布于
2021年11月9日
许可协议