救命!我还有更多作业!


18

我的老师对我的火星家庭作业感到不满。我遵守了所有规则,但是她说我的输出是胡言乱语的……当她第一次看时,她非常可疑。“所有语言都应遵循齐普夫定律等等……”我什至不知道齐普夫定律是什么!

事实证明,齐普夫定律指出,如果在y轴上绘制每个单词的频率的对数,在x轴上绘制每个单词的“位置”的对数(最常见= 1,第二最常见= 2,第三最commmon = 3,依此类推),则该图将显示一条斜率约为-1的直线,给定或取约10%。

例如,这是Moby Dick的情节:

在此处输入图片说明

x轴是第n个最常见的单词,y轴是第n个最常见的单词的出现次数。该线的斜率约为-1.07。

现在我们涵盖了Venutian。值得庆幸的是,Venutians使用拉丁字母。规则如下:

  • 每个单词必须至少包含一个元音(a,e,i,o,u)
  • 每个单词中最多可以连续三个元音,但连续最多两个辅音(辅音是不是元音的任何字母)。
  • 单词长度不超过15个字母
  • 可选:将单词分为3-30个单词的句子,以句点分隔

因为老师觉得我在火星作业上作弊,所以我被分配去写一篇至少30,000字长的文章(以Venutian语言写)。她将使用Zipf定律来检查我的工作,因此,当拟合一条直线时(如上所述),斜率必须最多为-0.9,但不小于-1.1,并且她希望词汇量至少为200个单词。同一单词连续不得重复超过5次。

这是CodeGolf,因此以字节为单位的最短代码获胜。请将输出粘贴到Pastebin或其他我可以将其下载为文本文件的工具中。


是的,如果您愿意,可以只写一个32767个单词的句子。限制是句子中单词的频率必须遵循zipf定律
J. Antonio Perez

1
“来自金星”的传统形容词是Veneral,但由于某种原因,它的受欢迎程度有所下降。金星常用于科幻小说中。
彼得·泰勒

我猜想在zipf分布之后构建单词列表并对其进行混洗将很有可能在zipf分布之后生成具有成对连续单词的序列。而且,如果列表中有足够的不同单词,那么将同一单词连续重复执行5次以上的可能性将很小。如果我尝试了这种方法并设法撰写了有效的论文,是否可以接受?
Leo

您的猜测是合理的,尽管斜率将是-0.35
J. Antonio Perez

它看起来仍然像一条直线。只是坡度会太大
J. Antonio Perez

Answers:


3

Mathematica,102个字节

""<>RandomChoice[1/Range@215->Rest@Flatten@Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}],8!]

未命名函数,不输入任何内容,返回一个字符串,该字符串包含40,320个三字母金星词,并带有结尾空格。

Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]仅使用字母“ vaeiou”即可产生216个三个字母的单词,每个字母都有自己的尾随空格。其中第一个单词“ vvv”不是有效的维纳斯语,但Rest会将其丢弃。

然后RandomChoice[1/Range@215->...,8!]赚8!=产生的215个单词列表中的40,320个随机选择,频率权重由前215个整数的倒数决定(1/Range@215)。最后,<>""...将结果列表中的字符串连接起来。

输出结果远非确定性的。奔跑了这篇金星论文

Mathematica,129个字节

#2&@@@Sort[Join@@Table[{i,Rest@Flatten@Outer[StringJoin,a={"v","a","e","i","o","u"},a,a,{" "}]~Part~j},{j,215},{i,0,1,j/7!}]]<>""

这是确定性的。215个单词的基本集合是相同的,但是现在每个单词被重复精确的次数(单词#j被重复大约7!/ j次),以使zipf定律成立。然后,将单词平均交织以避免重复。(想象每个单词都放在标尺上,并且该单词的所有副本均等距;当按顺序阅读所有单词时,没有哪个单词会重复很多,也许根本不会重复。)结果是30117单词金星随笔


不赚8!伪随机选择意味着您可以连续6次重复同一单词吗?
丹尼斯

是的,理论上。
格雷格·马丁

@GregMartin实际上...您链接到的文章不合规;vva连续出现六次。我认为这可能是一个更大的问题……不应该每次都挑战答案吗?(如果不是,您如何确定它们应该起作用的可能性?)
H Walters

这是一个公平的批评,我很想知道它如何发挥作用。
格雷格·马丁

2

05AB1E34 33 32字节

525DL/9*vNy<FD}})žMDâžNâJè3ô.rðý

