将网格划分为三角形


18

目标

挑战的目标是产生一个函数,n该函数计算将n X 1网格划分为三角形的方式的数量,其中三角形的所有顶点均位于网格点上。

例如,有14种方法来划分2 x 1网格,因此f(2) = 14通过以下分区分区2 x 1 ,其中分区分别具有2、2、2、2、4和2个不同的方向。

计分

这是,因此最短的代码获胜。


10
一些额外的测试用例将是有益的,因此我们可以验证我们提交的内容是否正确。
AdmBorkBork

8
您可能要指定非退化三角形。
Arnauld

1
我已经对OEIS序列A051708进行了编辑,以反映这种解释。
彼得·卡吉

Answers:


2

05AB1E,13 个字节

·LÉœÙεÅγo;P}O

@Bubbler的Jelly答案端口。

由于内置置换,因此非常慢。

在线尝试验证前四个输入

说明:

·                # Double the (implicit) input
 L               # Create a list in the range [1, doubled_input]
  É              # Check for each if they're odd (1 if truthy, 0 is falsey)
                 # We now have a list of n 0s and n 1s (n being the input)
   œ             # Get all permutations of that list
    Ù            # Only leave the unique permutations
     ε     }     # Map each permutation to:
      Åγ         #  Run-length encode the current value (short for `γ€g`)
        o        #  Take 2 to the power for each
         ;       #  Halve each
          P      #  Take the product of the mapped permutation
            O    # Sum all mapped values together (and output implicitly)

19

Haskell60 55 54 52字节

经过大量的绘图和编程示例后,我发现这与车队的问题相同:

在一个ñ+1个×ñ+1个棋盘,一车从去多少种方法在那里00ññ通过只向右移动+1个0或高达+01个

基本上,您具有1个×ñ网格的顶行和底行。现在,您必须填写非水平行。每个三角形必须有两条非水平线。它的侧面之一是顶线还是底线的一部分,对应于您在车队问题中所走的方向和长度。这是OEIS A051708。为了说明这种对应关系,请考虑以下示例。在此,顶线对应于上移,而底线对应于右移。

感谢@PeterTaylor提供-6个字节,以及@PostLeftGarfHunter提供-2个字节!

b 0=1
b 1=2
b n=div((10*n-6)*b(n-1)-9*(n-2)*b(n-2))n

在线尝试!


我通过搜索前几个值找到了OEIS序列。为什么它匹配很好的解释。您是否要对其进行编辑以添加对此替代组合解释的评论?如果没有,我可能会。
彼得·泰勒

顺便说一句,您需要调整索引编制,因为此处的正确答案是A051708(n+1)。因此,我发布了第一个正确答案:-P
彼得·泰勒

我认为通过使具有顶部和底部边缘的三角形对应于向上或向右移动,车队移动贴图可以映射到三角形?
尼尔

@PeterTaylor Damn,感谢您指出我的错误:)
瑕疵的

5
@Neil我添加了图形说明。
瑕疵

8

Haskell,42个字节

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

在线尝试!

一个相当直接的实现,它重复两个变量。

这是我们如何获得此解决方案的方法。从实现直接递归公式的代码开始:

54字节

0%0=1
a%b=sum$map(a%)[0..b-1]++map(b%)[0..a-1]
f n=n%n

在线尝试!

使用frank的车队移动解释a%b是将车队从(a,b)转到的路径数(0,0),仅使用移动减少坐标。第一步减少a或减少b,另一步保持不变,因此是递归公式。

49个字节

a?b=sum$map(a%)[0..b-1]
0%0=1
a%b=a?b+b?a
f n=n%n

在线尝试!

我们可以map(a%)[0..b-1]++map(b%)[0..a-1]通过注意两个半部分相同ab互换来避免重复。辅助呼叫a?b计算第一个移动减少的路径a,因此b?a计算第一个移动减少的路径b。这些通常是不同的,它们增加了a%b

的总和a?b也可以写成列表理解a?b=sum[a%i|i<-[0..b-1]]

42字节

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

在线尝试!

最后,我们摆脱%,只是写在条款递归?通过更换a%ia?i+i?a在递归调用。

新的基本情况使它的?输出?是49字节版本的两倍,因为有了0?0=1,我们就可以了0%0=0?0+0?0=2。这样就可以使用define f n=n?n而不需要我们其他需要做的一半。


您的49字节解决方案使用与我的答案相同的递归,但是我还没有弄清楚42字节的解决方案。一个解释会很好。
彼得·泰勒

我想我在较早的程序中使用了相同的方法:这个想法是通过生成从右到左的非水平线来生成(或计算)所有分区的。您从垂直线开始。然后您可以递归:取上一行的末端节点之一,并将其​​连接到相对的水平线上的一个节点,该节点距离该行上所有先前节点的左侧更远。
瑕疵的

