有没有一种程序化的方式来阐述raku中的“半风”?

我有这个工作:

my %pnt = %( cardinal => <N E S W>, 
             ordinal  => <N NE E SE S SW W NW>,
             half-winds => <N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW>,
            );

我认为有可能以编程方式创建半风阵列。

然而,我可怜的尝试似乎更加冗长:

my @cards = <N E S W>; 
my @odds  = <NE SE SW NW>;
my @ords  = ( @cards Z @odds ).flat; 
my @mids  = ( ( @cards Z~ @odds ) Z ( @cards.rotate(1) Z~ @odds ) ).flat;
my @halfs = ( @ords Z @mids ).flat; 

say @cards; #[N E S W]
say @ords;  #[N NE E SE S SW W NW] 
say @mids;  #[NNE ENE ESE SSE SSW WSW WNW NNW]
say @halfs; #[N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW]

有没有更好/更简洁的替代方案?

即。https://en.wikipedia.org/wiki/Points_of_the_compass
- 四分之一风的奖励积分!

回答

FWIW,在这种情况下,我会考虑代码的可读性,我认为您的原始代码是您可以获得的最易读的代码。

但是如果你想获得算法,我会@halfs使用一个序列来使用数组切片:

my @halfs = <N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW>;
my @mids  = @halfs[1,3...*];
my @ords  = @halfs[0,2...*];
my @cards = @halfs[0,4...*];

say @cards; #[N E S W]
say @ords;  #[N NE E SE S SW W NW] 
say @mids;  #[NNE ENE ESE SSE SSW WSW WNW NNW]
say @halfs; #[N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW]

将四分之一风留给读者作为练习,但基本上那将使用四分之一风作为基础,并以类似的方式解决这个问题。


回答

假设我们手头有主风:

my @principals = <N NE E SE S SW W NW>;

然后我们可以遵循维基百科的定义:

每个半风的名称是通过将主风的名称组合到任一侧来构造的

这意味着我们要以重叠的成对获取主风,这rotor可以做得相当巧妙:

say @principals.rotor(2 => -1);

这给了我们:

((N NE) (NE E) (E SE) (SE S) (S SW) (SW W) (W NW))

遗憾的是,它有一个问题,因为它错过了(NW, N). 好的,我们可以N再次包含,以牺牲一点美感为代价:

say @principals[*,0].flat.rotor(2 => -1)

给予:

((N NE) (NE E) (E SE) (SE S) (S SW) (SW W) (W NW) (NW N))

如果我们加入他们:

say @principals[*,0].flat.rotor(2 => -1).map(*.join)

我们得到:

(NNE NEE ESE SES SSW SWW WNW NWN)

这还不正确,因为文章接下来要说的是:

主风先来,间风次之

主要的风是一个字符的,可以通过排序来修复:

say @principals[*,0].flat.rotor(2 => -1).map(*.sort(*.chars).join)

最终看起来是正确的:

(NNE ENE ESE SSE SSW WSW WNW NNW)

除了半风位于主风之间,这可以通过压缩它们并压平结果来解决:

say flat @principals Z @principals[*,0].flat.rotor(2 => -1).map(*.sort(*.chars).join)

最后给我们:

(N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW)

如果我们希望它更短,重复提到的@principals可以用一个given

say flat $_ Z .[*,0].flat.rotor(2 => -1).map(*.sort(*.chars).join) given @principals

.join可刚刚成为列表字串:

say flat $_ Z .[*,0].flat.rotor(2 => -1).map(~*.sort(*.chars)) given @principals:

并且可以使用|滑动运算符替换内部扁平化:

say flat $_ Z (|$_,.[0]).rotor(2 => -1).map(~*.sort(*.chars)) given @principals;

这仍然比首先列出它们要长,这就是我可能会做的,但无论如何尝试击败它很有趣......


回答

TL;DR无缘无故,这个 nanswer只是为了加分。

my quadrant = <N NbE NNE NEbN NE NEbE ENE EbN E>;

my @quarts = |quadrant,
             |quadrant.reverse.map( *.trans: 'NE'=>'SE'),
             |quadrant       .map( *.trans: 'NE'=>'SW'),
             |quadrant.reverse.map( *.trans: 'NE'=>'NW');

@quarts .=unique .batch(8) .map: *.say;

# (N NbE NNE NEbN NE NEbE ENE EbN)
# (E EbS ESE SEbE SE SEbS SSE SbE)
# (S SbW SSW SWbS SW SWbW WSW WbS)
# (W WbN WNW NWbW NW NWbN NNW NbW)

也许我得到了一些奖励积分来解释上述内容:

  • 前缀| “滑动”其右侧的值;在四个象限中的每个象限上使用它的净效果是结果列表包含 32 个元素而不是 4 个。

  • .reverse 反转列表,对应于风点符号在 NE/SW 和 SE/NW 之间反转的方式。

  • .map(...) 将函数或 lambda 应用于其调用者列表中的每个元素。

  • *.trans: 'NE'=>'SE'是一个将每个N字符音译为S和每个E到的 lambda E。第E一次音译有多余的部分,因为它感觉比丢弃它更清晰;我也可以*.trans: 'NE'=>'NE'为第一象限添加,但感觉不太清楚。注意。我使用trans它是因为它简洁,但subst总是可以做同样的事情trans,即使需要更多的行,而且在 Rakudo 2020.12subst中,几乎在所有情况下都快 5 到 10 倍。

  • |quadrant .map...是一个“unspace”的方式来指示编译器,它应该解析代码,如果斜线和空白是不存在。没有它,|quadrant如同它的操作数一样。unspace 使其将整个quadrant.map( *.trans: 'NE'=>'SW')表达式作为其操作数。(在这个答案的原始版本中,我的代码是错误的,因为我在.map没有 unspace的情况下排列了。)

  • .=.=unique适用的方法,然后分配结果返回给调用者的,在地方变异它。

  • unique删除列表中重复的任何元素。没有它,四个基点 ( <N E S W>)就会重复。

  • .batch(8) 将这些点分成 8 个一组,对应于准备漂亮打印的四个象限。

奖励积分

这个答案的其余部分只是我无耻的奖励积分清除的理由。

从你的问题:

四分之一风的奖励积分!

来自莉兹的回答:

将四分之一风留给读者作为练习

“四分之一风”的32分

正如 Liz 所指出的,一个包含她的风四分之一风的简单超集解决方案只需要:

使用四分之一风作为基础,并以类似的方式解决它

换句话说,做四分之一风奖金练习可以只需要写一些简单、容易理解和合理维护的东西,即写出四分之一风列表中的 32 分,就像 Liz 对半风的 16 分所做的那样。(但那样我就得不到加分了。)

将此扩展到令人困惑的半点(64 点)和四分之一点(128),为它们做的明智之举也是用手将它们写出来,并使用 Unicode 分数字符完成,任何支持 Unicode 的 PL源代码和“引用词”之类的功能(例如 Raku)变得微不足道。我敢肯定,如果您这样做,任何阅读您代码的人都会感谢您保持简单。

但我想找点乐子,坚持你的程序化主题,并尝试寻找一些“奖励积分”。因此,我一开始的代码。


我将创建更多不必要的复杂的、复杂的、繁琐的半点/四分之一点计算结构(完全支持别名和世界各地为这些更精细的圆规使用的不同约定)作为读者练习......


以上是有没有一种程序化的方式来阐述raku中的“半风”?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>