525DL                            Yield [1, ..., 525]
     /                           Yield [525/1, ..., 525/525]
      9*                         Yield [4725/1, ..., 4725/525]. It's the number of occurences of each word. The sum of this array is greater than 30000
        v                        For each value (y = value, N = iteration counter starting from 0)
         N                       Push iteration counter
          y<FD}                  Push an array of "int(value)" times the iteration counter
               }                 End for
                )                Wrap everything in an array. At this point the array countains the sorted indices of all words that matches the frequency specs
                 žM              Push "aeiou"
                   Dâ            Cartesian product with itself (["aa", "ae", ...])
                     žN          Push the consonants
                       âJ        Cartesian product and join the values to make valid venutian words
                         è       Compute a big string with all words that correspond to the formerly computed indices
                          3ô     Since all words are concatenated, separate them into blocks of 3 letters
                            .r   Shuffle
                              ðý Join with whitespaces and implicitly display

在线尝试!

我认为它仍然可以打高尔夫球!例如,数字常数vNy<FD}可能是可修改的。

输出例子

它是如何工作的?

它按照“元音+元音+辅音”规则生成单词的所有组合,该规则使525个唯一有效单词(超过200个)。然后,它关联到他们每个人的频率符合法律规定f(x) = 4725/x,其中x是当前单词的等级,从1开始到525结束。然后将频率标准化并相乘,因此至少有30000个单词。该代码始终产生32074个单词,以使所涉及的常数可转换(请参见代码说明)。因此,每个单词的重复次数对应于同一单词的频率。最后,单词被打乱了。但是,这不能保证一个单词不会连续重复五次。因此,程序将生成所需的200个以上的唯一单词,以减少单词连续连续重复五次的可能性。请注意,此代码始终会生成相同的单词序列。两次运行之间唯一不同的是混洗操作的结果。

如何评估频率?

我编写了一个简单的Python3代码,该文件将文本存储在名为“输出”的文件中(从算法的角度来看,这很有意义!)并将其输出到“ stats.csv”。

from collections import Counter
from math import log10

with open("output", "r") as f:
    with open("stats.csv", "w") as stats:
        words = f.read().split()
        freqs = Counter(words)
        freqs = sorted([(i,freqs[i]) for i in freqs],key=lambda x:-x[1])

        print(len(words), "words")
        stats.write("logX;logF\n")
        for i, (key, f) in enumerate(freqs):
            stats.write(str(log10(i+1))+";"+str(log10(f))+"\n")

这总是为我的代码产生以下分布: 频率定律

因此斜率是-1.0138。现在,此值比上一个代码的斜率更接近-1,但仍满足斜率约束。


感谢您提供用于评估频率的脚本,请注意,最后还有一个额外的`。另外,为什么还要使用分号作为分隔符?csv通常代表逗号分隔的值;)
Leo

1
是的,你是对的哈哈!我对降价感到困惑。我先使用了内联代码,然后意识到使用代码块更合适,但是我忘记删除多余的`。我使用分号作为csv分隔符,因为我是法国人,有些软件或公司习惯用逗号分隔十进制值,而不是像手写十进制值那样使用点。尽管我总是使用点将整数部分与小数部分分开,但我使用分号时没有进一步考虑。但是,嘿,SSV是伟大的,以及;)
奥萨卜莱

0

击/核心的Utils,122个 110字节

for w in {b,c,d}{a,e,i}{f,g,h}{o,u,a}{j,k,l};{ let ++x;yes $w|head -$[5575/x];}|shuf --random-source=<(yes ae)

展开:

for w in {b,c,d}{a,e,i}{f,g,h}{o,u,a}{j,k,l};{
    let ++x
    yes $w|head -$[5575/x]
}|shuf --random-source=<(yes ae)

for w环243分产生不同的话。 let ++x;最初未设置x的增量(在第一次执行过程中,根据算术表达式规则,x将其视为0,因此其增量会将其设置为1)。因此,下一行将以5575 / x的频率生成后续单词,以近似zipf频率。

下一步是确定性地执行此操作,以满足重复要求;尽管这--random-source是一个非常大的标志名称,但将其与shuf一起使用会击败滚动mul-mod选择器的字符计数。 yes ae实际上是我发现符合要求的最短的固定“随机”设备。

这将生成此33729个单词文章[pastebin]

Bash / Core Utils,96 84字节(无竞争)

对于非确定性方法,只需砍掉shuf标志:

for w in {b,c,d}{a,e,i}{f,g,h}{o,u,a}{j,k,l};{ let ++x;yes $w|head -$[5575/x];}|shuf

分析

zipf斜率已调整为笔直。使用Excel绘制对数刻度:

老师应注意zipf斜率= -1.000764。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.