操作员a%b使用0,1,...,a顶行的节点和0,1,..,b底端的节点对分区数进行计数。如果底部节点已在使用中,则操作员a?b计算从顶部节点添加新行的方式。(您可以连接到所有的节点,但你必须改乘每个那些。)aba[0,1,...,b-1]
flawr

@flawr,这是49字节的字节,据我了解。这是?我不知道的42字节字节,而特别奇怪的是它不是对称的。
彼得·泰勒

@PeterTaylor抱歉,我以某种方式混淆了两种解决方案。我认为我们可以很容易地将两种解决方案相互转换:第一步,我们可以map...用列表理解代替;第二步,我们只需插入的定义%a?b=sum$map(a%)[0..b-1], a%b=a?b+b?a a?b=sum[a%i|i<-[0..b-1]], a%b=a?b+b?a a?b=sum[a?i+i?a|i<-[0..b-1]]
瑕疵的

7

CJam(24字节)

{2,*e!{e`0f=:(1b2\#}%1b}

在线演示

这使用了Bubblern0和n1的排列求和的方法

解剖

{         e# Define a block
  2,*     e#   Given input n, create an array of n 0s and n 1s
  e!      e#   Generate all permutations of that array
  {       e#   Map:
    e`    e#     Run-length encode
    0f=:( e#     Extract just the lengths and decrement them
    1b    e#     Sum
    2\#   e#     Raise 2 to the power of that sum
  }%
  1b      e#  Sum the mapped values
}

替代方法(28字节)

{_1aa{_2$,f{j}@@,f{j}+1b}2j}

在线演示

解剖

三角形都有一个水平边和两个连接水平线的边。用两个x坐标的元组标记非水平边缘,然后按字典顺序排序。然后,第一个边缘为(0,0),最后一个边缘为(n,n),并且两个连续的边缘恰好在两个位置之一不同。这实现了一个简单的递归,我已经使用记忆化的递归运算符实现了它j

{            e# Define a block
  _          e#   Duplicate the argument to get n n
  1aa        e#   Base case for recursion: 0 0 => 1
  {          e#   Recursive body taking args a b
    _2$,f{j} e#     Recurse on 0 b up to a-1 b
    @@,f{j}  e#     Recurse on a 0 up to a b-1
    +1b      e#     Combine and sum
  }2j        e#   Memoised recursion with 2 args
}

注意

这不是我第一次希望fj获得CJam支持。在这里它也将分数降低到24个字节。也许我应该尝试写一个补丁...


耶,我以10秒打不过你,我不认为我曾经有近 :)
flawr

@flawr,我确实在写解剖之前考虑过张贴,但是我认为我有时间将其快速淘汰。然后,我看到“新答案”,因此我删除了部分写作的解剖,发布并进行了编辑。
彼得·泰勒

1
感谢-5字节btw:D
瑕疵的

4

果冻15 14字节

Ø.xŒ!QŒɠ€’§2*S

在线尝试!

-1个字节,基于Peter Taylor的评论。

直接使用fuerr的插图,而不使用结果公式。

怎么运行的

Ø.xŒ!QŒɠ€’§2*S    Main link (monad). Input: positive integer N.
Ø.x               Make an array containing N zeros and ones
   Œ!Q            All unique permutations
      Œɠ€         Run-length encode on each permutation
         ’§       Decrement and sum each
           2*S    Raise to power of 2 and sum

在正方形网格上走所有可能的路线。作为车队,在一个方向上移动L个单位的方式为2**(L-1)。将其应用到每条路线,并汇总遍历每条路线的方式数量。


好的方法。当我将其移植到CJam时,缩短长度,求和然后将2增加到总和就更短了。而不是将长度提高2,减半,然后相乘。不知道它是否可以为您节省一个字节。
彼得·泰勒

3

木炭44 31字节

划掉44仍然是常规44

F⊕θ«≔⟦⟧ηF⊕θ⊞ηΣ∨⁺ηEυ§λκ¹⊞υη»I⊟⊟υ

在线尝试!说明:通过计算将相对边长的梯形划分为m,n全部位于整数偏移量上的三角形的方式来工作。这只是n问题中矩形大小的一般情况。递归给出分区的数目,作为所有边m,0..n-1和的分区数目之和n,0..m-1。这等效于车队的普遍问题OEIS A035002。该代码简单地计算工作的分区数量,0,0直到n,n使用之前计算的值为止。

F⊕θ«

在行上循环0..n

≔⟦⟧η

从空行开始。

F⊕θ

循环浏览行中的列0..n

⊞ηΣ∨⁺ηEυ§λκ¹

将当前行和当前行中前几行中的值相加,然后将总和添加到当前行中。但是,如果根本没有值,则用替代值1代替总和。

⊞υη»

将完成的行添加到到目前为止的行列表中。

I⊟⊟υ

输出计算出的最终值。



2

Pari / GP,43个字节

根据OEIS,此序列的生成函数为

1个21个-X1个-9X+1个

n->Vec(sqrt((1-x)/(1-9*x)+O(x^n++))+1)[n]/2

在线尝试!


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.